@beignet/cli 0.0.38 → 0.0.40
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 +18 -0
- package/README.md +154 -102
- package/dist/choices.d.ts +17 -21
- package/dist/choices.d.ts.map +1 -1
- package/dist/choices.js +21 -67
- package/dist/choices.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/create-prompts.d.ts +5 -6
- package/dist/create-prompts.d.ts.map +1 -1
- package/dist/create-prompts.js +15 -15
- package/dist/create-prompts.js.map +1 -1
- package/dist/create.d.ts +11 -2
- package/dist/create.d.ts.map +1 -1
- package/dist/create.js +38 -28
- package/dist/create.js.map +1 -1
- package/dist/framework.d.ts +3 -0
- package/dist/framework.d.ts.map +1 -0
- package/dist/framework.js +6 -0
- package/dist/framework.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -47
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +4 -2
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +174 -34
- package/dist/inspect.js.map +1 -1
- package/dist/lib.d.ts +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/make/inbox.js +3 -3
- package/dist/make/inbox.js.map +1 -1
- package/dist/make/payments.d.ts.map +1 -1
- package/dist/make/payments.js +5 -3
- package/dist/make/payments.js.map +1 -1
- package/dist/make/shared.d.ts +10 -3
- package/dist/make/shared.d.ts.map +1 -1
- package/dist/make/shared.js +7 -8
- package/dist/make/shared.js.map +1 -1
- package/dist/make.d.ts +3 -2
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +549 -186
- package/dist/make.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +15 -11
- package/dist/mcp.js.map +1 -1
- package/dist/provider-add.d.ts +21 -3
- package/dist/provider-add.d.ts.map +1 -1
- package/dist/provider-add.js +101 -65
- package/dist/provider-add.js.map +1 -1
- package/dist/task.js +1 -1
- package/dist/task.js.map +1 -1
- package/dist/templates/base.d.ts +1 -1
- package/dist/templates/base.d.ts.map +1 -1
- package/dist/templates/base.js +15 -15
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/index.d.ts +2 -2
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +5 -5
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +17 -13
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shadcn.js +1 -1
- package/dist/templates/shared.d.ts +4 -4
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +6 -6
- package/dist/templates/shared.js.map +1 -1
- package/package.json +2 -2
- package/skills/app-structure/SKILL.md +29 -9
- package/src/choices.ts +38 -88
- package/src/config.ts +7 -3
- package/src/create-prompts.ts +20 -21
- package/src/create.ts +54 -36
- package/src/framework.ts +13 -0
- package/src/index.ts +193 -65
- package/src/inspect.ts +290 -39
- package/src/lib.ts +1 -1
- package/src/make/inbox.ts +3 -3
- package/src/make/payments.ts +10 -3
- package/src/make/shared.ts +16 -10
- package/src/make.ts +720 -176
- package/src/mcp.ts +20 -13
- package/src/provider-add.ts +159 -79
- package/src/task.ts +1 -1
- package/src/templates/base.ts +16 -16
- package/src/templates/index.ts +6 -6
- package/src/templates/server.ts +17 -13
- package/src/templates/shadcn.ts +1 -1
- package/src/templates/shared.ts +10 -10
- package/src/test-helpers/generated-app.ts +2 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { buildApplication, buildCommand, buildRouteMap, proposeCompletions, run, text_en, } from "@stricli/core";
|
|
5
|
-
import { completionShellChoices,
|
|
5
|
+
import { completionShellChoices, createProviderChoices, databaseChoices, databaseStartCommand, makeFeatureAddonChoices, makeFeatureRecipeChoices, packageManagerChoices, providerPresetChoices, splitCreateProviders, templateChoices, } from "./choices.js";
|
|
6
6
|
import { getCliVersion } from "./version.js";
|
|
7
7
|
const outputFormatChoices = [
|
|
8
8
|
"human",
|
|
@@ -50,11 +50,17 @@ const parseDate = (input) => {
|
|
|
50
50
|
}
|
|
51
51
|
return value;
|
|
52
52
|
};
|
|
53
|
-
const
|
|
53
|
+
const createForceFlag = {
|
|
54
54
|
kind: "boolean",
|
|
55
55
|
optional: true,
|
|
56
56
|
withNegated: false,
|
|
57
|
-
brief: "
|
|
57
|
+
brief: "Create the app in a non-empty directory and overwrite conflicts.",
|
|
58
|
+
};
|
|
59
|
+
const makeForceFlag = {
|
|
60
|
+
kind: "boolean",
|
|
61
|
+
optional: true,
|
|
62
|
+
withNegated: false,
|
|
63
|
+
brief: "Overwrite conflicting generated files.",
|
|
58
64
|
};
|
|
59
65
|
const dryRunFlag = {
|
|
60
66
|
kind: "boolean",
|
|
@@ -86,7 +92,7 @@ const parsedDateFlag = (brief) => ({
|
|
|
86
92
|
optional: true,
|
|
87
93
|
brief,
|
|
88
94
|
});
|
|
89
|
-
const cwdFlag = parsedStringFlag("App directory
|
|
95
|
+
const cwdFlag = parsedStringFlag("App directory. Defaults to the current working directory.");
|
|
90
96
|
const formatFlag = {
|
|
91
97
|
kind: "enum",
|
|
92
98
|
values: outputFormatChoices,
|
|
@@ -94,9 +100,10 @@ const formatFlag = {
|
|
|
94
100
|
brief: "Output format. Defaults to human, or github when GITHUB_ACTIONS=true.",
|
|
95
101
|
};
|
|
96
102
|
const makeFlagParameters = {
|
|
97
|
-
force:
|
|
103
|
+
force: makeForceFlag,
|
|
98
104
|
dryRun: dryRunFlag,
|
|
99
105
|
json: jsonFlag,
|
|
106
|
+
cwd: cwdFlag,
|
|
100
107
|
};
|
|
101
108
|
const routesFlagParameters = {
|
|
102
109
|
json: jsonFlag,
|
|
@@ -119,6 +126,7 @@ const providerAddFlagParameters = {
|
|
|
119
126
|
const dbFlagParameters = {
|
|
120
127
|
json: jsonFlag,
|
|
121
128
|
dryRun: dryRunFlag,
|
|
129
|
+
cwd: cwdFlag,
|
|
122
130
|
};
|
|
123
131
|
const dbSchemaSyncFlagParameters = {
|
|
124
132
|
...dbFlagParameters,
|
|
@@ -142,6 +150,7 @@ const taskRunFlagParameters = {
|
|
|
142
150
|
input: parsedStringFlag("JSON input passed to the task schema."),
|
|
143
151
|
tenant: parsedStringFlag("Tenant id or slug passed to the app's createTaskContext, separate from task input."),
|
|
144
152
|
module: parsedStringFlag("Task registry module. Defaults to server/tasks.ts."),
|
|
153
|
+
cwd: cwdFlag,
|
|
145
154
|
};
|
|
146
155
|
const outboxDrainFlagParameters = {
|
|
147
156
|
json: jsonFlag,
|
|
@@ -152,6 +161,7 @@ const outboxDrainFlagParameters = {
|
|
|
152
161
|
optional: true,
|
|
153
162
|
brief: "Maximum messages to claim in one drain pass.",
|
|
154
163
|
},
|
|
164
|
+
cwd: cwdFlag,
|
|
155
165
|
};
|
|
156
166
|
const outboxListFlagParameters = {
|
|
157
167
|
json: jsonFlag,
|
|
@@ -175,10 +185,12 @@ const outboxListFlagParameters = {
|
|
|
175
185
|
optional: true,
|
|
176
186
|
brief: "Maximum messages to return. Defaults to 50.",
|
|
177
187
|
},
|
|
188
|
+
cwd: cwdFlag,
|
|
178
189
|
};
|
|
179
190
|
const outboxShowFlagParameters = {
|
|
180
191
|
json: jsonFlag,
|
|
181
192
|
module: parsedStringFlag("Outbox registry module. Defaults to server/outbox.ts."),
|
|
193
|
+
cwd: cwdFlag,
|
|
182
194
|
};
|
|
183
195
|
const outboxRequeueFlagParameters = {
|
|
184
196
|
json: jsonFlag,
|
|
@@ -190,6 +202,7 @@ const outboxRequeueFlagParameters = {
|
|
|
190
202
|
withNegated: false,
|
|
191
203
|
brief: "Reset attempts to zero before requeueing.",
|
|
192
204
|
},
|
|
205
|
+
cwd: cwdFlag,
|
|
193
206
|
};
|
|
194
207
|
const outboxPurgeFlagParameters = {
|
|
195
208
|
json: jsonFlag,
|
|
@@ -208,6 +221,7 @@ const outboxPurgeFlagParameters = {
|
|
|
208
221
|
brief: "Maximum messages to purge.",
|
|
209
222
|
},
|
|
210
223
|
dryRun: operationDryRunFlag,
|
|
224
|
+
cwd: cwdFlag,
|
|
211
225
|
};
|
|
212
226
|
const outboxPruneFlagParameters = {
|
|
213
227
|
json: jsonFlag,
|
|
@@ -220,12 +234,13 @@ const outboxPruneFlagParameters = {
|
|
|
220
234
|
brief: "Maximum messages to prune.",
|
|
221
235
|
},
|
|
222
236
|
dryRun: operationDryRunFlag,
|
|
237
|
+
cwd: cwdFlag,
|
|
223
238
|
};
|
|
224
239
|
const scheduleRunFlagParameters = {
|
|
225
240
|
json: jsonFlag,
|
|
226
241
|
module: parsedStringFlag("Schedule registry module. Defaults to server/schedules.ts."),
|
|
227
242
|
payload: parsedStringFlag("JSON payload passed to the schedule schema."),
|
|
228
|
-
|
|
243
|
+
runId: parsedStringFlag("Provider or app schedule run ID."),
|
|
229
244
|
attempt: {
|
|
230
245
|
kind: "parsed",
|
|
231
246
|
parse: parsePositiveInteger,
|
|
@@ -235,6 +250,7 @@ const scheduleRunFlagParameters = {
|
|
|
235
250
|
scheduledAt: parsedStringFlag("Provider scheduled timestamp."),
|
|
236
251
|
triggeredAt: parsedStringFlag("Schedule trigger timestamp."),
|
|
237
252
|
source: parsedStringFlag("Provider or app source label."),
|
|
253
|
+
cwd: cwdFlag,
|
|
238
254
|
};
|
|
239
255
|
const namePositional = {
|
|
240
256
|
kind: "tuple",
|
|
@@ -289,11 +305,11 @@ and a shadcn UI shell. Pass --api for an API-only scaffold without the
|
|
|
289
305
|
UI shell, and --db to choose the database.
|
|
290
306
|
|
|
291
307
|
Available databases: ${databaseChoices.join(", ")}
|
|
292
|
-
Available
|
|
308
|
+
Available providers: ${createProviderChoices.join(", ")}
|
|
293
309
|
|
|
294
|
-
--
|
|
295
|
-
|
|
296
|
-
|
|
310
|
+
--providers accepts the full beignet provider add preset catalog. Providers
|
|
311
|
+
with starter-native setup are rendered directly; the rest use the same
|
|
312
|
+
machinery as beignet provider add.
|
|
297
313
|
|
|
298
314
|
Running create on an interactive terminal without selection flags opens a
|
|
299
315
|
prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
@@ -324,12 +340,12 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
324
340
|
optional: true,
|
|
325
341
|
brief: "Package manager to use in next-step commands.",
|
|
326
342
|
},
|
|
327
|
-
|
|
343
|
+
providers: {
|
|
328
344
|
kind: "enum",
|
|
329
|
-
values:
|
|
345
|
+
values: createProviderChoices,
|
|
330
346
|
optional: true,
|
|
331
347
|
variadic: ",",
|
|
332
|
-
brief: "Add
|
|
348
|
+
brief: "Add provider presets as a comma-separated list.",
|
|
333
349
|
},
|
|
334
350
|
yes: {
|
|
335
351
|
kind: "boolean",
|
|
@@ -337,7 +353,7 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
337
353
|
withNegated: false,
|
|
338
354
|
brief: "Skip interactive prompts and use the defaults.",
|
|
339
355
|
},
|
|
340
|
-
force:
|
|
356
|
+
force: createForceFlag,
|
|
341
357
|
dryRun: dryRunFlag,
|
|
342
358
|
json: jsonFlag,
|
|
343
359
|
},
|
|
@@ -354,14 +370,14 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
354
370
|
},
|
|
355
371
|
},
|
|
356
372
|
loader: async () => {
|
|
357
|
-
const { createProject } = await import("./create.js");
|
|
373
|
+
const { createProject, planCreateProject } = await import("./create.js");
|
|
358
374
|
const { promptCreateSelections, shouldPromptInteractively } = await import("./create-prompts.js");
|
|
359
375
|
return async function runCreate(flags, directory) {
|
|
360
376
|
let selections = {
|
|
361
377
|
directory,
|
|
362
378
|
api: flags.api,
|
|
363
379
|
db: flags.db,
|
|
364
|
-
|
|
380
|
+
providers: flags.providers,
|
|
365
381
|
packageManager: flags.packageManager,
|
|
366
382
|
};
|
|
367
383
|
const interactive = shouldPromptInteractively({ ...selections, yes: flags.yes }, {
|
|
@@ -382,34 +398,65 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
382
398
|
}
|
|
383
399
|
const api = selections.api ?? false;
|
|
384
400
|
const database = selections.db ?? "sqlite";
|
|
385
|
-
const {
|
|
401
|
+
const { starterProviders, presets } = splitCreateProviders(uniqueValues([...(selections.providers ?? [])]));
|
|
386
402
|
let presetsNeedEnv = false;
|
|
387
403
|
if (presets.length > 0) {
|
|
388
404
|
const { assertCompatibleCreatePresets, providerPresetNeedsEnv } = await import("./provider-add.js");
|
|
389
|
-
assertCompatibleCreatePresets(presets,
|
|
405
|
+
assertCompatibleCreatePresets(presets, starterProviders);
|
|
390
406
|
presetsNeedEnv = presets.some(providerPresetNeedsEnv);
|
|
391
407
|
}
|
|
392
|
-
const
|
|
408
|
+
const createOptions = {
|
|
393
409
|
name: selections.directory,
|
|
394
410
|
template: flags.template,
|
|
395
411
|
api,
|
|
396
412
|
packageManager: selections.packageManager,
|
|
397
|
-
|
|
413
|
+
providers: starterProviders,
|
|
398
414
|
db: database,
|
|
399
415
|
force: Boolean(flags.force),
|
|
400
416
|
dryRun: Boolean(flags.dryRun),
|
|
401
|
-
}
|
|
417
|
+
};
|
|
418
|
+
let result;
|
|
419
|
+
if (flags.dryRun) {
|
|
420
|
+
const plan = await planCreateProject(createOptions);
|
|
421
|
+
if (presets.length === 0) {
|
|
422
|
+
result = plan.result;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
const { planProviderPresetsForCreate } = await import("./provider-add.js");
|
|
426
|
+
const providerPlan = await planProviderPresetsForCreate({
|
|
427
|
+
targetDir: plan.result.targetDir,
|
|
428
|
+
files: plan.files,
|
|
429
|
+
names: presets,
|
|
430
|
+
});
|
|
431
|
+
result = {
|
|
432
|
+
...plan.result,
|
|
433
|
+
files: providerPlan.files.map((file) => file.path),
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
result = await createProject(createOptions);
|
|
439
|
+
}
|
|
402
440
|
if (!flags.dryRun && presets.length > 0) {
|
|
403
441
|
const { addProviderPreset } = await import("./provider-add.js");
|
|
442
|
+
const presetFiles = [];
|
|
404
443
|
for (const preset of presets) {
|
|
405
|
-
await addProviderPreset({
|
|
444
|
+
const presetResult = await addProviderPreset({
|
|
445
|
+
name: preset,
|
|
446
|
+
cwd: result.targetDir,
|
|
447
|
+
});
|
|
448
|
+
presetFiles.push(...presetResult.files);
|
|
406
449
|
}
|
|
450
|
+
result = {
|
|
451
|
+
...result,
|
|
452
|
+
files: uniqueValues([...result.files, ...presetFiles]),
|
|
453
|
+
};
|
|
407
454
|
}
|
|
408
455
|
writeOutput(this, flags.json
|
|
409
|
-
? JSON.stringify({ ...result,
|
|
456
|
+
? JSON.stringify({ ...result, providers: selections.providers ?? [] }, null, 2)
|
|
410
457
|
: nextSteps(result, {
|
|
411
458
|
api,
|
|
412
|
-
|
|
459
|
+
providers: starterProviders,
|
|
413
460
|
database,
|
|
414
461
|
presets,
|
|
415
462
|
presetsNeedEnv,
|
|
@@ -679,6 +726,7 @@ function databaseCommand(command) {
|
|
|
679
726
|
return async function runDb(flags) {
|
|
680
727
|
const result = await runDatabaseCommand({
|
|
681
728
|
command,
|
|
729
|
+
cwd: flags.cwd,
|
|
682
730
|
captureOutput: Boolean(flags.json),
|
|
683
731
|
dryRun: Boolean(flags.dryRun),
|
|
684
732
|
});
|
|
@@ -704,6 +752,7 @@ const dbSchemaSyncCommand = buildCommand({
|
|
|
704
752
|
const { syncDatabaseSchema } = await import("./db.js");
|
|
705
753
|
return async function runDbSchemaSync(flags) {
|
|
706
754
|
const result = await syncDatabaseSchema({
|
|
755
|
+
cwd: flags.cwd,
|
|
707
756
|
dialect: flags.dialect,
|
|
708
757
|
tables: flags.tables,
|
|
709
758
|
output: flags.output,
|
|
@@ -748,6 +797,7 @@ const taskRunCommand = buildCommand({
|
|
|
748
797
|
return async function runTask(flags, name) {
|
|
749
798
|
const result = await runAppTask({
|
|
750
799
|
name,
|
|
800
|
+
cwd: flags.cwd,
|
|
751
801
|
input: flags.input,
|
|
752
802
|
tenant: flags.tenant,
|
|
753
803
|
modulePath: flags.module,
|
|
@@ -777,6 +827,7 @@ const outboxDrainCommand = buildCommand({
|
|
|
777
827
|
const { runOutboxDrain } = await import("./outbox.js");
|
|
778
828
|
return async function runDrain(flags) {
|
|
779
829
|
const result = await runOutboxDrain({
|
|
830
|
+
cwd: flags.cwd,
|
|
780
831
|
modulePath: flags.module,
|
|
781
832
|
batchSize: flags.batchSize,
|
|
782
833
|
});
|
|
@@ -797,6 +848,7 @@ const outboxListCommand = buildCommand({
|
|
|
797
848
|
const { runOutboxList } = await import("./outbox.js");
|
|
798
849
|
return async function runList(flags) {
|
|
799
850
|
const result = await runOutboxList({
|
|
851
|
+
cwd: flags.cwd,
|
|
800
852
|
modulePath: flags.module,
|
|
801
853
|
status: flags.status,
|
|
802
854
|
kind: flags.kind,
|
|
@@ -821,6 +873,7 @@ const outboxShowCommand = buildCommand({
|
|
|
821
873
|
const { runOutboxShow } = await import("./outbox.js");
|
|
822
874
|
return async function runShow(flags, id) {
|
|
823
875
|
const result = await runOutboxShow({
|
|
876
|
+
cwd: flags.cwd,
|
|
824
877
|
modulePath: flags.module,
|
|
825
878
|
id,
|
|
826
879
|
});
|
|
@@ -842,6 +895,7 @@ const outboxRequeueCommand = buildCommand({
|
|
|
842
895
|
const { runOutboxRequeue } = await import("./outbox.js");
|
|
843
896
|
return async function runRequeue(flags, id) {
|
|
844
897
|
const result = await runOutboxRequeue({
|
|
898
|
+
cwd: flags.cwd,
|
|
845
899
|
modulePath: flags.module,
|
|
846
900
|
id,
|
|
847
901
|
availableAt: flags.availableAt,
|
|
@@ -864,6 +918,7 @@ const outboxPurgeCommand = buildCommand({
|
|
|
864
918
|
const { runOutboxPurge } = await import("./outbox.js");
|
|
865
919
|
return async function runPurge(flags) {
|
|
866
920
|
const result = await runOutboxPurge({
|
|
921
|
+
cwd: flags.cwd,
|
|
867
922
|
modulePath: flags.module,
|
|
868
923
|
before: flags.before,
|
|
869
924
|
all: Boolean(flags.all),
|
|
@@ -890,6 +945,7 @@ const outboxPruneCommand = buildCommand({
|
|
|
890
945
|
throw new Error("Pass --before <date> to prune delivered messages.");
|
|
891
946
|
}
|
|
892
947
|
const result = await runOutboxPrune({
|
|
948
|
+
cwd: flags.cwd,
|
|
893
949
|
modulePath: flags.module,
|
|
894
950
|
before: flags.before,
|
|
895
951
|
limit: flags.limit,
|
|
@@ -927,9 +983,10 @@ const scheduleRunCommand = buildCommand({
|
|
|
927
983
|
return async function runSchedule(flags, name) {
|
|
928
984
|
const result = await runAppSchedule({
|
|
929
985
|
name,
|
|
986
|
+
cwd: flags.cwd,
|
|
930
987
|
modulePath: flags.module,
|
|
931
988
|
payload: flags.payload,
|
|
932
|
-
id: flags.
|
|
989
|
+
id: flags.runId,
|
|
933
990
|
attempt: flags.attempt,
|
|
934
991
|
scheduledAt: flags.scheduledAt,
|
|
935
992
|
triggeredAt: flags.triggeredAt,
|
|
@@ -1012,13 +1069,13 @@ const makeResourceCommand = buildCommand({
|
|
|
1012
1069
|
parameters: {
|
|
1013
1070
|
flags: {
|
|
1014
1071
|
...makeFlagParameters,
|
|
1015
|
-
|
|
1072
|
+
authorization: {
|
|
1016
1073
|
kind: "boolean",
|
|
1017
1074
|
optional: true,
|
|
1018
1075
|
withNegated: false,
|
|
1019
1076
|
brief: "Generate policy metadata and use-case authorization checks for mutating routes.",
|
|
1020
1077
|
},
|
|
1021
|
-
|
|
1078
|
+
tenantScoped: {
|
|
1022
1079
|
kind: "boolean",
|
|
1023
1080
|
optional: true,
|
|
1024
1081
|
withNegated: false,
|
|
@@ -1044,10 +1101,11 @@ const makeResourceCommand = buildCommand({
|
|
|
1044
1101
|
return async function runMakeResource(flags, name) {
|
|
1045
1102
|
const result = await makeResource({
|
|
1046
1103
|
name,
|
|
1104
|
+
cwd: flags.cwd,
|
|
1047
1105
|
force: Boolean(flags.force),
|
|
1048
1106
|
dryRun: Boolean(flags.dryRun),
|
|
1049
|
-
|
|
1050
|
-
|
|
1107
|
+
authorization: Boolean(flags.authorization),
|
|
1108
|
+
tenantScoped: Boolean(flags.tenantScoped),
|
|
1051
1109
|
events: Boolean(flags.events),
|
|
1052
1110
|
softDelete: Boolean(flags.softDelete),
|
|
1053
1111
|
});
|
|
@@ -1069,7 +1127,7 @@ const makeFeatureCommand = buildCommand({
|
|
|
1069
1127
|
values: makeFeatureAddonChoices,
|
|
1070
1128
|
optional: true,
|
|
1071
1129
|
variadic: ",",
|
|
1072
|
-
brief: "Add feature-owned artifacts. Supports policy, factory
|
|
1130
|
+
brief: "Add feature-owned artifacts. Supports policy, factory, seed, task, event, listener, job, notification, schedule, ui, and upload.",
|
|
1073
1131
|
},
|
|
1074
1132
|
recipe: {
|
|
1075
1133
|
kind: "enum",
|
|
@@ -1085,6 +1143,7 @@ const makeFeatureCommand = buildCommand({
|
|
|
1085
1143
|
return async function runMakeFeature(flags, name) {
|
|
1086
1144
|
const result = await makeFeature({
|
|
1087
1145
|
name,
|
|
1146
|
+
cwd: flags.cwd,
|
|
1088
1147
|
with: flags.with,
|
|
1089
1148
|
recipe: flags.recipe,
|
|
1090
1149
|
force: Boolean(flags.force),
|
|
@@ -1110,6 +1169,7 @@ function simpleMakeCommand(generator, brief, formatNextSteps) {
|
|
|
1110
1169
|
return async function runMake(flags, name) {
|
|
1111
1170
|
const result = await generators[generator]({
|
|
1112
1171
|
name,
|
|
1172
|
+
cwd: flags.cwd,
|
|
1113
1173
|
force: Boolean(flags.force),
|
|
1114
1174
|
dryRun: Boolean(flags.dryRun),
|
|
1115
1175
|
});
|
|
@@ -1120,6 +1180,38 @@ function simpleMakeCommand(generator, brief, formatNextSteps) {
|
|
|
1120
1180
|
},
|
|
1121
1181
|
});
|
|
1122
1182
|
}
|
|
1183
|
+
const makeUploadCommand = buildCommand({
|
|
1184
|
+
docs: {
|
|
1185
|
+
brief: "Generate a feature upload.",
|
|
1186
|
+
},
|
|
1187
|
+
parameters: {
|
|
1188
|
+
flags: {
|
|
1189
|
+
...makeFlagParameters,
|
|
1190
|
+
ui: {
|
|
1191
|
+
kind: "boolean",
|
|
1192
|
+
optional: true,
|
|
1193
|
+
withNegated: false,
|
|
1194
|
+
brief: "Generate a typed React upload client, uploader component, and component test.",
|
|
1195
|
+
},
|
|
1196
|
+
},
|
|
1197
|
+
positional: namePositional,
|
|
1198
|
+
},
|
|
1199
|
+
loader: async () => {
|
|
1200
|
+
const { makeUpload } = await import("./make.js");
|
|
1201
|
+
return async function runMakeUpload(flags, name) {
|
|
1202
|
+
const result = await makeUpload({
|
|
1203
|
+
name,
|
|
1204
|
+
cwd: flags.cwd,
|
|
1205
|
+
force: Boolean(flags.force),
|
|
1206
|
+
dryRun: Boolean(flags.dryRun),
|
|
1207
|
+
ui: Boolean(flags.ui),
|
|
1208
|
+
});
|
|
1209
|
+
writeOutput(this, flags.json
|
|
1210
|
+
? JSON.stringify(result, null, 2)
|
|
1211
|
+
: makeUploadNextSteps(result));
|
|
1212
|
+
};
|
|
1213
|
+
},
|
|
1214
|
+
});
|
|
1123
1215
|
const makeListenerCommand = buildCommand({
|
|
1124
1216
|
docs: {
|
|
1125
1217
|
brief: "Generate a feature event listener.",
|
|
@@ -1127,7 +1219,7 @@ const makeListenerCommand = buildCommand({
|
|
|
1127
1219
|
parameters: {
|
|
1128
1220
|
flags: {
|
|
1129
1221
|
...makeFlagParameters,
|
|
1130
|
-
event: parsedStringFlag("Event to listen to, for example posts
|
|
1222
|
+
event: parsedStringFlag("Event to listen to, for example posts.published."),
|
|
1131
1223
|
},
|
|
1132
1224
|
positional: namePositional,
|
|
1133
1225
|
},
|
|
@@ -1135,10 +1227,11 @@ const makeListenerCommand = buildCommand({
|
|
|
1135
1227
|
const { makeListener } = await import("./make.js");
|
|
1136
1228
|
return async function runMakeListener(flags, name) {
|
|
1137
1229
|
if (!flags.event) {
|
|
1138
|
-
throw new Error("beignet make listener requires --event feature
|
|
1230
|
+
throw new Error("beignet make listener requires --event feature.name, for example --event posts.published.");
|
|
1139
1231
|
}
|
|
1140
1232
|
const result = await makeListener({
|
|
1141
1233
|
name,
|
|
1234
|
+
cwd: flags.cwd,
|
|
1142
1235
|
event: flags.event,
|
|
1143
1236
|
force: Boolean(flags.force),
|
|
1144
1237
|
dryRun: Boolean(flags.dryRun),
|
|
@@ -1172,6 +1265,7 @@ const makeScheduleCommand = buildCommand({
|
|
|
1172
1265
|
return async function runMakeSchedule(flags, name) {
|
|
1173
1266
|
const result = await makeSchedule({
|
|
1174
1267
|
name,
|
|
1268
|
+
cwd: flags.cwd,
|
|
1175
1269
|
cron: flags.cron,
|
|
1176
1270
|
timezone: flags.timezone,
|
|
1177
1271
|
route: Boolean(flags.route),
|
|
@@ -1195,6 +1289,7 @@ const makePaymentsCommand = buildCommand({
|
|
|
1195
1289
|
const { makePayments, makePaymentsNextStepLines } = await import("./make.js");
|
|
1196
1290
|
return async function runMakePayments(flags) {
|
|
1197
1291
|
const result = await makePayments({
|
|
1292
|
+
cwd: flags.cwd,
|
|
1198
1293
|
force: Boolean(flags.force),
|
|
1199
1294
|
dryRun: Boolean(flags.dryRun),
|
|
1200
1295
|
});
|
|
@@ -1215,6 +1310,7 @@ const makeTenancyCommand = buildCommand({
|
|
|
1215
1310
|
const { makeTenancy, makeTenancyNextStepLines } = await import("./make.js");
|
|
1216
1311
|
return async function runMakeTenancy(flags) {
|
|
1217
1312
|
const result = await makeTenancy({
|
|
1313
|
+
cwd: flags.cwd,
|
|
1218
1314
|
force: Boolean(flags.force),
|
|
1219
1315
|
dryRun: Boolean(flags.dryRun),
|
|
1220
1316
|
});
|
|
@@ -1235,6 +1331,7 @@ const makeInboxCommand = buildCommand({
|
|
|
1235
1331
|
const { makeInbox, makeInboxNextStepLines } = await import("./make.js");
|
|
1236
1332
|
return async function runMakeInbox(flags) {
|
|
1237
1333
|
const result = await makeInbox({
|
|
1334
|
+
cwd: flags.cwd,
|
|
1238
1335
|
force: Boolean(flags.force),
|
|
1239
1336
|
dryRun: Boolean(flags.dryRun),
|
|
1240
1337
|
});
|
|
@@ -1255,6 +1352,7 @@ const makeOutboxCommand = buildCommand({
|
|
|
1255
1352
|
const { makeOutbox } = await import("./make.js");
|
|
1256
1353
|
return async function runMakeOutbox(flags) {
|
|
1257
1354
|
const result = await makeOutbox({
|
|
1355
|
+
cwd: flags.cwd,
|
|
1258
1356
|
force: Boolean(flags.force),
|
|
1259
1357
|
dryRun: Boolean(flags.dryRun),
|
|
1260
1358
|
});
|
|
@@ -1288,7 +1386,7 @@ const makeRoutes = buildRouteMap({
|
|
|
1288
1386
|
task: simpleMakeCommand("makeTask", "Generate a feature operational task.", makeTaskNextSteps),
|
|
1289
1387
|
tenancy: makeTenancyCommand,
|
|
1290
1388
|
test: simpleMakeCommand("makeTest", "Generate a use case test.", makeTestNextSteps),
|
|
1291
|
-
upload:
|
|
1389
|
+
upload: makeUploadCommand,
|
|
1292
1390
|
useCase: simpleMakeCommand("makeUseCase", "Generate a use case.", makeUseCaseNextSteps),
|
|
1293
1391
|
},
|
|
1294
1392
|
});
|
|
@@ -1310,15 +1408,11 @@ Run npm create beignet@latest (or bun create beignet) to scaffold a new app.`,
|
|
|
1310
1408
|
mcp: mcpCommand,
|
|
1311
1409
|
outbox: outboxRoutes,
|
|
1312
1410
|
preflight: preflightCommand,
|
|
1313
|
-
|
|
1411
|
+
provider: providerRoutes,
|
|
1314
1412
|
routes: routesCommand,
|
|
1315
1413
|
schedule: scheduleRoutes,
|
|
1316
1414
|
task: taskRoutes,
|
|
1317
1415
|
},
|
|
1318
|
-
aliases: {
|
|
1319
|
-
// The singular form is a common near-miss for the providers commands.
|
|
1320
|
-
provider: "providers",
|
|
1321
|
-
},
|
|
1322
1416
|
});
|
|
1323
1417
|
const cli = buildApplication(rootRoutes, {
|
|
1324
1418
|
name: "beignet",
|
|
@@ -1433,7 +1527,7 @@ function nextSteps(result, options = {}) {
|
|
|
1433
1527
|
if (result.dryRun) {
|
|
1434
1528
|
const plannedFiles = result.files.map((file) => ` ${file}`).join("\n");
|
|
1435
1529
|
const plannedPresets = options.presets && options.presets.length > 0
|
|
1436
|
-
? `\n\nProvider presets
|
|
1530
|
+
? `\n\nProvider presets included in this plan:\n${options.presets
|
|
1437
1531
|
.map((preset) => ` ${preset}`)
|
|
1438
1532
|
.join("\n")}`
|
|
1439
1533
|
: "";
|
|
@@ -1445,14 +1539,14 @@ ${plannedFiles}${plannedPresets}`;
|
|
|
1445
1539
|
const pm = result.packageManager;
|
|
1446
1540
|
const run = pm === "npm" ? "npm run" : `${pm} run`;
|
|
1447
1541
|
const cli = packageRunnerFromPackageManager(pm);
|
|
1448
|
-
const
|
|
1449
|
-
const envStep =
|
|
1450
|
-
? " Fill .env.local for selected
|
|
1542
|
+
const envRequiredProviders = options.providers?.filter(isEnvRequiredStarterProvider) ?? [];
|
|
1543
|
+
const envStep = envRequiredProviders.length > 0 || options.presetsNeedEnv
|
|
1544
|
+
? " Fill .env.local for selected providers before starting the app.\n"
|
|
1451
1545
|
: "";
|
|
1452
1546
|
const presetSection = options.presets && options.presets.length > 0
|
|
1453
1547
|
? `\nProvider presets applied:\n${options.presets
|
|
1454
1548
|
.map((preset) => ` ${preset}`)
|
|
1455
|
-
.join("\n")}\n See docs/
|
|
1549
|
+
.join("\n")}\n See docs/providers.md for setup notes and follow-up steps.\n`
|
|
1456
1550
|
: "";
|
|
1457
1551
|
const openStep = options.api
|
|
1458
1552
|
? " open http://localhost:3000 for the API landing page"
|
|
@@ -1502,10 +1596,10 @@ function packageRunnerFromPackageManager(pm) {
|
|
|
1502
1596
|
return "bun beignet";
|
|
1503
1597
|
}
|
|
1504
1598
|
}
|
|
1505
|
-
function
|
|
1506
|
-
return (
|
|
1507
|
-
|
|
1508
|
-
|
|
1599
|
+
function isEnvRequiredStarterProvider(provider) {
|
|
1600
|
+
return (provider === "jobs-inngest" ||
|
|
1601
|
+
provider === "mail-resend" ||
|
|
1602
|
+
provider === "rate-limit-upstash");
|
|
1509
1603
|
}
|
|
1510
1604
|
function changedFileLines(result) {
|
|
1511
1605
|
return {
|
|
@@ -1676,8 +1770,16 @@ function makeScheduleNextSteps(result, options = {}) {
|
|
|
1676
1770
|
]);
|
|
1677
1771
|
}
|
|
1678
1772
|
function makeUploadNextSteps(result) {
|
|
1773
|
+
const includesUi = result.files.some((file) => file.endsWith("-uploader.tsx"));
|
|
1679
1774
|
return makeNextSteps(result, "upload", [
|
|
1680
1775
|
"Replace the starter metadata, constraints, key, authorization, and onComplete behavior.",
|
|
1776
|
+
...(includesUi
|
|
1777
|
+
? [
|
|
1778
|
+
"Render the generated uploader with its required resourceId and connect onComplete to refresh the owning view.",
|
|
1779
|
+
]
|
|
1780
|
+
: [
|
|
1781
|
+
"Add --ui in a full-stack app when you want a typed upload client, component, and component test.",
|
|
1782
|
+
]),
|
|
1681
1783
|
"Use the generated upload route for local development, then swap the local storage provider for S3-compatible storage before production.",
|
|
1682
1784
|
]);
|
|
1683
1785
|
}
|