@stackframe/init-stack 2.5.9 → 2.5.11
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.
- package/CHANGELOG.md +8 -0
- package/index.mjs +155 -50
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
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(
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
263
|
+
console.log(`${ansis.green}Successfully installed Stack! 🚀🚀🚀${ansis.clear}`);
|
|
196
264
|
console.log();
|
|
197
|
-
console.log(
|
|
198
|
-
|
|
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.
|
|
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
|
-
|
|
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(
|
|
292
|
+
console.error(`${ansis.red}ERROR!${ansis.clear} ${err.message}`);
|
|
223
293
|
} else {
|
|
224
294
|
console.error(
|
|
225
|
-
"
|
|
295
|
+
"An error occurred during the initialization process."
|
|
226
296
|
);
|
|
227
297
|
}
|
|
228
|
-
console.error(
|
|
298
|
+
console.error();
|
|
299
|
+
console.error(`${ansis.red}===============================================${ansis.clear}`);
|
|
300
|
+
console.error();
|
|
229
301
|
console.error(
|
|
230
|
-
"
|
|
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("
|
|
234
|
-
console.error(`
|
|
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
|
-
|
|
454
|
+
|
|
455
|
+
async function shellNicelyFormatted(command, { quiet, ...options }) {
|
|
385
456
|
console.log();
|
|
386
457
|
const ui = new inquirer.ui.BottomBar();
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
-
|
|
403
|
-
|
|
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
|
-
|
|
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.
|
|
419
|
-
|
|
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) {
|