@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/src/index.ts
CHANGED
|
@@ -15,13 +15,12 @@ import {
|
|
|
15
15
|
} from "@stricli/core";
|
|
16
16
|
import {
|
|
17
17
|
type CompletionShell,
|
|
18
|
-
type
|
|
18
|
+
type CreateProviderName,
|
|
19
19
|
completionShellChoices,
|
|
20
|
-
|
|
20
|
+
createProviderChoices,
|
|
21
21
|
type DatabaseName,
|
|
22
22
|
databaseChoices,
|
|
23
23
|
databaseStartCommand,
|
|
24
|
-
type IntegrationName,
|
|
25
24
|
type MakeFeatureAddon,
|
|
26
25
|
type MakeFeatureRecipe,
|
|
27
26
|
makeFeatureAddonChoices,
|
|
@@ -30,7 +29,8 @@ import {
|
|
|
30
29
|
type ProviderPresetName,
|
|
31
30
|
packageManagerChoices,
|
|
32
31
|
providerPresetChoices,
|
|
33
|
-
|
|
32
|
+
type StarterProviderName,
|
|
33
|
+
splitCreateProviders,
|
|
34
34
|
type TemplateName,
|
|
35
35
|
templateChoices,
|
|
36
36
|
} from "./choices.js";
|
|
@@ -56,7 +56,7 @@ type CreateFlags = {
|
|
|
56
56
|
api?: boolean;
|
|
57
57
|
db?: DatabaseName;
|
|
58
58
|
packageManager?: PackageManager;
|
|
59
|
-
|
|
59
|
+
providers?: readonly CreateProviderName[];
|
|
60
60
|
yes?: boolean;
|
|
61
61
|
force?: boolean;
|
|
62
62
|
dryRun?: boolean;
|
|
@@ -72,11 +72,12 @@ type MakeFlags = {
|
|
|
72
72
|
force?: boolean;
|
|
73
73
|
dryRun?: boolean;
|
|
74
74
|
json?: boolean;
|
|
75
|
+
cwd?: string;
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
type MakeResourceFlags = MakeFlags & {
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
authorization?: boolean;
|
|
80
|
+
tenantScoped?: boolean;
|
|
80
81
|
events?: boolean;
|
|
81
82
|
softDelete?: boolean;
|
|
82
83
|
};
|
|
@@ -96,6 +97,10 @@ type MakeScheduleFlags = MakeFlags & {
|
|
|
96
97
|
route?: boolean;
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
type MakeUploadFlags = MakeFlags & {
|
|
101
|
+
ui?: boolean;
|
|
102
|
+
};
|
|
103
|
+
|
|
99
104
|
type RoutesFlags = {
|
|
100
105
|
json?: boolean;
|
|
101
106
|
cwd?: string;
|
|
@@ -126,6 +131,7 @@ type PreflightFlags = {
|
|
|
126
131
|
type DbFlags = {
|
|
127
132
|
json?: boolean;
|
|
128
133
|
dryRun?: boolean;
|
|
134
|
+
cwd?: string;
|
|
129
135
|
};
|
|
130
136
|
|
|
131
137
|
type DatabaseSchemaDialect = "sqlite" | "postgres" | "mysql";
|
|
@@ -154,12 +160,14 @@ type TaskRunFlags = {
|
|
|
154
160
|
input?: string;
|
|
155
161
|
tenant?: string;
|
|
156
162
|
module?: string;
|
|
163
|
+
cwd?: string;
|
|
157
164
|
};
|
|
158
165
|
|
|
159
166
|
type OutboxDrainFlags = {
|
|
160
167
|
json?: boolean;
|
|
161
168
|
module?: string;
|
|
162
169
|
batchSize?: number;
|
|
170
|
+
cwd?: string;
|
|
163
171
|
};
|
|
164
172
|
|
|
165
173
|
type OutboxMessageStatus = "pending" | "claimed" | "delivered" | "deadLettered";
|
|
@@ -185,11 +193,13 @@ type OutboxListFlags = {
|
|
|
185
193
|
kind?: OutboxMessageKind;
|
|
186
194
|
name?: string;
|
|
187
195
|
limit?: number;
|
|
196
|
+
cwd?: string;
|
|
188
197
|
};
|
|
189
198
|
|
|
190
199
|
type OutboxShowFlags = {
|
|
191
200
|
json?: boolean;
|
|
192
201
|
module?: string;
|
|
202
|
+
cwd?: string;
|
|
193
203
|
};
|
|
194
204
|
|
|
195
205
|
type OutboxRequeueFlags = {
|
|
@@ -197,6 +207,7 @@ type OutboxRequeueFlags = {
|
|
|
197
207
|
module?: string;
|
|
198
208
|
availableAt?: Date;
|
|
199
209
|
resetAttempts?: boolean;
|
|
210
|
+
cwd?: string;
|
|
200
211
|
};
|
|
201
212
|
|
|
202
213
|
type OutboxPurgeFlags = {
|
|
@@ -206,6 +217,7 @@ type OutboxPurgeFlags = {
|
|
|
206
217
|
all?: boolean;
|
|
207
218
|
limit?: number;
|
|
208
219
|
dryRun?: boolean;
|
|
220
|
+
cwd?: string;
|
|
209
221
|
};
|
|
210
222
|
|
|
211
223
|
type OutboxPruneFlags = {
|
|
@@ -214,17 +226,19 @@ type OutboxPruneFlags = {
|
|
|
214
226
|
before?: Date;
|
|
215
227
|
limit?: number;
|
|
216
228
|
dryRun?: boolean;
|
|
229
|
+
cwd?: string;
|
|
217
230
|
};
|
|
218
231
|
|
|
219
232
|
type ScheduleRunFlags = {
|
|
220
233
|
json?: boolean;
|
|
221
234
|
module?: string;
|
|
222
235
|
payload?: string;
|
|
223
|
-
|
|
236
|
+
runId?: string;
|
|
224
237
|
attempt?: number;
|
|
225
238
|
scheduledAt?: string;
|
|
226
239
|
triggeredAt?: string;
|
|
227
240
|
source?: string;
|
|
241
|
+
cwd?: string;
|
|
228
242
|
};
|
|
229
243
|
|
|
230
244
|
type McpFlags = {
|
|
@@ -277,11 +291,18 @@ const parseDate = (input: string): Date => {
|
|
|
277
291
|
return value;
|
|
278
292
|
};
|
|
279
293
|
|
|
280
|
-
const
|
|
294
|
+
const createForceFlag = {
|
|
295
|
+
kind: "boolean",
|
|
296
|
+
optional: true,
|
|
297
|
+
withNegated: false,
|
|
298
|
+
brief: "Create the app in a non-empty directory and overwrite conflicts.",
|
|
299
|
+
} as const;
|
|
300
|
+
|
|
301
|
+
const makeForceFlag = {
|
|
281
302
|
kind: "boolean",
|
|
282
303
|
optional: true,
|
|
283
304
|
withNegated: false,
|
|
284
|
-
brief: "Overwrite conflicting files
|
|
305
|
+
brief: "Overwrite conflicting generated files.",
|
|
285
306
|
} as const;
|
|
286
307
|
|
|
287
308
|
const dryRunFlag = {
|
|
@@ -322,7 +343,7 @@ const parsedDateFlag = (brief: string) =>
|
|
|
322
343
|
}) as const;
|
|
323
344
|
|
|
324
345
|
const cwdFlag = parsedStringFlag(
|
|
325
|
-
"App directory
|
|
346
|
+
"App directory. Defaults to the current working directory.",
|
|
326
347
|
);
|
|
327
348
|
|
|
328
349
|
const formatFlag = {
|
|
@@ -334,9 +355,10 @@ const formatFlag = {
|
|
|
334
355
|
} as const;
|
|
335
356
|
|
|
336
357
|
const makeFlagParameters = {
|
|
337
|
-
force:
|
|
358
|
+
force: makeForceFlag,
|
|
338
359
|
dryRun: dryRunFlag,
|
|
339
360
|
json: jsonFlag,
|
|
361
|
+
cwd: cwdFlag,
|
|
340
362
|
} satisfies FlagParametersForType<MakeFlags, CliContext>;
|
|
341
363
|
|
|
342
364
|
const routesFlagParameters = {
|
|
@@ -364,6 +386,7 @@ const providerAddFlagParameters = {
|
|
|
364
386
|
const dbFlagParameters = {
|
|
365
387
|
json: jsonFlag,
|
|
366
388
|
dryRun: dryRunFlag,
|
|
389
|
+
cwd: cwdFlag,
|
|
367
390
|
} satisfies FlagParametersForType<DbFlags, CliContext>;
|
|
368
391
|
|
|
369
392
|
const dbSchemaSyncFlagParameters = {
|
|
@@ -397,6 +420,7 @@ const taskRunFlagParameters = {
|
|
|
397
420
|
module: parsedStringFlag(
|
|
398
421
|
"Task registry module. Defaults to server/tasks.ts.",
|
|
399
422
|
),
|
|
423
|
+
cwd: cwdFlag,
|
|
400
424
|
} satisfies FlagParametersForType<TaskRunFlags, CliContext>;
|
|
401
425
|
|
|
402
426
|
const outboxDrainFlagParameters = {
|
|
@@ -410,6 +434,7 @@ const outboxDrainFlagParameters = {
|
|
|
410
434
|
optional: true,
|
|
411
435
|
brief: "Maximum messages to claim in one drain pass.",
|
|
412
436
|
},
|
|
437
|
+
cwd: cwdFlag,
|
|
413
438
|
} satisfies FlagParametersForType<OutboxDrainFlags, CliContext>;
|
|
414
439
|
|
|
415
440
|
const outboxListFlagParameters = {
|
|
@@ -436,6 +461,7 @@ const outboxListFlagParameters = {
|
|
|
436
461
|
optional: true,
|
|
437
462
|
brief: "Maximum messages to return. Defaults to 50.",
|
|
438
463
|
},
|
|
464
|
+
cwd: cwdFlag,
|
|
439
465
|
} satisfies FlagParametersForType<OutboxListFlags, CliContext>;
|
|
440
466
|
|
|
441
467
|
const outboxShowFlagParameters = {
|
|
@@ -443,6 +469,7 @@ const outboxShowFlagParameters = {
|
|
|
443
469
|
module: parsedStringFlag(
|
|
444
470
|
"Outbox registry module. Defaults to server/outbox.ts.",
|
|
445
471
|
),
|
|
472
|
+
cwd: cwdFlag,
|
|
446
473
|
} satisfies FlagParametersForType<OutboxShowFlags, CliContext>;
|
|
447
474
|
|
|
448
475
|
const outboxRequeueFlagParameters = {
|
|
@@ -459,6 +486,7 @@ const outboxRequeueFlagParameters = {
|
|
|
459
486
|
withNegated: false,
|
|
460
487
|
brief: "Reset attempts to zero before requeueing.",
|
|
461
488
|
},
|
|
489
|
+
cwd: cwdFlag,
|
|
462
490
|
} satisfies FlagParametersForType<OutboxRequeueFlags, CliContext>;
|
|
463
491
|
|
|
464
492
|
const outboxPurgeFlagParameters = {
|
|
@@ -482,6 +510,7 @@ const outboxPurgeFlagParameters = {
|
|
|
482
510
|
brief: "Maximum messages to purge.",
|
|
483
511
|
},
|
|
484
512
|
dryRun: operationDryRunFlag,
|
|
513
|
+
cwd: cwdFlag,
|
|
485
514
|
} satisfies FlagParametersForType<OutboxPurgeFlags, CliContext>;
|
|
486
515
|
|
|
487
516
|
const outboxPruneFlagParameters = {
|
|
@@ -499,6 +528,7 @@ const outboxPruneFlagParameters = {
|
|
|
499
528
|
brief: "Maximum messages to prune.",
|
|
500
529
|
},
|
|
501
530
|
dryRun: operationDryRunFlag,
|
|
531
|
+
cwd: cwdFlag,
|
|
502
532
|
} satisfies FlagParametersForType<OutboxPruneFlags, CliContext>;
|
|
503
533
|
|
|
504
534
|
const scheduleRunFlagParameters = {
|
|
@@ -507,7 +537,7 @@ const scheduleRunFlagParameters = {
|
|
|
507
537
|
"Schedule registry module. Defaults to server/schedules.ts.",
|
|
508
538
|
),
|
|
509
539
|
payload: parsedStringFlag("JSON payload passed to the schedule schema."),
|
|
510
|
-
|
|
540
|
+
runId: parsedStringFlag("Provider or app schedule run ID."),
|
|
511
541
|
attempt: {
|
|
512
542
|
kind: "parsed",
|
|
513
543
|
parse: parsePositiveInteger,
|
|
@@ -517,6 +547,7 @@ const scheduleRunFlagParameters = {
|
|
|
517
547
|
scheduledAt: parsedStringFlag("Provider scheduled timestamp."),
|
|
518
548
|
triggeredAt: parsedStringFlag("Schedule trigger timestamp."),
|
|
519
549
|
source: parsedStringFlag("Provider or app source label."),
|
|
550
|
+
cwd: cwdFlag,
|
|
520
551
|
} satisfies FlagParametersForType<ScheduleRunFlags, CliContext>;
|
|
521
552
|
|
|
522
553
|
const namePositional = {
|
|
@@ -588,11 +619,11 @@ and a shadcn UI shell. Pass --api for an API-only scaffold without the
|
|
|
588
619
|
UI shell, and --db to choose the database.
|
|
589
620
|
|
|
590
621
|
Available databases: ${databaseChoices.join(", ")}
|
|
591
|
-
Available
|
|
622
|
+
Available providers: ${createProviderChoices.join(", ")}
|
|
592
623
|
|
|
593
|
-
--
|
|
594
|
-
|
|
595
|
-
|
|
624
|
+
--providers accepts the full beignet provider add preset catalog. Providers
|
|
625
|
+
with starter-native setup are rendered directly; the rest use the same
|
|
626
|
+
machinery as beignet provider add.
|
|
596
627
|
|
|
597
628
|
Running create on an interactive terminal without selection flags opens a
|
|
598
629
|
prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
@@ -623,13 +654,12 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
623
654
|
optional: true,
|
|
624
655
|
brief: "Package manager to use in next-step commands.",
|
|
625
656
|
},
|
|
626
|
-
|
|
657
|
+
providers: {
|
|
627
658
|
kind: "enum",
|
|
628
|
-
values:
|
|
659
|
+
values: createProviderChoices,
|
|
629
660
|
optional: true,
|
|
630
661
|
variadic: ",",
|
|
631
|
-
brief:
|
|
632
|
-
"Add first-party integrations or provider presets as a comma-separated list.",
|
|
662
|
+
brief: "Add provider presets as a comma-separated list.",
|
|
633
663
|
},
|
|
634
664
|
yes: {
|
|
635
665
|
kind: "boolean",
|
|
@@ -637,7 +667,7 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
637
667
|
withNegated: false,
|
|
638
668
|
brief: "Skip interactive prompts and use the defaults.",
|
|
639
669
|
},
|
|
640
|
-
force:
|
|
670
|
+
force: createForceFlag,
|
|
641
671
|
dryRun: dryRunFlag,
|
|
642
672
|
json: jsonFlag,
|
|
643
673
|
},
|
|
@@ -654,7 +684,7 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
654
684
|
},
|
|
655
685
|
},
|
|
656
686
|
loader: async () => {
|
|
657
|
-
const { createProject } = await import("./create.js");
|
|
687
|
+
const { createProject, planCreateProject } = await import("./create.js");
|
|
658
688
|
const { promptCreateSelections, shouldPromptInteractively } = await import(
|
|
659
689
|
"./create-prompts.js"
|
|
660
690
|
);
|
|
@@ -668,7 +698,7 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
668
698
|
directory,
|
|
669
699
|
api: flags.api,
|
|
670
700
|
db: flags.db,
|
|
671
|
-
|
|
701
|
+
providers: flags.providers,
|
|
672
702
|
packageManager: flags.packageManager,
|
|
673
703
|
};
|
|
674
704
|
|
|
@@ -697,43 +727,79 @@ prompt-based setup. Pass --yes or any selection flag to skip the prompts.`,
|
|
|
697
727
|
|
|
698
728
|
const api = selections.api ?? false;
|
|
699
729
|
const database = selections.db ?? "sqlite";
|
|
700
|
-
const {
|
|
701
|
-
uniqueValues([...(selections.
|
|
730
|
+
const { starterProviders, presets } = splitCreateProviders(
|
|
731
|
+
uniqueValues([...(selections.providers ?? [])]),
|
|
702
732
|
);
|
|
703
733
|
|
|
704
734
|
let presetsNeedEnv = false;
|
|
705
735
|
if (presets.length > 0) {
|
|
706
736
|
const { assertCompatibleCreatePresets, providerPresetNeedsEnv } =
|
|
707
737
|
await import("./provider-add.js");
|
|
708
|
-
assertCompatibleCreatePresets(presets,
|
|
738
|
+
assertCompatibleCreatePresets(presets, starterProviders);
|
|
709
739
|
presetsNeedEnv = presets.some(providerPresetNeedsEnv);
|
|
710
740
|
}
|
|
711
741
|
|
|
712
|
-
const
|
|
742
|
+
const createOptions = {
|
|
713
743
|
name: selections.directory,
|
|
714
744
|
template: flags.template,
|
|
715
745
|
api,
|
|
716
746
|
packageManager: selections.packageManager,
|
|
717
|
-
|
|
747
|
+
providers: starterProviders,
|
|
718
748
|
db: database,
|
|
719
749
|
force: Boolean(flags.force),
|
|
720
750
|
dryRun: Boolean(flags.dryRun),
|
|
721
|
-
}
|
|
751
|
+
} as const;
|
|
752
|
+
|
|
753
|
+
let result: Awaited<ReturnType<typeof createProject>>;
|
|
754
|
+
if (flags.dryRun) {
|
|
755
|
+
const plan = await planCreateProject(createOptions);
|
|
756
|
+
if (presets.length === 0) {
|
|
757
|
+
result = plan.result;
|
|
758
|
+
} else {
|
|
759
|
+
const { planProviderPresetsForCreate } = await import(
|
|
760
|
+
"./provider-add.js"
|
|
761
|
+
);
|
|
762
|
+
const providerPlan = await planProviderPresetsForCreate({
|
|
763
|
+
targetDir: plan.result.targetDir,
|
|
764
|
+
files: plan.files,
|
|
765
|
+
names: presets,
|
|
766
|
+
});
|
|
767
|
+
result = {
|
|
768
|
+
...plan.result,
|
|
769
|
+
files: providerPlan.files.map((file) => file.path),
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
} else {
|
|
773
|
+
result = await createProject(createOptions);
|
|
774
|
+
}
|
|
722
775
|
|
|
723
776
|
if (!flags.dryRun && presets.length > 0) {
|
|
724
777
|
const { addProviderPreset } = await import("./provider-add.js");
|
|
778
|
+
const presetFiles: string[] = [];
|
|
725
779
|
for (const preset of presets) {
|
|
726
|
-
await addProviderPreset({
|
|
780
|
+
const presetResult = await addProviderPreset({
|
|
781
|
+
name: preset,
|
|
782
|
+
cwd: result.targetDir,
|
|
783
|
+
});
|
|
784
|
+
presetFiles.push(...presetResult.files);
|
|
727
785
|
}
|
|
786
|
+
result = {
|
|
787
|
+
...result,
|
|
788
|
+
files: uniqueValues([...result.files, ...presetFiles]),
|
|
789
|
+
};
|
|
728
790
|
}
|
|
729
791
|
|
|
730
792
|
writeOutput(
|
|
731
793
|
this,
|
|
732
794
|
flags.json
|
|
733
|
-
? JSON.stringify(
|
|
795
|
+
? JSON.stringify(
|
|
796
|
+
{ ...result, providers: selections.providers ?? [] },
|
|
797
|
+
null,
|
|
798
|
+
2,
|
|
799
|
+
)
|
|
734
800
|
: nextSteps(result, {
|
|
735
801
|
api,
|
|
736
|
-
|
|
802
|
+
providers: starterProviders,
|
|
737
803
|
database,
|
|
738
804
|
presets,
|
|
739
805
|
presetsNeedEnv,
|
|
@@ -1083,6 +1149,7 @@ function databaseCommand(command: DatabaseCommandName) {
|
|
|
1083
1149
|
return async function runDb(this: CliContext, flags: DbFlags) {
|
|
1084
1150
|
const result = await runDatabaseCommand({
|
|
1085
1151
|
command,
|
|
1152
|
+
cwd: flags.cwd,
|
|
1086
1153
|
captureOutput: Boolean(flags.json),
|
|
1087
1154
|
dryRun: Boolean(flags.dryRun),
|
|
1088
1155
|
});
|
|
@@ -1118,6 +1185,7 @@ const dbSchemaSyncCommand = buildCommand<DbSchemaSyncFlags, [], CliContext>({
|
|
|
1118
1185
|
flags: DbSchemaSyncFlags,
|
|
1119
1186
|
) {
|
|
1120
1187
|
const result = await syncDatabaseSchema({
|
|
1188
|
+
cwd: flags.cwd,
|
|
1121
1189
|
dialect: flags.dialect,
|
|
1122
1190
|
tables: flags.tables,
|
|
1123
1191
|
output: flags.output,
|
|
@@ -1174,6 +1242,7 @@ const taskRunCommand = buildCommand<TaskRunFlags, [string], CliContext>({
|
|
|
1174
1242
|
) {
|
|
1175
1243
|
const result = await runAppTask({
|
|
1176
1244
|
name,
|
|
1245
|
+
cwd: flags.cwd,
|
|
1177
1246
|
input: flags.input,
|
|
1178
1247
|
tenant: flags.tenant,
|
|
1179
1248
|
modulePath: flags.module,
|
|
@@ -1210,6 +1279,7 @@ const outboxDrainCommand = buildCommand<OutboxDrainFlags, [], CliContext>({
|
|
|
1210
1279
|
|
|
1211
1280
|
return async function runDrain(this: CliContext, flags: OutboxDrainFlags) {
|
|
1212
1281
|
const result = await runOutboxDrain({
|
|
1282
|
+
cwd: flags.cwd,
|
|
1213
1283
|
modulePath: flags.module,
|
|
1214
1284
|
batchSize: flags.batchSize,
|
|
1215
1285
|
});
|
|
@@ -1236,6 +1306,7 @@ const outboxListCommand = buildCommand<OutboxListFlags, [], CliContext>({
|
|
|
1236
1306
|
|
|
1237
1307
|
return async function runList(this: CliContext, flags: OutboxListFlags) {
|
|
1238
1308
|
const result = await runOutboxList({
|
|
1309
|
+
cwd: flags.cwd,
|
|
1239
1310
|
modulePath: flags.module,
|
|
1240
1311
|
status: flags.status,
|
|
1241
1312
|
kind: flags.kind,
|
|
@@ -1270,6 +1341,7 @@ const outboxShowCommand = buildCommand<OutboxShowFlags, [string], CliContext>({
|
|
|
1270
1341
|
id: string,
|
|
1271
1342
|
) {
|
|
1272
1343
|
const result = await runOutboxShow({
|
|
1344
|
+
cwd: flags.cwd,
|
|
1273
1345
|
modulePath: flags.module,
|
|
1274
1346
|
id,
|
|
1275
1347
|
});
|
|
@@ -1305,6 +1377,7 @@ const outboxRequeueCommand = buildCommand<
|
|
|
1305
1377
|
id: string,
|
|
1306
1378
|
) {
|
|
1307
1379
|
const result = await runOutboxRequeue({
|
|
1380
|
+
cwd: flags.cwd,
|
|
1308
1381
|
modulePath: flags.module,
|
|
1309
1382
|
id,
|
|
1310
1383
|
availableAt: flags.availableAt,
|
|
@@ -1333,6 +1406,7 @@ const outboxPurgeCommand = buildCommand<OutboxPurgeFlags, [], CliContext>({
|
|
|
1333
1406
|
|
|
1334
1407
|
return async function runPurge(this: CliContext, flags: OutboxPurgeFlags) {
|
|
1335
1408
|
const result = await runOutboxPurge({
|
|
1409
|
+
cwd: flags.cwd,
|
|
1336
1410
|
modulePath: flags.module,
|
|
1337
1411
|
before: flags.before,
|
|
1338
1412
|
all: Boolean(flags.all),
|
|
@@ -1369,6 +1443,7 @@ const outboxPruneCommand = buildCommand<OutboxPruneFlags, [], CliContext>({
|
|
|
1369
1443
|
}
|
|
1370
1444
|
|
|
1371
1445
|
const result = await runOutboxPrune({
|
|
1446
|
+
cwd: flags.cwd,
|
|
1372
1447
|
modulePath: flags.module,
|
|
1373
1448
|
before: flags.before,
|
|
1374
1449
|
limit: flags.limit,
|
|
@@ -1418,9 +1493,10 @@ const scheduleRunCommand = buildCommand<ScheduleRunFlags, [string], CliContext>(
|
|
|
1418
1493
|
) {
|
|
1419
1494
|
const result = await runAppSchedule({
|
|
1420
1495
|
name,
|
|
1496
|
+
cwd: flags.cwd,
|
|
1421
1497
|
modulePath: flags.module,
|
|
1422
1498
|
payload: flags.payload,
|
|
1423
|
-
id: flags.
|
|
1499
|
+
id: flags.runId,
|
|
1424
1500
|
attempt: flags.attempt,
|
|
1425
1501
|
scheduledAt: flags.scheduledAt,
|
|
1426
1502
|
triggeredAt: flags.triggeredAt,
|
|
@@ -1533,14 +1609,14 @@ const makeResourceCommand = buildCommand<
|
|
|
1533
1609
|
parameters: {
|
|
1534
1610
|
flags: {
|
|
1535
1611
|
...makeFlagParameters,
|
|
1536
|
-
|
|
1612
|
+
authorization: {
|
|
1537
1613
|
kind: "boolean",
|
|
1538
1614
|
optional: true,
|
|
1539
1615
|
withNegated: false,
|
|
1540
1616
|
brief:
|
|
1541
1617
|
"Generate policy metadata and use-case authorization checks for mutating routes.",
|
|
1542
1618
|
},
|
|
1543
|
-
|
|
1619
|
+
tenantScoped: {
|
|
1544
1620
|
kind: "boolean",
|
|
1545
1621
|
optional: true,
|
|
1546
1622
|
withNegated: false,
|
|
@@ -1573,10 +1649,11 @@ const makeResourceCommand = buildCommand<
|
|
|
1573
1649
|
) {
|
|
1574
1650
|
const result = await makeResource({
|
|
1575
1651
|
name,
|
|
1652
|
+
cwd: flags.cwd,
|
|
1576
1653
|
force: Boolean(flags.force),
|
|
1577
1654
|
dryRun: Boolean(flags.dryRun),
|
|
1578
|
-
|
|
1579
|
-
|
|
1655
|
+
authorization: Boolean(flags.authorization),
|
|
1656
|
+
tenantScoped: Boolean(flags.tenantScoped),
|
|
1580
1657
|
events: Boolean(flags.events),
|
|
1581
1658
|
softDelete: Boolean(flags.softDelete),
|
|
1582
1659
|
});
|
|
@@ -1604,7 +1681,7 @@ const makeFeatureCommand = buildCommand<MakeFeatureFlags, [string], CliContext>(
|
|
|
1604
1681
|
optional: true,
|
|
1605
1682
|
variadic: ",",
|
|
1606
1683
|
brief:
|
|
1607
|
-
"Add feature-owned artifacts. Supports policy, factory
|
|
1684
|
+
"Add feature-owned artifacts. Supports policy, factory, seed, task, event, listener, job, notification, schedule, ui, and upload.",
|
|
1608
1685
|
},
|
|
1609
1686
|
recipe: {
|
|
1610
1687
|
kind: "enum",
|
|
@@ -1626,6 +1703,7 @@ const makeFeatureCommand = buildCommand<MakeFeatureFlags, [string], CliContext>(
|
|
|
1626
1703
|
) {
|
|
1627
1704
|
const result = await makeFeature({
|
|
1628
1705
|
name,
|
|
1706
|
+
cwd: flags.cwd,
|
|
1629
1707
|
with: flags.with,
|
|
1630
1708
|
recipe: flags.recipe,
|
|
1631
1709
|
force: Boolean(flags.force),
|
|
@@ -1654,7 +1732,6 @@ type MakeGeneratorName =
|
|
|
1654
1732
|
| "makeSeed"
|
|
1655
1733
|
| "makeTask"
|
|
1656
1734
|
| "makeTest"
|
|
1657
|
-
| "makeUpload"
|
|
1658
1735
|
| "makeUseCase";
|
|
1659
1736
|
|
|
1660
1737
|
function simpleMakeCommand(
|
|
@@ -1680,6 +1757,7 @@ function simpleMakeCommand(
|
|
|
1680
1757
|
) {
|
|
1681
1758
|
const result = await generators[generator]({
|
|
1682
1759
|
name,
|
|
1760
|
+
cwd: flags.cwd,
|
|
1683
1761
|
force: Boolean(flags.force),
|
|
1684
1762
|
dryRun: Boolean(flags.dryRun),
|
|
1685
1763
|
});
|
|
@@ -1694,6 +1772,48 @@ function simpleMakeCommand(
|
|
|
1694
1772
|
});
|
|
1695
1773
|
}
|
|
1696
1774
|
|
|
1775
|
+
const makeUploadCommand = buildCommand<MakeUploadFlags, [string], CliContext>({
|
|
1776
|
+
docs: {
|
|
1777
|
+
brief: "Generate a feature upload.",
|
|
1778
|
+
},
|
|
1779
|
+
parameters: {
|
|
1780
|
+
flags: {
|
|
1781
|
+
...makeFlagParameters,
|
|
1782
|
+
ui: {
|
|
1783
|
+
kind: "boolean",
|
|
1784
|
+
optional: true,
|
|
1785
|
+
withNegated: false,
|
|
1786
|
+
brief:
|
|
1787
|
+
"Generate a typed React upload client, uploader component, and component test.",
|
|
1788
|
+
},
|
|
1789
|
+
} satisfies FlagParametersForType<MakeUploadFlags, CliContext>,
|
|
1790
|
+
positional: namePositional,
|
|
1791
|
+
},
|
|
1792
|
+
loader: async () => {
|
|
1793
|
+
const { makeUpload } = await import("./make.js");
|
|
1794
|
+
|
|
1795
|
+
return async function runMakeUpload(
|
|
1796
|
+
this: CliContext,
|
|
1797
|
+
flags: MakeUploadFlags,
|
|
1798
|
+
name: string,
|
|
1799
|
+
) {
|
|
1800
|
+
const result = await makeUpload({
|
|
1801
|
+
name,
|
|
1802
|
+
cwd: flags.cwd,
|
|
1803
|
+
force: Boolean(flags.force),
|
|
1804
|
+
dryRun: Boolean(flags.dryRun),
|
|
1805
|
+
ui: Boolean(flags.ui),
|
|
1806
|
+
});
|
|
1807
|
+
writeOutput(
|
|
1808
|
+
this,
|
|
1809
|
+
flags.json
|
|
1810
|
+
? JSON.stringify(result, null, 2)
|
|
1811
|
+
: makeUploadNextSteps(result),
|
|
1812
|
+
);
|
|
1813
|
+
};
|
|
1814
|
+
},
|
|
1815
|
+
});
|
|
1816
|
+
|
|
1697
1817
|
const makeListenerCommand = buildCommand<
|
|
1698
1818
|
MakeListenerFlags,
|
|
1699
1819
|
[string],
|
|
@@ -1706,7 +1826,7 @@ const makeListenerCommand = buildCommand<
|
|
|
1706
1826
|
flags: {
|
|
1707
1827
|
...makeFlagParameters,
|
|
1708
1828
|
event: parsedStringFlag(
|
|
1709
|
-
"Event to listen to, for example posts
|
|
1829
|
+
"Event to listen to, for example posts.published.",
|
|
1710
1830
|
),
|
|
1711
1831
|
} satisfies FlagParametersForType<MakeListenerFlags, CliContext>,
|
|
1712
1832
|
positional: namePositional,
|
|
@@ -1721,12 +1841,13 @@ const makeListenerCommand = buildCommand<
|
|
|
1721
1841
|
) {
|
|
1722
1842
|
if (!flags.event) {
|
|
1723
1843
|
throw new Error(
|
|
1724
|
-
"beignet make listener requires --event feature
|
|
1844
|
+
"beignet make listener requires --event feature.name, for example --event posts.published.",
|
|
1725
1845
|
);
|
|
1726
1846
|
}
|
|
1727
1847
|
|
|
1728
1848
|
const result = await makeListener({
|
|
1729
1849
|
name,
|
|
1850
|
+
cwd: flags.cwd,
|
|
1730
1851
|
event: flags.event,
|
|
1731
1852
|
force: Boolean(flags.force),
|
|
1732
1853
|
dryRun: Boolean(flags.dryRun),
|
|
@@ -1773,6 +1894,7 @@ const makeScheduleCommand = buildCommand<
|
|
|
1773
1894
|
) {
|
|
1774
1895
|
const result = await makeSchedule({
|
|
1775
1896
|
name,
|
|
1897
|
+
cwd: flags.cwd,
|
|
1776
1898
|
cron: flags.cron,
|
|
1777
1899
|
timezone: flags.timezone,
|
|
1778
1900
|
route: Boolean(flags.route),
|
|
@@ -1803,6 +1925,7 @@ const makePaymentsCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1803
1925
|
|
|
1804
1926
|
return async function runMakePayments(this: CliContext, flags: MakeFlags) {
|
|
1805
1927
|
const result = await makePayments({
|
|
1928
|
+
cwd: flags.cwd,
|
|
1806
1929
|
force: Boolean(flags.force),
|
|
1807
1930
|
dryRun: Boolean(flags.dryRun),
|
|
1808
1931
|
});
|
|
@@ -1832,6 +1955,7 @@ const makeTenancyCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1832
1955
|
|
|
1833
1956
|
return async function runMakeTenancy(this: CliContext, flags: MakeFlags) {
|
|
1834
1957
|
const result = await makeTenancy({
|
|
1958
|
+
cwd: flags.cwd,
|
|
1835
1959
|
force: Boolean(flags.force),
|
|
1836
1960
|
dryRun: Boolean(flags.dryRun),
|
|
1837
1961
|
});
|
|
@@ -1861,6 +1985,7 @@ const makeInboxCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1861
1985
|
|
|
1862
1986
|
return async function runMakeInbox(this: CliContext, flags: MakeFlags) {
|
|
1863
1987
|
const result = await makeInbox({
|
|
1988
|
+
cwd: flags.cwd,
|
|
1864
1989
|
force: Boolean(flags.force),
|
|
1865
1990
|
dryRun: Boolean(flags.dryRun),
|
|
1866
1991
|
});
|
|
@@ -1890,6 +2015,7 @@ const makeOutboxCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1890
2015
|
|
|
1891
2016
|
return async function runMakeOutbox(this: CliContext, flags: MakeFlags) {
|
|
1892
2017
|
const result = await makeOutbox({
|
|
2018
|
+
cwd: flags.cwd,
|
|
1893
2019
|
force: Boolean(flags.force),
|
|
1894
2020
|
dryRun: Boolean(flags.dryRun),
|
|
1895
2021
|
});
|
|
@@ -1971,11 +2097,7 @@ const makeRoutes = buildRouteMap({
|
|
|
1971
2097
|
"Generate a use case test.",
|
|
1972
2098
|
makeTestNextSteps,
|
|
1973
2099
|
),
|
|
1974
|
-
upload:
|
|
1975
|
-
"makeUpload",
|
|
1976
|
-
"Generate a feature upload.",
|
|
1977
|
-
makeUploadNextSteps,
|
|
1978
|
-
),
|
|
2100
|
+
upload: makeUploadCommand,
|
|
1979
2101
|
useCase: simpleMakeCommand(
|
|
1980
2102
|
"makeUseCase",
|
|
1981
2103
|
"Generate a use case.",
|
|
@@ -2002,15 +2124,11 @@ Run npm create beignet@latest (or bun create beignet) to scaffold a new app.`,
|
|
|
2002
2124
|
mcp: mcpCommand,
|
|
2003
2125
|
outbox: outboxRoutes,
|
|
2004
2126
|
preflight: preflightCommand,
|
|
2005
|
-
|
|
2127
|
+
provider: providerRoutes,
|
|
2006
2128
|
routes: routesCommand,
|
|
2007
2129
|
schedule: scheduleRoutes,
|
|
2008
2130
|
task: taskRoutes,
|
|
2009
2131
|
},
|
|
2010
|
-
aliases: {
|
|
2011
|
-
// The singular form is a common near-miss for the providers commands.
|
|
2012
|
-
provider: "providers",
|
|
2013
|
-
},
|
|
2014
2132
|
});
|
|
2015
2133
|
|
|
2016
2134
|
const cli = buildApplication(rootRoutes, {
|
|
@@ -2058,6 +2176,7 @@ type MakeNextStepsResult = {
|
|
|
2058
2176
|
name: string;
|
|
2059
2177
|
targetDir: string;
|
|
2060
2178
|
dryRun: boolean;
|
|
2179
|
+
files: string[];
|
|
2061
2180
|
createdFiles: string[];
|
|
2062
2181
|
updatedFiles: string[];
|
|
2063
2182
|
skippedFiles: string[];
|
|
@@ -2245,7 +2364,7 @@ function nextSteps(
|
|
|
2245
2364
|
result: CreateNextStepsResult,
|
|
2246
2365
|
options: {
|
|
2247
2366
|
api?: boolean;
|
|
2248
|
-
|
|
2367
|
+
providers?: readonly StarterProviderName[];
|
|
2249
2368
|
database?: DatabaseName;
|
|
2250
2369
|
presets?: readonly ProviderPresetName[];
|
|
2251
2370
|
presetsNeedEnv?: boolean;
|
|
@@ -2255,7 +2374,7 @@ function nextSteps(
|
|
|
2255
2374
|
const plannedFiles = result.files.map((file) => ` ${file}`).join("\n");
|
|
2256
2375
|
const plannedPresets =
|
|
2257
2376
|
options.presets && options.presets.length > 0
|
|
2258
|
-
? `\n\nProvider presets
|
|
2377
|
+
? `\n\nProvider presets included in this plan:\n${options.presets
|
|
2259
2378
|
.map((preset) => ` ${preset}`)
|
|
2260
2379
|
.join("\n")}`
|
|
2261
2380
|
: "";
|
|
@@ -2269,11 +2388,11 @@ ${plannedFiles}${plannedPresets}`;
|
|
|
2269
2388
|
const pm = result.packageManager;
|
|
2270
2389
|
const run = pm === "npm" ? "npm run" : `${pm} run`;
|
|
2271
2390
|
const cli = packageRunnerFromPackageManager(pm);
|
|
2272
|
-
const
|
|
2273
|
-
options.
|
|
2391
|
+
const envRequiredProviders =
|
|
2392
|
+
options.providers?.filter(isEnvRequiredStarterProvider) ?? [];
|
|
2274
2393
|
const envStep =
|
|
2275
|
-
|
|
2276
|
-
? " Fill .env.local for selected
|
|
2394
|
+
envRequiredProviders.length > 0 || options.presetsNeedEnv
|
|
2395
|
+
? " Fill .env.local for selected providers before starting the app.\n"
|
|
2277
2396
|
: "";
|
|
2278
2397
|
const presetSection =
|
|
2279
2398
|
options.presets && options.presets.length > 0
|
|
@@ -2281,7 +2400,7 @@ ${plannedFiles}${plannedPresets}`;
|
|
|
2281
2400
|
.map((preset) => ` ${preset}`)
|
|
2282
2401
|
.join(
|
|
2283
2402
|
"\n",
|
|
2284
|
-
)}\n See docs/
|
|
2403
|
+
)}\n See docs/providers.md for setup notes and follow-up steps.\n`
|
|
2285
2404
|
: "";
|
|
2286
2405
|
const openStep = options.api
|
|
2287
2406
|
? " open http://localhost:3000 for the API landing page"
|
|
@@ -2334,13 +2453,11 @@ function packageRunnerFromPackageManager(pm: PackageManager): string {
|
|
|
2334
2453
|
}
|
|
2335
2454
|
}
|
|
2336
2455
|
|
|
2337
|
-
function
|
|
2338
|
-
integration: IntegrationName,
|
|
2339
|
-
): boolean {
|
|
2456
|
+
function isEnvRequiredStarterProvider(provider: StarterProviderName): boolean {
|
|
2340
2457
|
return (
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2458
|
+
provider === "jobs-inngest" ||
|
|
2459
|
+
provider === "mail-resend" ||
|
|
2460
|
+
provider === "rate-limit-upstash"
|
|
2344
2461
|
);
|
|
2345
2462
|
}
|
|
2346
2463
|
|
|
@@ -2558,8 +2675,19 @@ function makeScheduleNextSteps(
|
|
|
2558
2675
|
}
|
|
2559
2676
|
|
|
2560
2677
|
function makeUploadNextSteps(result: MakeNextStepsResult): string {
|
|
2678
|
+
const includesUi = result.files.some((file) =>
|
|
2679
|
+
file.endsWith("-uploader.tsx"),
|
|
2680
|
+
);
|
|
2681
|
+
|
|
2561
2682
|
return makeNextSteps(result, "upload", [
|
|
2562
2683
|
"Replace the starter metadata, constraints, key, authorization, and onComplete behavior.",
|
|
2684
|
+
...(includesUi
|
|
2685
|
+
? [
|
|
2686
|
+
"Render the generated uploader with its required resourceId and connect onComplete to refresh the owning view.",
|
|
2687
|
+
]
|
|
2688
|
+
: [
|
|
2689
|
+
"Add --ui in a full-stack app when you want a typed upload client, component, and component test.",
|
|
2690
|
+
]),
|
|
2563
2691
|
"Use the generated upload route for local development, then swap the local storage provider for S3-compatible storage before production.",
|
|
2564
2692
|
]);
|
|
2565
2693
|
}
|