@stackframe/init-stack 2.5.8 → 2.5.10

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 +8 -0
  2. package/index.mjs +155 -50
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @stackframe/init-stack
2
2
 
3
+ ## 2.5.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Facebook Business support
8
+
9
+ ## 2.5.9
10
+
3
11
  ## 2.5.8
4
12
 
5
13
  ### Patch Changes
package/index.mjs CHANGED
@@ -30,8 +30,39 @@ class UserError extends Error {
30
30
 
31
31
  let savedProjectPath = process.argv[2] || undefined;
32
32
 
33
+ const isDryRun = process.argv.includes("--dry-run");
34
+
35
+ const ansis = {
36
+ red: "\x1b[31m",
37
+ blue: "\x1b[34m",
38
+ green: "\x1b[32m",
39
+ yellow: "\x1b[33m",
40
+ clear: "\x1b[0m",
41
+ bold: "\x1b[1m",
42
+ };
43
+
44
+ const filesCreated = [];
45
+ const filesModified = [];
46
+ const commandsExecuted = [];
47
+
33
48
  async function main() {
34
- console.log("Welcome to the Stack installation wizard! 🧙‍♂️");
49
+ console.log();
50
+ console.log(`
51
+ ██████
52
+ ██████████████
53
+ ████████████████████
54
+ ████████████████████ WELCOME TO
55
+ █████████████████ ╔═╗╔╦╗╔═╗╔═╗╦╔═ ┌─┐┬ ┬┌┬┐┬ ┬
56
+ █████████████ ╚═╗ ║ ╠═╣║ ╠╩╗ ├─┤│ │ │ ├─┤
57
+ █████████████ ████ ╚═╝ ╩ ╩ ╩╚═╝╩ ╩ ┴ ┴└─┘ ┴ ┴ ┴
58
+ █████████████████
59
+ ██████ ██
60
+ ████ ████
61
+ █████ █████
62
+ ██████
63
+ `);
64
+ console.log();
65
+
35
66
 
36
67
  let projectPath = await getProjectPath();
37
68
  if (!fs.existsSync(projectPath)) {
@@ -44,6 +75,17 @@ async function main() {
44
75
  `The package.json file does not exist in the project path ${projectPath}. You must initialize a new project first before installing Stack.`
45
76
  );
46
77
  }
78
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
79
+ if (!packageJson.dependencies || !packageJson.dependencies["next"]) {
80
+ throw new UserError(
81
+ `The project at ${projectPath} does not appear to be a Next.js project, or does not have 'next' installed as a dependency. Only Next.js projects are currently supported.`
82
+ );
83
+ }
84
+ if (!packageJson.dependencies["next"].includes("14")) {
85
+ throw new UserError(
86
+ `The project at ${projectPath} is using an unsupported version of Next.js (found ${packageJson.dependencies["next"]}).\n\nOnly Next.js 14 projects are currently supported. See Next's upgrade guide: https://nextjs.org/docs/app/building-your-application/upgrading/version-14`
87
+ );
88
+ }
47
89
 
48
90
  const nextConfigPathWithoutExtension = path.join(projectPath, "next.config");
49
91
  const nextConfigFileExtension = await findJsExtension(
@@ -109,11 +151,11 @@ async function main() {
109
151
  if (stackAppContent) {
110
152
  if (!stackAppContent.includes("@stackframe/stack")) {
111
153
  throw new UserError(
112
- `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.`
154
+ `A file at the path ${stackAppPath} already exists. Stack uses the /src/stack.ts file to initialize the Stack SDK. Please remove the existing file and try again.`
113
155
  );
114
156
  }
115
157
  throw new UserError(
116
- `It seems that you've already installed Stack in this project.`
158
+ `It seems that you already installed Stack in this project.`
117
159
  );
118
160
  }
119
161
 
@@ -136,33 +178,41 @@ async function main() {
136
178
  (await findJsExtension(loadingPathWithoutExtension)) ?? defaultExtension;
137
179
  const loadingPath = loadingPathWithoutExtension + "." + loadingFileExtension;
138
180
 
139
- console.log();
140
- console.log("Found supported project at:", projectPath);
141
- console.log("Installing now! 💃");
142
-
143
181
  const packageManager = await getPackageManager();
144
182
  const versionCommand = `${packageManager} --version`;
145
183
  const installCommand =
146
184
  packageManager === "yarn" ? "yarn add" : `${packageManager} install`;
147
185
 
148
- process.stdout.write("\nChecking package manager version... ");
149
186
  try {
150
- await shellNicelyFormatted(versionCommand, { shell: true });
187
+ await shellNicelyFormatted(versionCommand, { shell: true, quiet: true });
151
188
  } catch (err) {
152
189
  throw new UserError(
153
- `Could not run the package manager command ${versionCommand}. Please make sure ${packageManager} is installed on your system.`
190
+ `Could not run the package manager command '${versionCommand}'. Please make sure ${packageManager} is installed on your system.`
154
191
  );
155
192
  }
156
193
 
194
+ const isReady = await inquirer.prompt([
195
+ {
196
+ type: "confirm",
197
+ name: "ready",
198
+ message: `Found a Next.js project at ${projectPath}. Ready to install Stack?`,
199
+ default: true,
200
+ },
201
+ ]);
202
+ if (!isReady.ready) {
203
+ throw new UserError("Installation aborted.");
204
+ }
205
+
157
206
  console.log();
158
- console.log("Installing dependencies...");
207
+ console.log(`${ansis.bold}Installing dependencies...${ansis.clear}`);
159
208
  await shellNicelyFormatted(`${installCommand} @stackframe/stack`, {
160
209
  shell: true,
161
210
  cwd: projectPath,
162
211
  });
163
212
 
164
213
  console.log();
165
- console.log("Writing files...");
214
+ console.log(`${ansis.bold}Writing files...${ansis.clear}`);
215
+ console.log();
166
216
  if (potentialEnvLocations.every((p) => !fs.existsSync(p))) {
167
217
  await writeFile(
168
218
  envLocalPath,
@@ -182,7 +232,25 @@ async function main() {
182
232
  `import "server-only";\n\nimport { StackServerApp } from "@stackframe/stack";\n\nexport const stackServerApp = new StackServerApp({\n${ind}tokenStore: "nextjs-cookie",\n});\n`
183
233
  );
184
234
  await writeFile(layoutPath, updatedLayoutContent);
185
- console.log("Files written successfully!");
235
+ console.log(`${ansis.green}√${ansis.clear} Done writing files`);
236
+
237
+ console.log();
238
+ console.log();
239
+ console.log();
240
+ console.log(`${ansis.bold}${ansis.green}Installation succeeded!${ansis.clear}`);
241
+ console.log();
242
+ console.log("Commands executed:");
243
+ for (const command of commandsExecuted) {
244
+ console.log(` ${ansis.blue}${command}${ansis.clear}`);
245
+ }
246
+ console.log();
247
+ console.log("Files written:");
248
+ for (const file of filesModified) {
249
+ console.log(` ${ansis.yellow}${file}${ansis.clear}`);
250
+ }
251
+ for (const file of filesCreated) {
252
+ console.log(` ${ansis.green}${file}${ansis.clear}`);
253
+ }
186
254
  }
187
255
  main()
188
256
  .then(async () => {
@@ -190,52 +258,54 @@ main()
190
258
  console.log();
191
259
  console.log();
192
260
  console.log();
193
- console.log("===============================================");
261
+ console.log(`${ansis.green}===============================================${ansis.clear}`);
194
262
  console.log();
195
- console.log("Successfully installed Stack! 🚀🚀🚀");
263
+ console.log(`${ansis.green}Successfully installed Stack! 🚀🚀🚀${ansis.clear}`);
196
264
  console.log();
197
- console.log(
198
- "Next up, please create an account on https://app.stack-auth.com to create a new project, and copy the Next.js environment variables from a new API key into your .env.local file."
199
- );
265
+ console.log("Next steps:");
266
+ console.log(" 1. Create an account and project on https://app.stack-auth.com");
267
+ console.log(" 2. Copy the environment variables from the new API key into your .env.local file");
200
268
  console.log();
201
269
  console.log(
202
- "Then, you will be able to access your sign-in page on http://your-website.example.com/handler/sign-in. Congratulations!"
270
+ "Then, you will be able to access your sign-in page on http://your-website.example.com/handler/sign-in. That's it!"
203
271
  );
204
272
  console.log();
273
+ console.log(`${ansis.green}===============================================${ansis.clear}`);
274
+ console.log();
205
275
  console.log(
206
276
  "For more information, please visit https://docs.stack-auth.com/docs/getting-started/setup"
207
277
  );
208
278
  console.log();
209
- console.log("===============================================");
210
- console.log();
211
279
  await open("https://app.stack-auth.com/wizard-congrats");
212
280
  })
213
281
  .catch((err) => {
214
- console.error(err);
282
+ if (!(err instanceof UserError)) {
283
+ console.error(err);
284
+ }
215
285
  console.error();
216
286
  console.error();
217
287
  console.error();
218
288
  console.error();
219
- console.error("===============================================");
289
+ console.error(`${ansis.red}===============================================${ansis.clear}`);
220
290
  console.error();
221
291
  if (err instanceof UserError) {
222
- console.error("[ERR] Error: " + err.message);
292
+ console.error(`${ansis.red}ERROR!${ansis.clear} ${err.message}`);
223
293
  } else {
224
294
  console.error(
225
- "[ERR] An error occurred during the initialization process."
295
+ "An error occurred during the initialization process."
226
296
  );
227
297
  }
228
- console.error("[ERR]");
298
+ console.error();
299
+ console.error(`${ansis.red}===============================================${ansis.clear}`);
300
+ console.error();
229
301
  console.error(
230
- "[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"
302
+ "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"
231
303
  );
232
304
  if (!(err instanceof UserError)) {
233
- console.error("[ERR]");
234
- console.error(`[ERR] Error message: ${err.message}`);
305
+ console.error("");
306
+ console.error(`Error message: ${err.message}`);
235
307
  }
236
308
  console.error();
237
- console.error("===============================================");
238
- console.error();
239
309
  process.exit(1);
240
310
  });
241
311
 
@@ -381,31 +451,55 @@ async function getPackageManager() {
381
451
  return answers.packageManager;
382
452
  }
383
453
 
384
- async function shellNicelyFormatted(command, options) {
454
+
455
+ async function shellNicelyFormatted(command, { quiet, ...options }) {
385
456
  console.log();
386
457
  const ui = new inquirer.ui.BottomBar();
387
- ui.updateBottomBar(`Running command: ${command}...`);
388
- const child = child_process.spawn(command, options);
389
- child.stdout.pipe(ui.log);
390
- child.stderr.pipe(ui.log);
391
-
392
- await new Promise((resolve, reject) => {
393
- child.on("exit", (code) => {
394
- if (code === 0) {
395
- resolve();
396
- } else {
397
- reject(new Error(`Command ${command} failed with code ${code}`));
458
+ let dots = 4;
459
+ ui.updateBottomBar(`${ansis.blue}Running command: ${command}...${ansis.clear}`);
460
+ const interval = setInterval(() => {
461
+ if (!isDryRun) {
462
+ ui.updateBottomBar(
463
+ `${ansis.blue}Running command: ${command}${".".repeat(dots++ % 5)}${ansis.clear}`
464
+ );
465
+ }
466
+ }, 700);
467
+ try {
468
+ if (!isDryRun) {
469
+ const child = child_process.spawn(command, options);
470
+ if (!quiet) {
471
+ child.stdout.pipe(ui.log);
472
+ child.stderr.pipe(ui.log);
398
473
  }
399
- });
400
- });
401
474
 
402
- ui.updateBottomBar(`Command ${command} finished successfully!\n`);
403
- ui.close();
475
+ await new Promise((resolve, reject) => {
476
+ child.on("exit", (code) => {
477
+ if (code === 0) {
478
+ resolve();
479
+ } else {
480
+ reject(new Error(`Command ${command} failed with code ${code}`));
481
+ }
482
+ });
483
+ });
484
+ } else {
485
+ console.log(`[DRY-RUN] Would have run: ${command}`);
486
+ }
487
+
488
+ if (!quiet) {
489
+ commandsExecuted.push(command);
490
+ }
491
+ } finally {
492
+ clearTimeout(interval);
493
+ ui.updateBottomBar(quiet ? "" : `${ansis.green}√${ansis.clear} Command ${command} succeeded\n`);
494
+ ui.close();
495
+ }
404
496
  }
405
497
 
406
498
  async function readFile(fullPath) {
407
499
  try {
408
- return fs.readFileSync(fullPath, "utf-8");
500
+ if (!isDryRun) {
501
+ return fs.readFileSync(fullPath, "utf-8");
502
+ }
409
503
  } catch (err) {
410
504
  if (err.code === "ENOENT") {
411
505
  return null;
@@ -415,8 +509,19 @@ async function readFile(fullPath) {
415
509
  }
416
510
 
417
511
  async function writeFile(fullPath, content) {
418
- fs.mkdirSync(path.dirname(fullPath), { recursive: true });
419
- fs.writeFileSync(fullPath, content);
512
+ let create = !fs.existsSync(fullPath);
513
+ if (!isDryRun) {
514
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
515
+ fs.writeFileSync(fullPath, content);
516
+ } else {
517
+ console.log(`[DRY-RUN] Would have written to ${fullPath}`);
518
+ }
519
+ const relativeToProjectPath = path.relative(await getProjectPath(), fullPath);
520
+ if (!create) {
521
+ filesModified.push(relativeToProjectPath);
522
+ } else {
523
+ filesCreated.push(relativeToProjectPath);
524
+ }
420
525
  }
421
526
 
422
527
  async function writeFileIfNotExists(fullPath, content) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/init-stack",
3
- "version": "2.5.8",
3
+ "version": "2.5.10",
4
4
  "description": "The setup wizard for Stack. https://stack-auth.com",
5
5
  "main": "index.mjs",
6
6
  "bin": "./index.mjs",