@stacksjs/buddy 0.70.113 → 0.70.115
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/dist/cli.js +23 -2
- package/dist/commands/add.js +1 -1
- package/dist/commands/build.js +58 -11
- package/dist/commands/clean.js +9 -2
- package/dist/commands/cloud.js +27 -11
- package/dist/commands/commit.js +1 -1
- package/dist/commands/create.js +20 -10
- package/dist/commands/deploy.js +31 -6
- package/dist/commands/dev.js +17 -20
- package/dist/commands/doctor.d.ts +9 -0
- package/dist/commands/doctor.js +77 -19
- package/dist/commands/extension.js +38 -2
- package/dist/commands/fresh.js +9 -2
- package/dist/commands/make.js +48 -31
- package/dist/commands/migrate.js +2 -1
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +56 -10
- package/dist/commands/types.js +1 -1
- package/dist/lazy-commands.js +15 -5
- package/package.json +44 -43
|
@@ -10,7 +10,7 @@ export function extension(buddy) {
|
|
|
10
10
|
const pkg = await Bun.file(`${process.cwd()}/package.json`).json().catch(() => ({}));
|
|
11
11
|
return { config, version: pkg.version ?? "0.0.0" };
|
|
12
12
|
};
|
|
13
|
-
buddy.command("extension:build", "Build the browser extension (Chrome + Firefox) from config/extension.ts").option("--target <target>", "Build a single target (chrome | firefox); omit to build all").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
|
|
13
|
+
buddy.command("extension:build", "Build the browser extension (Chrome + Firefox + Safari) from config/extension.ts").option("--target <target>", "Build a single target (chrome | firefox | safari); omit to build all").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
|
|
14
14
|
const { buildExtension, buildAllTargets } = await import("@stacksjs/browser-extension"), { config, version } = await load(), v = options.version ?? version;
|
|
15
15
|
if (options.target) {
|
|
16
16
|
const { outdir } = await buildExtension(config, { target: options.target, version: v });
|
|
@@ -68,11 +68,47 @@ console.log('[${name}] popup')
|
|
|
68
68
|
`);
|
|
69
69
|
log.info("Next: add icons under public/icons, then `buddy extension:build`.");
|
|
70
70
|
});
|
|
71
|
-
buddy.command("extension:package", "Build + zip the browser extension into store-ready archives").option("--target <target>", "Package a single target (chrome | firefox); omit to package all").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
|
|
71
|
+
buddy.command("extension:package", "Build + zip the browser extension into store-ready archives").option("--target <target>", "Package a single target (chrome | firefox | safari); omit to package all").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
|
|
72
72
|
const { packageExtension } = await import("@stacksjs/browser-extension"), { config, version } = await load(), v = options.version ?? version, targets = options.target ? [options.target] : config.targets ?? ["chrome", "firefox"];
|
|
73
73
|
for (const target of targets) {
|
|
74
74
|
const out = await packageExtension(config, { target, version: v });
|
|
75
75
|
log.success(`Packaged ${config.name} (${target}) \u2192 ${out}`);
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
|
+
buddy.command("extension:safari:init", "Scaffold the Safari container app (Xcode project) from the template").option("--bundle-id <id>", "Base bundle identifier (defaults to config safariBundleId)").option("--dir <dir>", "Output directory for the Xcode project (default safari)").option("--force", "Overwrite existing scaffold files").option("--team-id <id>", "Apple Developer team used for signing").action(async (options) => {
|
|
79
|
+
const { scaffoldSafariApp } = await import("@stacksjs/browser-extension"), { config } = await load(), { dir, written, skipped } = await scaffoldSafariApp(config, {
|
|
80
|
+
bundleId: options.bundleId,
|
|
81
|
+
dir: options.dir,
|
|
82
|
+
force: Boolean(options.force),
|
|
83
|
+
teamId: options.teamId
|
|
84
|
+
});
|
|
85
|
+
log.success(`Scaffolded the Safari container app \u2192 ${dir} (${written.length} files)`);
|
|
86
|
+
if (skipped.length)
|
|
87
|
+
log.info(`kept ${skipped.length} existing files (use --force to overwrite)`);
|
|
88
|
+
});
|
|
89
|
+
buddy.command("extension:safari:app", "Build the extension, sync it into the appex, and xcodebuild the container app").option("--release", "Build the Release configuration (default Debug)").option("--signed", "Allow code signing (needs an Apple Development identity)").option("--skip-xcodebuild", "Only build + sync the extension payload").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
|
|
90
|
+
const { buildSafariApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), { appPath, resources } = await buildSafariApp(config, {
|
|
91
|
+
version: options.version ?? version,
|
|
92
|
+
release: Boolean(options.release),
|
|
93
|
+
signed: Boolean(options.signed),
|
|
94
|
+
skipXcodebuild: Boolean(options.skipXcodebuild)
|
|
95
|
+
});
|
|
96
|
+
if (appPath) {
|
|
97
|
+
log.success(`Built ${appPath}`);
|
|
98
|
+
log.info("Open the app once, then enable the extension in Safari > Settings > Extensions.");
|
|
99
|
+
} else
|
|
100
|
+
log.success(`Extension payload synced \u2192 ${resources}`);
|
|
101
|
+
});
|
|
102
|
+
buddy.command("extension:safari:publish", "Archive and validate or upload the Safari app to App Store Connect").option("--version <version>", "Override the marketing version (defaults to package.json)").option("--build-number <number>", "CFBundleVersion (defaults to GITHUB_RUN_NUMBER or Unix time)").option("--team-id <id>", "Apple Developer team (defaults to config safariTeamId)").option("--api-key-id <id>", "App Store Connect API key ID").option("--api-issuer-id <id>", "App Store Connect API issuer ID").option("--api-key-path <path>", "Path to the App Store Connect AuthKey_*.p8 file").option("--validate-only", "Create and validate the archive without uploading it").action(async (options) => {
|
|
103
|
+
const { publishSafariApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), result = await publishSafariApp(config, {
|
|
104
|
+
version: options.version ?? version,
|
|
105
|
+
buildNumber: options.buildNumber,
|
|
106
|
+
teamId: options.teamId,
|
|
107
|
+
keyId: options.apiKeyId,
|
|
108
|
+
issuerId: options.apiIssuerId,
|
|
109
|
+
keyPath: options.apiKeyPath,
|
|
110
|
+
validateOnly: Boolean(options.validateOnly)
|
|
111
|
+
});
|
|
112
|
+
log.success(options.validateOnly ? `Validated Safari archive ${result.archivePath} (build ${result.buildNumber})` : `Uploaded Safari build ${result.buildNumber} to App Store Connect`);
|
|
113
|
+
});
|
|
78
114
|
}
|
package/dist/commands/fresh.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
import { runAction } from "@stacksjs/actions";
|
|
3
3
|
import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
|
|
4
|
+
import { hasTTY, isCI } from "@stacksjs/env";
|
|
4
5
|
import { Action } from "@stacksjs/enums";
|
|
5
6
|
import { ExitCode } from "@stacksjs/types";
|
|
6
7
|
export function fresh(buddy) {
|
|
7
8
|
const descriptions = {
|
|
8
9
|
fresh: "Re-installs your npm dependencies",
|
|
9
10
|
project: "Target a specific project",
|
|
11
|
+
force: "Skip the confirmation prompt (required in CI/non-interactive shells)",
|
|
10
12
|
verbose: "Enable verbose output"
|
|
11
13
|
};
|
|
12
|
-
buddy.command("fresh", descriptions.fresh).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
14
|
+
buddy.command("fresh", descriptions.fresh).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-f, --force", descriptions.force, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
13
15
|
log.debug("Running `buddy fresh` ...", options);
|
|
14
|
-
|
|
16
|
+
const skipConfirm = options.force === !0 || Boolean(buddy.isForce) || Boolean(buddy.isNoInteraction);
|
|
17
|
+
if (!skipConfirm && (isCI || !hasTTY || !process.stdin.isTTY)) {
|
|
18
|
+
log.syncError("Refusing to run `buddy fresh` from a non-interactive shell without confirmation.");
|
|
19
|
+
log.fatal(" \u27A1\uFE0F Re-run with `--force` to proceed: `buddy fresh --force`");
|
|
20
|
+
}
|
|
21
|
+
if (!skipConfirm) {
|
|
15
22
|
const { confirm } = await import("@stacksjs/cli");
|
|
16
23
|
if (!await confirm({
|
|
17
24
|
message: "This will remove and reinstall all dependencies. Continue?",
|
package/dist/commands/make.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
import {
|
|
3
|
+
createFactory,
|
|
3
4
|
createMiddleware,
|
|
4
5
|
createMigration,
|
|
5
6
|
createModel,
|
|
@@ -45,16 +46,17 @@ export function make(buddy) {
|
|
|
45
46
|
resource: "Create a new API resource",
|
|
46
47
|
name: "The name of the action",
|
|
47
48
|
queue: "Make queue migration",
|
|
49
|
+
queueTable: "Create the queue jobs table migration",
|
|
48
50
|
stack: "Create a new stack",
|
|
49
51
|
certificate: "Create a new SSL Certificate",
|
|
50
52
|
select: "What are you trying to make?",
|
|
51
53
|
project: "Target a specific project",
|
|
52
54
|
verbose: "Enable verbose output"
|
|
53
55
|
};
|
|
54
|
-
buddy.command("make [make]", "The make command").option("-a, --action [action]", descriptions.action, { default: !1 }).option("-c, --component [component]", descriptions.component, { default: !1 }).option("-d, --database [database]", descriptions.database, { default: !1 }).option("-f, --factory [factory]", descriptions.factory, { default: !1 }).option("-
|
|
56
|
+
buddy.command("make [make]", "The make command").option("-a, --action [action]", descriptions.action, { default: !1 }).option("-c, --component [component]", descriptions.component, { default: !1 }).option("-d, --database [database]", descriptions.database, { default: !1 }).option("-f, --factory [factory]", descriptions.factory, { default: !1 }).option("-fn, --function [function]", descriptions.function, { default: !1 }).option("-l, --language [language]", descriptions.language, { default: !1 }).option("-m, --model [model]", descriptions.model, { default: !1 }).option("-mw, --middleware [middleware]", descriptions.middleware, { default: !1 }).option("-p, --page [page]", descriptions.page, { default: !1 }).option("-mg, --migration [migration]", descriptions.migration, { default: !1 }).option("-n, --notification [notification]", descriptions.notification, { default: !1 }).option("-qt, --queue-table", descriptions.queue, { default: !1 }).option("-s, --stack [stack]", descriptions.stack, { default: !1 }).option("--dry-run", "Preview the files that would be generated without writing", { default: !1 }).option("--with-validation", "Include a validation rules block in the generated stub", { default: !1 }).option("--with-auth", "Include auth-aware boilerplate in the generated stub", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (make, options) => {
|
|
55
57
|
log.debug("Running `buddy make` ...", options);
|
|
56
58
|
if (!buddy.args[0]) {
|
|
57
|
-
|
|
59
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
58
60
|
process.exit(ExitCode.FatalError);
|
|
59
61
|
}
|
|
60
62
|
setDryRun(Boolean(options.dryRun || options["dry-run"]));
|
|
@@ -115,7 +117,14 @@ export function make(buddy) {
|
|
|
115
117
|
case "stack":
|
|
116
118
|
await makeStack(options);
|
|
117
119
|
break;
|
|
118
|
-
|
|
120
|
+
case "factory":
|
|
121
|
+
await createFactory(options);
|
|
122
|
+
break;
|
|
123
|
+
default: {
|
|
124
|
+
console.error(`Unknown make subcommand: ${make}`);
|
|
125
|
+
console.error("Valid subcommands: action, certificate, command, component, database, factory, function, job, language, mail, middleware, migration, model, notification, page, policy, queue-table, resource, stack");
|
|
126
|
+
process.exit(ExitCode.InvalidArgument);
|
|
127
|
+
}
|
|
119
128
|
}
|
|
120
129
|
}
|
|
121
130
|
await invoke(options);
|
|
@@ -127,7 +136,7 @@ export function make(buddy) {
|
|
|
127
136
|
name = name ?? options.name;
|
|
128
137
|
options.name = name;
|
|
129
138
|
if (!name) {
|
|
130
|
-
|
|
139
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
131
140
|
process.exit(ExitCode.FatalError);
|
|
132
141
|
}
|
|
133
142
|
setDryRun(Boolean(options.dryRun || options["dry-run"]));
|
|
@@ -140,7 +149,7 @@ export function make(buddy) {
|
|
|
140
149
|
buddy.command("scaffold:crud [name]", "Generate model, migration, and CRUD actions").alias("make:crud").alias("make:scaffold").option("-n, --name [name]", "Resource name (PascalCase)", { default: !1 }).option("-f, --fields [fields]", "Comma-separated field list, e.g. title:string,body:text,published:boolean", { default: "" }).option("--dry-run", "Preview the generated files without writing", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy scaffold:crud Post --fields=title:string,body:text,published:boolean").action(async (name, options) => {
|
|
141
150
|
name = name ?? options.name;
|
|
142
151
|
if (!name) {
|
|
143
|
-
|
|
152
|
+
console.error("scaffold:crud requires a resource name. Example: buddy scaffold:crud Post --fields=title:string,body:text");
|
|
144
153
|
process.exit(ExitCode.FatalError);
|
|
145
154
|
}
|
|
146
155
|
const { scaffoldCrud } = await import("@stacksjs/actions");
|
|
@@ -148,7 +157,7 @@ export function make(buddy) {
|
|
|
148
157
|
try {
|
|
149
158
|
await scaffoldCrud(name, options);
|
|
150
159
|
} catch (err) {
|
|
151
|
-
|
|
160
|
+
console.error("scaffold:crud failed:", err);
|
|
152
161
|
process.exit(ExitCode.FatalError);
|
|
153
162
|
}
|
|
154
163
|
});
|
|
@@ -158,8 +167,8 @@ export function make(buddy) {
|
|
|
158
167
|
name = name ?? options.name;
|
|
159
168
|
options.name = name;
|
|
160
169
|
if (!name) {
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
console.error("You need to specify a command name.");
|
|
171
|
+
console.error("Example: buddy make:command SendEmails");
|
|
163
172
|
process.exit(ExitCode.FatalError);
|
|
164
173
|
}
|
|
165
174
|
if (!await makeCommand(options)) {
|
|
@@ -180,7 +189,7 @@ export function make(buddy) {
|
|
|
180
189
|
name = name ?? options.name;
|
|
181
190
|
options.name = name;
|
|
182
191
|
if (!name) {
|
|
183
|
-
|
|
192
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
184
193
|
process.exit(ExitCode.FatalError);
|
|
185
194
|
}
|
|
186
195
|
await makeComponent(options);
|
|
@@ -190,25 +199,32 @@ export function make(buddy) {
|
|
|
190
199
|
name = name ?? options.name;
|
|
191
200
|
options.name = name;
|
|
192
201
|
if (!name) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
console.error("You need to specify a database name via the `--name` option, or as the command\u2019s argument.");
|
|
203
|
+
console.error("Example: `buddy make:database my-cool-database`");
|
|
204
|
+
console.error("Or: `buddy make:database --name=my-cool-database`");
|
|
205
|
+
console.error("Read more about the documentation here: https://stacksjs.com/docs/make/database");
|
|
197
206
|
process.exit(ExitCode.FatalError);
|
|
198
207
|
}
|
|
199
208
|
makeDatabase(options);
|
|
200
209
|
});
|
|
201
|
-
buddy.command("make:factory [name]", descriptions.factory).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action((name, options) => {
|
|
210
|
+
buddy.command("make:factory [name]", descriptions.factory).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
202
211
|
log.debug("Running `buddy make:factory` ...", options);
|
|
203
212
|
name = name ?? options.name;
|
|
204
213
|
options.name = name;
|
|
205
214
|
if (!name) {
|
|
206
|
-
|
|
215
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
207
216
|
process.exit(ExitCode.FatalError);
|
|
208
217
|
}
|
|
218
|
+
await createFactory(options);
|
|
209
219
|
});
|
|
210
|
-
buddy.command("make:function [name]", descriptions.function).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
220
|
+
buddy.command("make:function [name]", descriptions.function).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
211
221
|
log.debug("Running `buddy make:function` ...", options);
|
|
222
|
+
name = name ?? options.name;
|
|
223
|
+
options.name = name;
|
|
224
|
+
if (!name) {
|
|
225
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
226
|
+
process.exit(ExitCode.FatalError);
|
|
227
|
+
}
|
|
212
228
|
await makeFunction(options);
|
|
213
229
|
});
|
|
214
230
|
buddy.command("make:lang [name]", descriptions.language).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
@@ -216,26 +232,27 @@ export function make(buddy) {
|
|
|
216
232
|
name = name ?? options.name;
|
|
217
233
|
options.name = name;
|
|
218
234
|
if (!name) {
|
|
219
|
-
|
|
235
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
220
236
|
process.exit(ExitCode.FatalError);
|
|
221
237
|
}
|
|
222
238
|
await makeLanguage(options);
|
|
223
239
|
});
|
|
224
|
-
buddy.command("make:migration [name]", descriptions.migration).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action((name, options) => {
|
|
240
|
+
buddy.command("make:migration [name]", descriptions.migration).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
225
241
|
log.debug("Running `buddy make:migration` ...", options);
|
|
226
242
|
name = name ?? options.name;
|
|
227
243
|
options.name = name;
|
|
228
244
|
if (!name) {
|
|
229
|
-
|
|
245
|
+
console.error("You need to specify a migration name");
|
|
230
246
|
process.exit(ExitCode.FatalError);
|
|
231
247
|
}
|
|
248
|
+
await createMigration(options);
|
|
232
249
|
});
|
|
233
250
|
buddy.command("make:model [name]", descriptions.model).option("-n, --name [name]", descriptions.name, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
234
251
|
log.debug("Running `buddy make:model` ...", options);
|
|
235
252
|
name = name ?? options.name;
|
|
236
253
|
options.name = name;
|
|
237
254
|
if (!name) {
|
|
238
|
-
|
|
255
|
+
console.error("You need to specify a model name");
|
|
239
256
|
process.exit(ExitCode.FatalError);
|
|
240
257
|
}
|
|
241
258
|
await createModel(options);
|
|
@@ -246,7 +263,7 @@ export function make(buddy) {
|
|
|
246
263
|
name = name ?? options.name;
|
|
247
264
|
options.name = name;
|
|
248
265
|
if (!name) {
|
|
249
|
-
|
|
266
|
+
console.error("You need to specify a name (e.g. `buddy make:mail OrderShipped`).");
|
|
250
267
|
process.exit(ExitCode.FatalError);
|
|
251
268
|
}
|
|
252
269
|
await makeMail(options);
|
|
@@ -262,7 +279,7 @@ export function make(buddy) {
|
|
|
262
279
|
name = name ?? options.name;
|
|
263
280
|
options.name = name;
|
|
264
281
|
if (!name) {
|
|
265
|
-
|
|
282
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
266
283
|
process.exit(ExitCode.FatalError);
|
|
267
284
|
}
|
|
268
285
|
if (!await createNotification(options)) {
|
|
@@ -284,8 +301,8 @@ export function make(buddy) {
|
|
|
284
301
|
name = name ?? options.name;
|
|
285
302
|
options.name = name;
|
|
286
303
|
if (!name) {
|
|
287
|
-
|
|
288
|
-
|
|
304
|
+
console.error("You need to specify a policy name.");
|
|
305
|
+
console.error("Example: buddy make:policy PostPolicy");
|
|
289
306
|
process.exit(ExitCode.FatalError);
|
|
290
307
|
}
|
|
291
308
|
if (!await makePolicy(options)) {
|
|
@@ -307,8 +324,8 @@ export function make(buddy) {
|
|
|
307
324
|
name = name ?? options.name;
|
|
308
325
|
options.name = name;
|
|
309
326
|
if (!name) {
|
|
310
|
-
|
|
311
|
-
|
|
327
|
+
console.error("You need to specify a resource name.");
|
|
328
|
+
console.error("Example: buddy make:resource UserResource");
|
|
312
329
|
process.exit(ExitCode.FatalError);
|
|
313
330
|
}
|
|
314
331
|
if (!await makeResource(options)) {
|
|
@@ -324,7 +341,7 @@ export function make(buddy) {
|
|
|
324
341
|
});
|
|
325
342
|
process.exit(ExitCode.Success);
|
|
326
343
|
});
|
|
327
|
-
buddy.command("make:queue-table", descriptions.
|
|
344
|
+
buddy.command("make:queue-table", descriptions.queueTable).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
328
345
|
log.debug("Running `buddy make queue:table` ...", options);
|
|
329
346
|
await makeQueueTable();
|
|
330
347
|
});
|
|
@@ -333,7 +350,7 @@ export function make(buddy) {
|
|
|
333
350
|
name = name ?? options.name;
|
|
334
351
|
options.name = name;
|
|
335
352
|
if (!name) {
|
|
336
|
-
|
|
353
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
337
354
|
process.exit(ExitCode.FatalError);
|
|
338
355
|
}
|
|
339
356
|
await makeStack(options);
|
|
@@ -343,7 +360,7 @@ export function make(buddy) {
|
|
|
343
360
|
name = name ?? options.name;
|
|
344
361
|
options.name = name;
|
|
345
362
|
if (!name) {
|
|
346
|
-
|
|
363
|
+
console.error("You need to specify a name. Read more about the documentation here.");
|
|
347
364
|
process.exit(ExitCode.FatalError);
|
|
348
365
|
}
|
|
349
366
|
await makePage(options);
|
|
@@ -354,8 +371,8 @@ export function make(buddy) {
|
|
|
354
371
|
name = name ?? options.name;
|
|
355
372
|
options.name = name;
|
|
356
373
|
if (!name) {
|
|
357
|
-
|
|
358
|
-
|
|
374
|
+
console.error("You need to specify a job name.");
|
|
375
|
+
console.error("Example: buddy make:job SendWelcomeEmail");
|
|
359
376
|
process.exit(ExitCode.FatalError);
|
|
360
377
|
}
|
|
361
378
|
if (!await makeJob(options)) {
|
package/dist/commands/migrate.js
CHANGED
|
@@ -181,6 +181,7 @@ function currentDatabaseLabel() {
|
|
|
181
181
|
export function migrate(buddy) {
|
|
182
182
|
const descriptions = {
|
|
183
183
|
migrate: "Migrates your database",
|
|
184
|
+
fresh: "Drop all tables and re-run every migration (destroys all data)",
|
|
184
185
|
project: "Target a specific project",
|
|
185
186
|
verbose: "Enable verbose output",
|
|
186
187
|
auth: "Also migrate auth tables (oauth_clients, oauth_access_tokens, oauth_refresh_tokens, password_resets)",
|
|
@@ -291,7 +292,7 @@ export function migrate(buddy) {
|
|
|
291
292
|
});
|
|
292
293
|
process.exit(ExitCode.Success);
|
|
293
294
|
});
|
|
294
|
-
buddy.command("migrate:fresh", descriptions.
|
|
295
|
+
buddy.command("migrate:fresh", descriptions.fresh).alias("db:fresh").option("-d, --diff", "Show the SQL that would be run", { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-s, --seed", "Run database seeders after migration", { default: !1 }).option("-a, --auth", descriptions.auth, { default: !0 }).option("--no-auth", "Skip auth/oauth table migrations").option("-f, --force", 'Skip the drop-database confirmation (only honored when the migrateFresh guard is "allow")', { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
295
296
|
log.debug("Running `buddy migrate:fresh` ...", options);
|
|
296
297
|
const perf = await intro("buddy migrate:fresh"), validation = validateModelsExist();
|
|
297
298
|
if (!validation.valid) {
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { CLI, CliOptions } from '@stacksjs/types';
|
|
|
2
2
|
export declare function setup(buddy: CLI): void;
|
|
3
3
|
export declare function ensurePantryInstalled(): Promise<void>;
|
|
4
4
|
export declare function ensurePantryDependencies(cwd: string): Promise<void>;
|
|
5
|
+
export declare function ensureNodeDependencies(cwd: string): Promise<void>;
|
|
5
6
|
export declare function ensureAppKey(cwd: string): Promise<void>;
|
|
6
7
|
export declare function pantryDatabasePackage(connection: string): DatabasePackage | undefined;
|
|
7
8
|
/**
|
package/dist/commands/setup.js
CHANGED
|
@@ -14,7 +14,7 @@ function getTimeoutMs(envVar, fallbackMs) {
|
|
|
14
14
|
return value;
|
|
15
15
|
return fallbackMs;
|
|
16
16
|
}
|
|
17
|
-
const PANTRY_CHECK_TIMEOUT_MS = getTimeoutMs("PANTRY_CHECK_TIMEOUT_MS", 15000), PANTRY_INSTALL_TIMEOUT_MS = getTimeoutMs("PANTRY_INSTALL_TIMEOUT_MS", 600000), PANTRY_DEPENDENCIES_TIMEOUT_MS = getTimeoutMs("PANTRY_DEPENDENCIES_TIMEOUT_MS", 1200000), KEYGEN_TIMEOUT_MS = getTimeoutMs("KEYGEN_TIMEOUT_MS", 120000), AWS_CONFIG_TIMEOUT_MS = getTimeoutMs("AWS_CONFIG_TIMEOUT_MS", 900000);
|
|
17
|
+
const PANTRY_CHECK_TIMEOUT_MS = getTimeoutMs("PANTRY_CHECK_TIMEOUT_MS", 15000), PANTRY_INSTALL_TIMEOUT_MS = getTimeoutMs("PANTRY_INSTALL_TIMEOUT_MS", 600000), PANTRY_DEPENDENCIES_TIMEOUT_MS = getTimeoutMs("PANTRY_DEPENDENCIES_TIMEOUT_MS", 1200000), BUN_INSTALL_TIMEOUT_MS = getTimeoutMs("BUN_INSTALL_TIMEOUT_MS", 600000), KEYGEN_TIMEOUT_MS = getTimeoutMs("KEYGEN_TIMEOUT_MS", 120000), AWS_CONFIG_TIMEOUT_MS = getTimeoutMs("AWS_CONFIG_TIMEOUT_MS", 900000);
|
|
18
18
|
export function setup(buddy) {
|
|
19
19
|
const descriptions = {
|
|
20
20
|
setup: "This command ensures your project is setup correctly",
|
|
@@ -103,6 +103,25 @@ export async function ensurePantryDependencies(cwd) {
|
|
|
103
103
|
handleError(result.error);
|
|
104
104
|
process.exit(ExitCode.FatalError);
|
|
105
105
|
}
|
|
106
|
+
export async function ensureNodeDependencies(cwd) {
|
|
107
|
+
if (existsSync(join(cwd, "node_modules"))) {
|
|
108
|
+
log.success("node_modules existed, skipping bun install");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
log.info("Running bun install...");
|
|
112
|
+
const result = await runCommand("bun install", {
|
|
113
|
+
cwd,
|
|
114
|
+
timeoutMs: BUN_INSTALL_TIMEOUT_MS
|
|
115
|
+
}).catch((error) => {
|
|
116
|
+
handleError(error);
|
|
117
|
+
process.exit(ExitCode.FatalError);
|
|
118
|
+
});
|
|
119
|
+
if (result.isErr) {
|
|
120
|
+
handleError(result.error);
|
|
121
|
+
process.exit(ExitCode.FatalError);
|
|
122
|
+
}
|
|
123
|
+
log.success("Installed node dependencies");
|
|
124
|
+
}
|
|
106
125
|
function hasAppKey(cwd) {
|
|
107
126
|
const envPath = join(cwd, ".env");
|
|
108
127
|
if (!existsSync(envPath))
|
|
@@ -124,26 +143,53 @@ export async function ensureAppKey(cwd) {
|
|
|
124
143
|
}
|
|
125
144
|
log.success("Generated application key");
|
|
126
145
|
}
|
|
146
|
+
async function runInitialMigration(cwd) {
|
|
147
|
+
const appEnv = (process.env.APP_ENV || process.env.NODE_ENV || "local").toLowerCase();
|
|
148
|
+
if (!["local", "development", "dev", "test"].includes(appEnv)) {
|
|
149
|
+
log.info(`Skipping initial migration in the ${appEnv} environment`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
log.info("Running initial database migration...");
|
|
153
|
+
try {
|
|
154
|
+
const result = await runAction(Action.Migrate, { cwd });
|
|
155
|
+
if (result.isErr) {
|
|
156
|
+
log.warn("Initial migration did not complete - you can run it later via ./buddy migrate");
|
|
157
|
+
log.debug(result.error);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
log.success("Database is migrated");
|
|
161
|
+
} catch (error) {
|
|
162
|
+
log.warn("Initial migration did not complete - you can run it later via ./buddy migrate");
|
|
163
|
+
log.debug(error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
127
166
|
async function initializeProject(options) {
|
|
128
167
|
const cwd = options.cwd || p.projectPath();
|
|
129
168
|
await ensurePantryDependencies(cwd);
|
|
169
|
+
await ensureNodeDependencies(cwd);
|
|
130
170
|
await ensureEnvIsSet(options);
|
|
131
171
|
if (!options.skipKeygen)
|
|
132
172
|
await ensureAppKey(cwd);
|
|
173
|
+
await runInitialMigration(cwd);
|
|
133
174
|
if (!options.skipAws) {
|
|
134
175
|
log.info("Ensuring AWS is connected...");
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
176
|
+
try {
|
|
177
|
+
const awsResult = await runCommand("./buddy configure:aws", {
|
|
178
|
+
cwd,
|
|
179
|
+
timeoutMs: AWS_CONFIG_TIMEOUT_MS
|
|
180
|
+
});
|
|
181
|
+
if (awsResult.isErr) {
|
|
182
|
+
log.warn("AWS not configured - you can do this later via ./buddy configure:aws");
|
|
183
|
+
log.debug(awsResult.error);
|
|
184
|
+
} else
|
|
185
|
+
log.success("Configured AWS");
|
|
186
|
+
} catch (error) {
|
|
187
|
+
log.warn("AWS not configured - you can do this later via ./buddy configure:aws");
|
|
188
|
+
log.debug(error);
|
|
142
189
|
}
|
|
143
|
-
log.success("Configured AWS");
|
|
144
190
|
}
|
|
145
191
|
log.success("Project is setup");
|
|
146
|
-
log.info("Happy coding! \uD83D\uDC99");
|
|
192
|
+
log.info("Run `./buddy doctor` anytime to check your setup. Happy coding! \uD83D\uDC99");
|
|
147
193
|
}
|
|
148
194
|
const DB_CONNECTION_PACKAGES = {
|
|
149
195
|
postgres: { name: "postgresql.org", version: "^17.10" },
|
package/dist/commands/types.js
CHANGED
|
@@ -5,7 +5,7 @@ import { onUnknownSubcommand } from "@stacksjs/cli";
|
|
|
5
5
|
export function types(buddy) {
|
|
6
6
|
const descriptions = {
|
|
7
7
|
generate: "Generate the types of & for your library/libraries",
|
|
8
|
-
fix: "
|
|
8
|
+
fix: "Fix the generated types of & for your library/libraries (not yet implemented)",
|
|
9
9
|
project: "Target a specific project",
|
|
10
10
|
verbose: "Enable verbose output"
|
|
11
11
|
};
|
package/dist/lazy-commands.js
CHANGED
|
@@ -12,6 +12,7 @@ const commandRegistry = {
|
|
|
12
12
|
"config:migrate": { path: "./commands/config-migrate.js", exportName: "configMigrate" },
|
|
13
13
|
configure: { path: "./commands/configure.js", exportName: "configure" },
|
|
14
14
|
create: { path: "./commands/create.js", exportName: "create" },
|
|
15
|
+
new: { path: "./commands/create.js", exportName: "create" },
|
|
15
16
|
deploy: { path: "./commands/deploy.js", exportName: "deploy" },
|
|
16
17
|
dev: { path: "./commands/dev.js", exportName: "dev" },
|
|
17
18
|
dns: { path: "./commands/dns.js", exportName: "dns" },
|
|
@@ -25,6 +26,9 @@ const commandRegistry = {
|
|
|
25
26
|
"extension:init": { path: "./commands/extension.js", exportName: "extension" },
|
|
26
27
|
"extension:build": { path: "./commands/extension.js", exportName: "extension" },
|
|
27
28
|
"extension:package": { path: "./commands/extension.js", exportName: "extension" },
|
|
29
|
+
"extension:safari:init": { path: "./commands/extension.js", exportName: "extension" },
|
|
30
|
+
"extension:safari:app": { path: "./commands/extension.js", exportName: "extension" },
|
|
31
|
+
"extension:safari:publish": { path: "./commands/extension.js", exportName: "extension" },
|
|
28
32
|
"dashboard:install": { path: "./commands/features.js", exportName: "features" },
|
|
29
33
|
"dashboard:uninstall": { path: "./commands/features.js", exportName: "features" },
|
|
30
34
|
"commerce:install": { path: "./commands/features.js", exportName: "features" },
|
|
@@ -45,6 +49,8 @@ const commandRegistry = {
|
|
|
45
49
|
install: { path: "./commands/install.js", exportName: "install" },
|
|
46
50
|
key: { path: "./commands/key.js", exportName: "key" },
|
|
47
51
|
lint: { path: "./commands/lint.js", exportName: "lint" },
|
|
52
|
+
format: { path: "./commands/lint.js", exportName: "lint" },
|
|
53
|
+
"format:check": { path: "./commands/lint.js", exportName: "lint" },
|
|
48
54
|
list: { path: "./commands/list.js", exportName: "list" },
|
|
49
55
|
mail: { path: "./commands/mail.js", exportName: "mailCommands" },
|
|
50
56
|
"mail:preview": { path: "./commands/mail.js", exportName: "mailCommands" },
|
|
@@ -52,7 +58,11 @@ const commandRegistry = {
|
|
|
52
58
|
down: { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
53
59
|
up: { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
54
60
|
status: { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
61
|
+
"coming-soon": { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
62
|
+
"coming-soon:status": { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
63
|
+
launch: { path: "./commands/maintenance.js", exportName: "maintenance" },
|
|
55
64
|
make: { path: "./commands/make.js", exportName: "make" },
|
|
65
|
+
"scaffold:crud": { path: "./commands/make.js", exportName: "make" },
|
|
56
66
|
migrate: { path: "./commands/migrate.js", exportName: "migrate" },
|
|
57
67
|
"migrate:fresh": { path: "./commands/migrate.js", exportName: "migrate" },
|
|
58
68
|
"migrate:switch": { path: "./commands/migrate.js", exportName: "migrate" },
|
|
@@ -74,8 +84,11 @@ const commandRegistry = {
|
|
|
74
84
|
release: { path: "./commands/release.js", exportName: "release" },
|
|
75
85
|
route: { path: "./commands/route.js", exportName: "route" },
|
|
76
86
|
saas: { path: "./commands/saas.js", exportName: "saas" },
|
|
87
|
+
"stripe:setup": { path: "./commands/saas.js", exportName: "saas" },
|
|
77
88
|
schedule: { path: "./commands/schedule.js", exportName: "schedule" },
|
|
78
89
|
search: { path: "./commands/search.js", exportName: "search" },
|
|
90
|
+
"search-engine:update": { path: "./commands/search.js", exportName: "search" },
|
|
91
|
+
"search-engine:settings": { path: "./commands/search.js", exportName: "search" },
|
|
79
92
|
seed: { path: "./commands/seed.js", exportName: "seed" },
|
|
80
93
|
"seed:roles": { path: "./commands/seed.js", exportName: "seed" },
|
|
81
94
|
"roles:seed": { path: "./commands/seed.js", exportName: "seed" },
|
|
@@ -177,12 +190,9 @@ export function getCommandsToLoad(args) {
|
|
|
177
190
|
const baseCommand = requestedCommand.split(":")[0];
|
|
178
191
|
if (baseCommand === "list")
|
|
179
192
|
return ["list", ...Object.keys(commandRegistry).filter((k) => k !== "list")];
|
|
193
|
+
if (commandRegistry[requestedCommand])
|
|
194
|
+
return [requestedCommand];
|
|
180
195
|
if (commandRegistry[baseCommand])
|
|
181
196
|
return [baseCommand];
|
|
182
|
-
if (requestedCommand.includes(":")) {
|
|
183
|
-
const namespace = baseCommand;
|
|
184
|
-
if (commandRegistry[namespace])
|
|
185
|
-
return [namespace];
|
|
186
|
-
}
|
|
187
197
|
return Object.keys(commandRegistry);
|
|
188
198
|
}
|