@stackframe/init-stack 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/index.mjs +53 -23
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @stackframe/init-stack
2
2
 
3
+ ## 1.0.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Improve setup flow
8
+
3
9
  ## 1.0.7
4
10
 
5
11
  ### Patch Changes
package/index.mjs CHANGED
@@ -8,33 +8,42 @@ import open from 'open';
8
8
 
9
9
  const jsLikeFileExtensions = ['mtsx', 'ctsx', 'tsx', 'mts', 'cts', 'ts', 'mjsx', 'cjsx', 'jsx', 'mjs', 'cjs', 'js'];
10
10
 
11
+ class UserError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'UserError';
15
+ }
16
+ }
17
+
18
+ let savedProjectPath = process.argv[2] || undefined;
19
+
11
20
  async function main() {
12
21
  console.log("Welcome to the Stack installation wizard! 🧙‍♂️");
13
22
 
14
- const projectPath = getProjectPath();
23
+ let projectPath = await getProjectPath();
15
24
  if (!fs.existsSync(projectPath)) {
16
- throw new Error(`The project path ${projectPath} does not exist`);
25
+ throw new UserError(`The project path ${projectPath} does not exist`);
17
26
  }
18
27
 
19
28
  const packageJsonPath = path.join(projectPath, 'package.json');
20
29
  if (!fs.existsSync(packageJsonPath)) {
21
- throw new Error(`The package.json file does not exist in the project path ${projectPath}. You must initialize a new project first before installing Stack.`);
30
+ throw new UserError(`The package.json file does not exist in the project path ${projectPath}. You must initialize a new project first before installing Stack.`);
22
31
  }
23
32
 
24
33
  const nextConfigPathWithoutExtension = path.join(projectPath, 'next.config');
25
34
  const nextConfigFileExtension = await findJsExtension(nextConfigPathWithoutExtension);
26
- const nextConfigPath = nextConfigPathWithoutExtension + '.' + nextConfigFileExtension;
35
+ const nextConfigPath = nextConfigPathWithoutExtension + '.' + (nextConfigFileExtension ?? "js");
27
36
  if (!fs.existsSync(nextConfigPath)) {
28
- throw new Error(`Expected file at ${nextConfigPath}. Only Next.js projects are currently supported supported.`);
37
+ throw new UserError(`Expected file at ${nextConfigPath}. Only Next.js projects are currently supported.`);
29
38
  }
30
39
 
31
40
  const envLocalPath = path.join(projectPath, '.env.local');
32
41
 
33
- const hasSrcFolder = fs.existsSync(path.join(projectPath, 'src'));
34
- const srcPath = path.join(projectPath, hasSrcFolder ? 'src' : '');
42
+ const hasSrcAppFolder = fs.existsSync(path.join(projectPath, 'src/app'));
43
+ const srcPath = path.join(projectPath, hasSrcAppFolder ? 'src' : '');
35
44
  const appPath = path.join(srcPath, 'app');
36
45
  if (!fs.existsSync(appPath)) {
37
- throw new Error(`The app path ${appPath} does not exist. Only the Next.js app router is supported.`);
46
+ throw new UserError(`The app path ${appPath} does not exist. Only the Next.js app router is supported.`);
38
47
  }
39
48
 
40
49
  const layoutPathWithoutExtension = path.join(appPath, 'layout');
@@ -54,9 +63,9 @@ async function main() {
54
63
  const stackAppContent = await readFile(stackAppPath);
55
64
  if (stackAppContent) {
56
65
  if (!stackAppContent.includes("@stackframe/stack")) {
57
- throw new Error(`A file at the path ${stackAppPath} already exists. Stack uses the /src/stack-app file to initialize the Stack SDK. Please remove the existing file and try again.`);
66
+ throw new UserError(`A file at the path ${stackAppPath} already exists. Stack uses the /src/stack-app file to initialize the Stack SDK. Please remove the existing file and try again.`);
58
67
  }
59
- throw new Error(`It seems that you've already installed Stack in this project.`);
68
+ throw new UserError(`It seems that you've already installed Stack in this project.`);
60
69
  }
61
70
 
62
71
 
@@ -65,7 +74,7 @@ async function main() {
65
74
  const handlerPath = handlerPathWithoutExtension + '.' + handlerFileExtension;
66
75
  const handlerContent = await readFile(handlerPath);
67
76
  if (handlerContent && !handlerContent.includes("@stackframe/stack")) {
68
- throw new Error(`A file at the path ${handlerPath} already exists. Stack uses the /handler path to handle incoming requests. Please remove the existing file and try again.`);
77
+ throw new UserError(`A file at the path ${handlerPath} already exists. Stack uses the /handler path to handle incoming requests. Please remove the existing file and try again.`);
69
78
  }
70
79
 
71
80
 
@@ -85,7 +94,7 @@ async function main() {
85
94
  try {
86
95
  await shellNicelyFormatted(versionCommand, { shell: true });
87
96
  } catch (err) {
88
- throw new Error(`Could not run the package manager command ${versionCommand}. Please make sure ${packageManager} is installed on your system.`);
97
+ throw new UserError(`Could not run the package manager command ${versionCommand}. Please make sure ${packageManager} is installed on your system.`);
89
98
  }
90
99
 
91
100
  console.log();
@@ -96,7 +105,7 @@ async function main() {
96
105
  console.log("Writing files...");
97
106
  await writeFileIfNotExists(envLocalPath, "NEXT_PUBLIC_STACK_PROJECT_ID=\nNEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=\nSTACK_SECRET_SERVER_KEY=\n");
98
107
  await writeFileIfNotExists(loadingPath, `export default function Loading() {\n${ind}// Stack uses React Suspense, which will render this page while user data is being fetched.\n${ind}// See: https://nextjs.org/docs/app/api-reference/file-conventions/loading\n${ind}return <></>;\n}\n`);
99
- await writeFileIfNotExists(handlerPath, `import { StackHandler } from "@stackframe/stack";\nimport { stackServerApp } from "../../../stack";\n\nexport default function Handler(props${handlerFileExtension.includes("ts") ? ": any" : ""}) {\n${ind}return <StackHandler app={stackServerApp} {...props} />;\n}\n`);
108
+ await writeFileIfNotExists(handlerPath, `import { StackHandler } from "@stackframe/stack";\nimport { stackServerApp } from "../../../stack";\n\nexport default function Handler(props${handlerFileExtension.includes("ts") ? ": any" : ""}) {\n${ind}return <StackHandler fullPage app={stackServerApp} {...props} />;\n}\n`);
100
109
  await writeFileIfNotExists(stackAppPath, `import "server-only";\n\nimport { StackServerApp } from "@stackframe/stack";\n\nexport const stackServerApp = new StackServerApp({\n${ind}tokenStore: "nextjs-cookie",\n});\n`);
101
110
  await writeFile(layoutPath, updatedLayoutContent);
102
111
  console.log("Files written successfully!");
@@ -127,11 +136,17 @@ main().then(async() => {
127
136
  console.error();
128
137
  console.error("===============================================");
129
138
  console.error();
130
- console.error("[ERR] An error occured during the initialization process. Please try manually installing Stack as described in https://docs.stack-auth.com/docs/getting-started/setup");
131
- console.error("[ERR]");
132
- console.error("[ERR] If you need assistance, please join our Discord where we're happy to help: https://discord.stack-auth.com");
139
+ if (err instanceof UserError) {
140
+ console.error("[ERR] Error: " + err.message);
141
+ } else {
142
+ console.error("[ERR] An error occured during the initialization process.");
143
+ }
133
144
  console.error("[ERR]");
134
- console.error(`[ERR] Error message: ${err.message}`);
145
+ console.error("[ERR] If you need assistance, please try installing Slack manually as described in https://docs.stack-auth.com/docs/getting-started/setup or join our Discord where we're happy to help: https://discord.stack-auth.com");
146
+ if (!(err instanceof UserError)) {
147
+ console.error("[ERR]");
148
+ console.error(`[ERR] Error message: ${err.message}`);
149
+ }
135
150
  console.error();
136
151
  console.error("===============================================");
137
152
  console.error();
@@ -199,9 +214,23 @@ function getLineIndex(lines, stringIndex) {
199
214
  throw new Error(`Index ${stringIndex} is out of bounds for lines ${JSON.stringify(lines)}`);
200
215
  }
201
216
 
202
- function getProjectPath() {
203
- const path = process.argv[2] || process.cwd();
204
- return path;
217
+ async function getProjectPath() {
218
+ if (savedProjectPath === undefined) {
219
+ savedProjectPath = process.cwd();
220
+
221
+ const askForPathModification = !fs.existsSync(path.join(savedProjectPath, 'package.json'));
222
+ if (askForPathModification) {
223
+ savedProjectPath = (await inquirer.prompt([
224
+ {
225
+ type: 'input',
226
+ name: 'newPath',
227
+ message: 'Please enter the path to your project:',
228
+ default: ".",
229
+ },
230
+ ])).newPath;
231
+ }
232
+ }
233
+ return savedProjectPath;
205
234
  }
206
235
 
207
236
  async function findJsExtension(fullPathWithoutExtension) {
@@ -215,9 +244,10 @@ async function findJsExtension(fullPathWithoutExtension) {
215
244
  }
216
245
 
217
246
  async function getPackageManager() {
218
- const yarnLock = fs.existsSync(path.join(getProjectPath(), 'yarn.lock'));
219
- const pnpmLock = fs.existsSync(path.join(getProjectPath(), 'pnpm-lock.yaml'));
220
- const npmLock = fs.existsSync(path.join(getProjectPath(), 'package-lock.json'));
247
+ const projectPath = await getProjectPath();
248
+ const yarnLock = fs.existsSync(path.join(projectPath, 'yarn.lock'));
249
+ const pnpmLock = fs.existsSync(path.join(projectPath, 'pnpm-lock.yaml'));
250
+ const npmLock = fs.existsSync(path.join(projectPath, 'package-lock.json'));
221
251
 
222
252
  if (yarnLock && !pnpmLock && !npmLock) {
223
253
  return 'yarn';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/init-stack",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "The setup wizard for Stack. https://stack-auth.com",
5
5
  "main": "index.mjs",
6
6
  "bin": "./index.mjs",