mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
init stack cli project-id and publishable-client-key args (#888)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Add CLI options for project ID and publishable client key, update initialization process, and modify documentation to reflect changes. > > - **CLI Options**: > - Added `--project-id` and `--publishable-client-key` options to `index.ts` for CLI setup. > - **Initialization**: > - Updated `writeEnvVars()` in `index.ts` to include project ID and publishable client key in `.env.local`. > - Modified `writeStackAppFile()` in `index.ts` to handle new CLI options. > - **Documentation**: > - Updated references from `stack.ts` to `stack/client.ts` and `stack/server.ts` in multiple `.mdx` files. > - Added examples for using project ID and publishable client key in `setup.mdx` and `example-pages.mdx`. > - **Testing**: > - Added `test-run-keys-next` and `test-run-keys-js` scripts in `package.json` for testing new CLI options. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup> forb204910ebd. You can [customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this summary. It will automatically update as commits are pushed.</sup> ---- <!-- ELLIPSIS_HIDDEN --> <!-- RECURSEML_SUMMARY:START --> ## Review by RecurseML _🔍 Review performed on [bd14f6b..92c332a](bd14f6be6a...92c332ad3f)_ ✨ No bugs found, your code is sparkling clean <details> <summary>✅ Files analyzed, no issues (2)</summary> • `packages/init-stack/src/index.ts` • `apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client.tsx` </details> <details> <summary>⏭️ Files skipped (trigger manually) (1)</summary> | Locations | Trigger Analysis | |-----------|------------------| `packages/init-stack/package.json` | [ </details> [](https://discord.gg/n3SsVDAW6U) <!-- RECURSEML_SUMMARY:END --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - Init tool accepts project ID and publishable client key; generated projects include those values in client/server outputs and env hints. - Next.js projects now generate both client and server app artifacts using a standardized client/server layout. - UI - Removed the vertical divider on the New Project page for a cleaner preview/form layout. - Documentation - Updated docs and examples to reference the new client/server file split. - Chores - Added key-based test-run scripts for Next.js and JS. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
5da45d8520
commit
0c4958afb4
@ -146,7 +146,6 @@ export default function PageClient() {
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
<Separator orientation="vertical" />
|
||||
|
||||
<div className="w-1/2 self-stretch py-4 px-4 lg:px-20 bg-zinc-300 dark:bg-zinc-800 hidden md:flex items-center">
|
||||
<div className="w-full">
|
||||
|
||||
@ -114,10 +114,10 @@ export default function SetupPage(props: { toMetrics: () => void }) {
|
||||
},
|
||||
{
|
||||
step: 4,
|
||||
title: "Create stack.ts file",
|
||||
title: "Create stack/client.ts file",
|
||||
content: <>
|
||||
<Typography>
|
||||
Create a new file called <InlineCode>stack.ts</InlineCode> and add the following code. Here we use react-router-dom as an example.
|
||||
Create a new file called <InlineCode>stack/client.ts</InlineCode> and add the following code. Here we use react-router-dom as an example.
|
||||
</Typography>
|
||||
<CodeBlock
|
||||
language="tsx"
|
||||
@ -135,7 +135,7 @@ export default function SetupPage(props: { toMetrics: () => void }) {
|
||||
}
|
||||
});
|
||||
`}
|
||||
title="stack.ts"
|
||||
title="stack/client.ts"
|
||||
icon="code"
|
||||
/>
|
||||
</>
|
||||
@ -154,7 +154,7 @@ export default function SetupPage(props: { toMetrics: () => void }) {
|
||||
import { StackHandler, StackProvider, StackTheme } from "@stackframe/react";
|
||||
import { Suspense } from "react";
|
||||
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
function HandlerRoutes() {
|
||||
const location = useLocation();
|
||||
|
||||
2
docs/templates/concepts/oauth.mdx
vendored
2
docs/templates/concepts/oauth.mdx
vendored
@ -91,7 +91,7 @@ To avoid showing the authorization page twice, you can already request scopes du
|
||||
|
||||
To do this, edit the `oauthScopesOnSignIn` setting of your `stackServerApp`:
|
||||
|
||||
```jsx title='stack.ts'
|
||||
```jsx title='stack/server.ts'
|
||||
export const stackServerApp = new StackServerApp({
|
||||
// ...your other settings...
|
||||
oauthScopesOnSignIn: {
|
||||
|
||||
@ -23,9 +23,9 @@ export default function CustomSignInPage() {
|
||||
}
|
||||
```
|
||||
|
||||
Then you can instruct the Stack app in `stack.ts` to use your custom sign in page:
|
||||
Then you can instruct the Stack app in `stack/server.ts` to use your custom sign in page:
|
||||
|
||||
```tsx title="stack.ts"
|
||||
```tsx title="stack/server.ts"
|
||||
export const stackServerApp = new StackServerApp({
|
||||
// ...
|
||||
// add these three lines
|
||||
@ -67,9 +67,9 @@ export default function CustomOAuthSignIn() {
|
||||
}
|
||||
```
|
||||
|
||||
Again, edit the Stack app in `stack.ts` to use your custom sign in page:
|
||||
Again, edit the Stack app in `stack/server.ts` to use your custom sign in page:
|
||||
|
||||
```tsx title="stack.ts"
|
||||
```tsx title="stack/server.ts"
|
||||
export const stackServerApp = new StackServerApp({
|
||||
// ...
|
||||
// add these three lines
|
||||
|
||||
@ -22,7 +22,7 @@ export default function DefaultForgotPassword() {
|
||||
To integrate the forgot password page with your application's routing:
|
||||
|
||||
1. Create a route for your forgot password page (e.g., `/forgot-password`)
|
||||
2. Configure Stack Auth to use your custom route in your `stack.ts` file:
|
||||
2. Configure Stack Auth to use your custom route in your `stack/server.ts` file:
|
||||
|
||||
```tsx
|
||||
export const stackServerApp = new StackServerApp({
|
||||
|
||||
@ -23,7 +23,7 @@ To integrate the password reset page with your application's routing:
|
||||
|
||||
1. Create a route handler that extracts the reset code from the URL (e.g., `/reset-password?code=xyz123`)
|
||||
2. Pass the code to your password reset component
|
||||
3. Configure Stack Auth to use your custom route in your `stack.ts` file:
|
||||
3. Configure Stack Auth to use your custom route in your `stack/server.ts` file:
|
||||
|
||||
```tsx
|
||||
export const stackServerApp = new StackServerApp({
|
||||
|
||||
12
docs/templates/getting-started/example-pages.mdx
vendored
12
docs/templates/getting-started/example-pages.mdx
vendored
@ -7,7 +7,7 @@ This guide demonstrates how to integrate Stack Auth with Vite. The same principl
|
||||
|
||||
### Initialize the app
|
||||
|
||||
```typescript title="stack.ts"
|
||||
```typescript title="stack/client.ts"
|
||||
import { StackClientApp } from "@stackframe/js";
|
||||
|
||||
// Add type declaration for Vite's import.meta.env
|
||||
@ -76,7 +76,7 @@ export const stackClientApp = new StackClientApp({
|
||||
|
||||
<TabsContent value="script">
|
||||
```typescript
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
const updateUIState = (user: any | null) => {
|
||||
const authOptions = document.getElementById("authOptions");
|
||||
@ -148,7 +148,7 @@ export const stackClientApp = new StackClientApp({
|
||||
|
||||
<TabsContent value="script">
|
||||
```typescript
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
// Check if user is already signed in
|
||||
stackClientApp.getUser().then((user) => {
|
||||
@ -253,7 +253,7 @@ export const stackClientApp = new StackClientApp({
|
||||
|
||||
<TabsContent value="script">
|
||||
```typescript
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
// Check if user is already signed in
|
||||
stackClientApp.getUser().then((user) => {
|
||||
@ -335,7 +335,7 @@ export const stackClientApp = new StackClientApp({
|
||||
|
||||
<TabsContent value="script">
|
||||
```typescript
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
// Check if user is already signed in
|
||||
stackClientApp.getUser().then((user) => {
|
||||
@ -413,7 +413,7 @@ export const stackClientApp = new StackClientApp({
|
||||
|
||||
<TabsContent value="script">
|
||||
```typescript
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
// Check if user is already signed in
|
||||
stackClientApp.getUser().then((user) => {
|
||||
|
||||
17
docs/templates/getting-started/setup.mdx
vendored
17
docs/templates/getting-started/setup.mdx
vendored
@ -50,7 +50,8 @@ We recommend using our **setup wizard** for a seamless installation experience.
|
||||
- `app/handler/[...stack]/page.tsx`: This file contains the default pages for sign-in, sign-out, account settings, and more. If you prefer, later you will learn how to [use custom pages](../customization/custom-pages.mdx) instead.
|
||||
- `app/layout.tsx`: The layout file was updated to wrap the entire body with `StackProvider` and `StackTheme`.
|
||||
- `app/loading.tsx`: If not yet found, Stack automatically adds a Suspense boundary to your app. This is shown to the user while Stack's async hooks, like `useUser`, are loading.
|
||||
- `stack.ts`: This file contains the `stackServerApp` which you can use to access Stack from Server Components, Server Actions, API routes, and middleware.
|
||||
- `stack/server.ts`: This file contains the `stackServerApp` which you can use to access Stack from Server Components, Server Actions, API routes, and middleware.
|
||||
- `stack/client.ts`: This file contains the `stackClientApp` which you can use to access Stack from Client Components
|
||||
</Steps>
|
||||
</TabsContent>
|
||||
|
||||
@ -82,11 +83,11 @@ We recommend using our **setup wizard** for a seamless installation experience.
|
||||
```
|
||||
|
||||
<Step>
|
||||
### Create `stack.ts` file
|
||||
### Create `stack/server.ts` file
|
||||
</Step>
|
||||
Create a new file `stack.ts` in your root directory and fill it with the following:
|
||||
Create a new file `stack/server.ts` in your root directory and fill it with the following:
|
||||
|
||||
```tsx title="stack.ts"
|
||||
```tsx title="stack/server.ts"
|
||||
import "server-only";
|
||||
import { StackServerApp } from "@stackframe/stack";
|
||||
|
||||
@ -202,11 +203,11 @@ Before getting started, make sure you have a [React project](https://react.dev/l
|
||||
If you haven't already, [register a new account on Stack](https://app.stack-auth.com/projects), create a project in the dashboard, create a new API key from the left sidebar, and copy the project ID, publishable client key, and secret server key into a new file called `.env.local` in the root of your React project:
|
||||
|
||||
<Step>
|
||||
### Create `stack.ts` file
|
||||
### Create `stack/client.ts` file
|
||||
</Step>
|
||||
Create a new file `stack.ts` in your root directory and fill it with the following Stack app initialization code:
|
||||
Create a new file `stack/client.ts` in your root directory and fill it with the following Stack app initialization code:
|
||||
|
||||
```tsx title="stack.ts"
|
||||
```tsx title="stack/client.ts"
|
||||
import { StackClientApp } from "@stackframe/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@ -231,7 +232,7 @@ Before getting started, make sure you have a [React project](https://react.dev/l
|
||||
import { StackHandler, StackProvider, StackTheme } from "@stackframe/react";
|
||||
import { Suspense } from "react";
|
||||
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
|
||||
import { stackClientApp } from "./stack";
|
||||
import { stackClientApp } from "./stack/client";
|
||||
|
||||
function HandlerRoutes() {
|
||||
const location = useLocation();
|
||||
|
||||
2
docs/templates/getting-started/users.mdx
vendored
2
docs/templates/getting-started/users.mdx
vendored
@ -30,7 +30,7 @@ Sometimes, you want to retrieve the user only if they're signed in, and redirect
|
||||
|
||||
## Server Component basics
|
||||
|
||||
Since `useUser()` is a stateful hook, you can't use it on server components. Instead, you can import `stackServerApp` from `stack.ts` and call `getUser()`:
|
||||
Since `useUser()` is a stateful hook, you can't use it on server components. Instead, you can import `stackServerApp` from `stack/client.ts` and call `getUser()`:
|
||||
|
||||
```tsx title="my-server-component.tsx"
|
||||
import { stackServerApp } from "@/stack";
|
||||
|
||||
@ -24,7 +24,9 @@
|
||||
"test-run-js:manual": "rimraf test-run-output && npx -y sv create test-run-output --no-install && pnpm run init-stack:local test-run-output",
|
||||
"test-run-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --client --npm",
|
||||
"test-run-next:manual": "rimraf test-run-output && npx -y create-next-app@latest test-run-output && pnpm run init-stack:local test-run-output",
|
||||
"test-run-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output"
|
||||
"test-run-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output",
|
||||
"test-run-keys-next": "rimraf test-run-output && npx -y create-next-app@latest test-run-output --app --ts --no-src-dir --tailwind --use-npm --eslint --import-alias '##@#/*' --turbopack && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --project-id my-project-id --publishable-client-key my-publishable-client-key",
|
||||
"test-run-keys-js": "rimraf test-run-output && npx -y sv create test-run-output --template minimal --types ts --no-add-ons --no-install && STACK_DISABLE_INTERACTIVE=true pnpm run init-stack:local test-run-output --js --client --npm --project-id my-project-id --publishable-client-key my-publishable-client-key"
|
||||
},
|
||||
"files": [
|
||||
"README.md",
|
||||
|
||||
@ -42,6 +42,8 @@ program
|
||||
.option("--bun", "Use bun as package manager")
|
||||
.option("--client", "Initialize client-side only")
|
||||
.option("--server", "Initialize server-side only")
|
||||
.option("--project-id <project-id>", "Project ID to use in setup")
|
||||
.option("--publishable-client-key <publishable-client-key>", "Publishable client key to use in setup")
|
||||
.option("--no-browser", "Don't open browser for environment variable setup")
|
||||
.addHelpText('after', `
|
||||
For more information, please visit https://docs.stack-auth.com/getting-started/setup`);
|
||||
@ -58,6 +60,8 @@ const typeFromArgs: string | undefined = options.js ? "js" : options.next ? "nex
|
||||
const packageManagerFromArgs: string | undefined = options.npm ? "npm" : options.yarn ? "yarn" : options.pnpm ? "pnpm" : options.bun ? "bun" : undefined;
|
||||
const isClient: boolean = options.client || false;
|
||||
const isServer: boolean = options.server || false;
|
||||
const projectIdFromArgs: string | undefined = options.projectId;
|
||||
const publishableClientKeyFromArgs: string | undefined = options.publishableClientKey;
|
||||
// Commander negates the boolean options with prefix `--no-`
|
||||
// so `--no-browser` becomes `browser: false`
|
||||
const noBrowser: boolean = !options.browser;
|
||||
@ -195,6 +199,7 @@ async function main(): Promise<void> {
|
||||
if (type === "next") {
|
||||
const projectInfo = await Steps.getNextProjectInfo({ packageJson: projectPackageJson });
|
||||
await Steps.updateNextLayoutFile(projectInfo);
|
||||
await Steps.writeStackAppFile(projectInfo, "client");
|
||||
await Steps.writeStackAppFile(projectInfo, "server");
|
||||
await Steps.writeNextHandlerFile(projectInfo);
|
||||
await Steps.writeNextLoadingFile(projectInfo);
|
||||
@ -511,13 +516,13 @@ const Steps = {
|
||||
"# 1. Go to https://app.stack-auth.com\n" +
|
||||
"# 2. Create a new project\n" +
|
||||
"# 3. Copy the keys below\n" +
|
||||
"NEXT_PUBLIC_STACK_PROJECT_ID=\n" +
|
||||
"NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=\n" +
|
||||
`NEXT_PUBLIC_STACK_PROJECT_ID="${projectIdFromArgs ?? ""}"\n` +
|
||||
`NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY="${publishableClientKeyFromArgs ?? ""}"\n` +
|
||||
"STACK_SECRET_SERVER_KEY=\n"
|
||||
: "# Stack Auth keys\n" +
|
||||
"# Get these variables by creating a project on https://app.stack-auth.com.\n" +
|
||||
"NEXT_PUBLIC_STACK_PROJECT_ID=\n" +
|
||||
"NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=\n" +
|
||||
`NEXT_PUBLIC_STACK_PROJECT_ID="${projectIdFromArgs ?? ""}"\n` +
|
||||
`NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY="${publishableClientKeyFromArgs ?? ""}"\n` +
|
||||
"STACK_SECRET_SERVER_KEY=\n";
|
||||
|
||||
laterWriteFile(envLocalPath, envContent);
|
||||
@ -567,18 +572,14 @@ const Steps = {
|
||||
return res;
|
||||
},
|
||||
|
||||
async writeStackAppFile({ type, srcPath, defaultExtension, indentation }: StackAppFileOptions, clientOrServer: string): Promise<StackAppFileResult> {
|
||||
async writeStackAppFile({ type, srcPath, defaultExtension, indentation }: StackAppFileOptions, clientOrServer: "server" | "client"): Promise<StackAppFileResult> {
|
||||
const packageName = await Steps.getStackPackageName(type);
|
||||
|
||||
const clientOrServerCap = {
|
||||
client: "Client",
|
||||
server: "Server",
|
||||
}[clientOrServer] ?? throwErr("unknown clientOrServer " + clientOrServer);
|
||||
|
||||
const relativeStackAppPath = {
|
||||
js: `stack/${clientOrServer}`,
|
||||
next: "stack",
|
||||
}[type] ?? throwErr("unknown type");
|
||||
}[clientOrServer as string] ?? throwErr("unknown clientOrServer " + clientOrServer);
|
||||
const relativeStackAppPath = `stack/${clientOrServer}`;
|
||||
|
||||
const stackAppPathWithoutExtension = path.join(srcPath, relativeStackAppPath);
|
||||
const stackAppFileExtension =
|
||||
@ -589,24 +590,30 @@ const Steps = {
|
||||
if (stackAppContent) {
|
||||
if (!stackAppContent.includes("@stackframe/")) {
|
||||
throw new UserError(
|
||||
`A file at the path ${stackAppPath} already exists. Stack uses the stack.ts file to initialize the Stack SDK. Please remove the existing file and try again.`
|
||||
`A file at the path ${stackAppPath} already exists. Stack uses the stack/${clientOrServer}.ts file to initialize the Stack SDK. Please remove the existing file and try again.`
|
||||
);
|
||||
}
|
||||
throw new UserError(
|
||||
`It seems that you already installed Stack in this project.`
|
||||
);
|
||||
}
|
||||
|
||||
const publishableClientKeyWrite = clientOrServer === "server"
|
||||
? `process.env.STACK_PUBLISHABLE_CLIENT_KEY ${publishableClientKeyFromArgs ? `|| '${publishableClientKeyFromArgs}'` : ""}`
|
||||
: `'${publishableClientKeyFromArgs ?? 'INSERT_YOUR_PUBLISHABLE_CLIENT_KEY_HERE'}'`;
|
||||
|
||||
laterWriteFileIfNotExists(
|
||||
stackAppPath,
|
||||
`
|
||||
${type === "next" ? `import "server-only";` : ""}
|
||||
${type === "next" && clientOrServer === "server" ? `import "server-only";` : ""}
|
||||
|
||||
import { Stack${clientOrServerCap}App } from ${JSON.stringify(packageName)};
|
||||
|
||||
export const stack${clientOrServerCap}App = new Stack${clientOrServerCap}App({
|
||||
${indentation}tokenStore: ${type === "next" ? '"nextjs-cookie"' : (clientOrServer === "client" ? '"cookie"' : '"memory"')},${
|
||||
type === "js" ? `\n\n${indentation}// get your Stack Auth API keys from https://app.stack-auth.com${clientOrServer === "client" ? ` and store them in a safe place (eg. environment variables)` : ""}` : ""}${
|
||||
type === "js" ? `\n${indentation}publishableClientKey: ${clientOrServer === "server" ? 'process.env.STACK_PUBLISHABLE_CLIENT_KEY' : 'INSERT_YOUR_PUBLISHABLE_CLIENT_KEY_HERE'},` : ""}${
|
||||
type === "js" && projectIdFromArgs ? `\n${indentation}projectId: '${projectIdFromArgs}',` : ""}${
|
||||
type === "js" ? `\n${indentation}publishableClientKey: ${publishableClientKeyWrite},` : ""}${
|
||||
type === "js" && clientOrServer === "server" ? `\n${indentation}secretServerKey: process.env.STACK_SECRET_SERVER_KEY,` : ""}
|
||||
});
|
||||
`.trim() + "\n"
|
||||
@ -630,7 +637,7 @@ type === "js" && clientOrServer === "server" ? `\n${indentation}secretServerKey:
|
||||
}
|
||||
laterWriteFileIfNotExists(
|
||||
handlerPath,
|
||||
`import { StackHandler } from "@stackframe/stack";\nimport { stackServerApp } from "../../../stack";\n\nexport default function Handler(props${
|
||||
`import { StackHandler } from "@stackframe/stack";\nimport { stackServerApp } from "../../../stack/server";\n\nexport default function Handler(props${
|
||||
handlerFileExtension.includes("ts") ? ": unknown" : ""
|
||||
}) {\n${projectInfo.indentation}return <StackHandler fullPage app={stackServerApp} routeProps={props} />;\n}\n`
|
||||
);
|
||||
@ -684,7 +691,7 @@ type === "js" && clientOrServer === "server" ? `\n${indentation}secretServerKey:
|
||||
}
|
||||
},
|
||||
|
||||
async getServerOrClientOrBoth(): Promise<string[]> {
|
||||
async getServerOrClientOrBoth(): Promise<Array<"server" | "client">> {
|
||||
if (isClient && isServer) return ["server", "client"];
|
||||
if (isServer) return ["server"];
|
||||
if (isClient) return ["client"];
|
||||
@ -742,7 +749,7 @@ async function getUpdatedLayout(originalLayout: string): Promise<LayoutResult |
|
||||
const importInsertLocationM1 =
|
||||
firstImportLocationM1 ?? (hasStringAsFirstLine ? layout.indexOf("\n") : -1);
|
||||
const importInsertLocation = importInsertLocationM1 + 1;
|
||||
const importStatement = `import { StackProvider, StackTheme } from "@stackframe/stack";\nimport { stackServerApp } from "../stack";\n`;
|
||||
const importStatement = `import { StackProvider, StackTheme } from "@stackframe/stack";\nimport { stackServerApp } from "../stack/server";\n`;
|
||||
layout =
|
||||
layout.slice(0, importInsertLocation) +
|
||||
importStatement +
|
||||
|
||||
Loading…
Reference in New Issue
Block a user