@beignet/cli 0.0.26 → 0.0.27
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 +14 -0
- package/README.md +29 -10
- package/dist/choices.d.ts +8 -0
- package/dist/choices.d.ts.map +1 -1
- package/dist/choices.js +14 -0
- package/dist/choices.js.map +1 -1
- package/dist/db.js +2 -2
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -13
- package/dist/index.js.map +1 -1
- package/dist/inspect.js +51 -3
- package/dist/inspect.js.map +1 -1
- package/dist/make/inbox.d.ts +63 -0
- package/dist/make/inbox.d.ts.map +1 -0
- package/dist/make/inbox.js +1747 -0
- package/dist/make/inbox.js.map +1 -0
- package/dist/make/payments.d.ts +61 -0
- package/dist/make/payments.d.ts.map +1 -0
- package/dist/make/payments.js +1900 -0
- package/dist/make/payments.js.map +1 -0
- package/dist/make/shared.d.ts +575 -0
- package/dist/make/shared.d.ts.map +1 -0
- package/dist/make/shared.js +2166 -0
- package/dist/make/shared.js.map +1 -0
- package/dist/make/tenancy.d.ts +101 -0
- package/dist/make/tenancy.d.ts.map +1 -0
- package/dist/make/tenancy.js +4409 -0
- package/dist/make/tenancy.js.map +1 -0
- package/dist/make.d.ts +8 -44
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +71 -3659
- package/dist/make.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +44 -3
- package/dist/mcp.js.map +1 -1
- package/dist/provider-add.d.ts +19 -0
- package/dist/provider-add.d.ts.map +1 -0
- package/dist/provider-add.js +691 -0
- package/dist/provider-add.js.map +1 -0
- package/dist/registry-edits.d.ts +9 -0
- package/dist/registry-edits.d.ts.map +1 -1
- package/dist/registry-edits.js +32 -0
- package/dist/registry-edits.js.map +1 -1
- package/dist/task.d.ts +2 -0
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js +2 -0
- package/dist/task.js.map +1 -1
- package/dist/templates/agents.js +2 -2
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +44 -37
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.d.ts +5 -0
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +5 -0
- package/dist/templates/shared.js.map +1 -1
- package/package.json +2 -2
- package/skills/app-structure/SKILL.md +1 -1
- package/src/choices.ts +28 -0
- package/src/db.ts +2 -2
- package/src/index.ts +170 -13
- package/src/inspect.ts +68 -2
- package/src/make/inbox.ts +2015 -0
- package/src/make/payments.ts +2182 -0
- package/src/make/shared.ts +3550 -0
- package/src/make/tenancy.ts +4809 -0
- package/src/make.ts +380 -5289
- package/src/mcp.ts +65 -2
- package/src/provider-add.ts +926 -0
- package/src/registry-edits.ts +47 -0
- package/src/task.ts +8 -10
- package/src/templates/agents.ts +2 -2
- package/src/templates/server.ts +44 -37
- package/src/templates/shared.ts +5 -0
- package/src/test-helpers/generated-app.ts +168 -0
package/src/index.ts
CHANGED
|
@@ -26,12 +26,15 @@ import {
|
|
|
26
26
|
makeFeatureAddonChoices,
|
|
27
27
|
makeFeatureRecipeChoices,
|
|
28
28
|
type PackageManager,
|
|
29
|
+
type ProviderPresetName,
|
|
29
30
|
packageManagerChoices,
|
|
31
|
+
providerPresetChoices,
|
|
30
32
|
type TemplateName,
|
|
31
33
|
templateChoices,
|
|
32
34
|
} from "./choices.js";
|
|
33
35
|
// Type-only: the runtime module stays behind the create command's lazy loader.
|
|
34
36
|
import type { CreateSelections } from "./create-prompts.js";
|
|
37
|
+
import type { AddProviderPresetResult } from "./provider-add.js";
|
|
35
38
|
import { getCliVersion } from "./version.js";
|
|
36
39
|
|
|
37
40
|
type CliContext = CommandContext & {
|
|
@@ -131,6 +134,7 @@ type DbSchemaGenerateFlags = DbFlags & {
|
|
|
131
134
|
type TaskRunFlags = {
|
|
132
135
|
json?: boolean;
|
|
133
136
|
input?: string;
|
|
137
|
+
tenant?: string;
|
|
134
138
|
module?: string;
|
|
135
139
|
};
|
|
136
140
|
|
|
@@ -168,7 +172,24 @@ type ProviderAuditFlags = {
|
|
|
168
172
|
cwd?: string;
|
|
169
173
|
};
|
|
170
174
|
|
|
175
|
+
type ProviderAddFlags = {
|
|
176
|
+
json?: boolean;
|
|
177
|
+
dryRun?: boolean;
|
|
178
|
+
cwd?: string;
|
|
179
|
+
};
|
|
180
|
+
|
|
171
181
|
const parseString = (input: string): string => input;
|
|
182
|
+
const parseProviderPreset = (input: string): ProviderPresetName => {
|
|
183
|
+
if ((providerPresetChoices as readonly string[]).includes(input)) {
|
|
184
|
+
return input as ProviderPresetName;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Unknown provider preset "${input}". Available presets: ${providerPresetChoices.join(
|
|
189
|
+
", ",
|
|
190
|
+
)}.`,
|
|
191
|
+
);
|
|
192
|
+
};
|
|
172
193
|
const parsePositiveInteger = (input: string): number => {
|
|
173
194
|
const value = Number(input);
|
|
174
195
|
if (!Number.isInteger(value) || value <= 0) {
|
|
@@ -240,6 +261,12 @@ const providerAuditFlagParameters = {
|
|
|
240
261
|
cwd: cwdFlag,
|
|
241
262
|
} satisfies FlagParametersForType<ProviderAuditFlags, CliContext>;
|
|
242
263
|
|
|
264
|
+
const providerAddFlagParameters = {
|
|
265
|
+
json: jsonFlag,
|
|
266
|
+
dryRun: dryRunFlag,
|
|
267
|
+
cwd: cwdFlag,
|
|
268
|
+
} satisfies FlagParametersForType<ProviderAddFlags, CliContext>;
|
|
269
|
+
|
|
243
270
|
const dbFlagParameters = {
|
|
244
271
|
json: jsonFlag,
|
|
245
272
|
dryRun: dryRunFlag,
|
|
@@ -270,6 +297,9 @@ const dbSchemaGenerateFlagParameters = {
|
|
|
270
297
|
const taskRunFlagParameters = {
|
|
271
298
|
json: jsonFlag,
|
|
272
299
|
input: parsedStringFlag("JSON input passed to the task schema."),
|
|
300
|
+
tenant: parsedStringFlag(
|
|
301
|
+
"Tenant id or slug passed to the app's createTaskContext, separate from task input.",
|
|
302
|
+
),
|
|
273
303
|
module: parsedStringFlag(
|
|
274
304
|
"Task registry module. Defaults to server/tasks.ts.",
|
|
275
305
|
),
|
|
@@ -317,6 +347,19 @@ const namePositional = {
|
|
|
317
347
|
],
|
|
318
348
|
} as const;
|
|
319
349
|
|
|
350
|
+
const providerPresetPositional = {
|
|
351
|
+
kind: "tuple",
|
|
352
|
+
parameters: [
|
|
353
|
+
{
|
|
354
|
+
parse: parseProviderPreset,
|
|
355
|
+
placeholder: "preset",
|
|
356
|
+
brief: `Provider preset to add. Available: ${providerPresetChoices.join(
|
|
357
|
+
", ",
|
|
358
|
+
)}.`,
|
|
359
|
+
},
|
|
360
|
+
],
|
|
361
|
+
} as const;
|
|
362
|
+
|
|
320
363
|
function resolveOutputFormat(flags: {
|
|
321
364
|
json?: boolean;
|
|
322
365
|
format?: OutputFormat;
|
|
@@ -639,11 +682,50 @@ const providerAuditCommand = buildCommand<ProviderAuditFlags, [], CliContext>({
|
|
|
639
682
|
},
|
|
640
683
|
});
|
|
641
684
|
|
|
685
|
+
const providerAddCommand = buildCommand<
|
|
686
|
+
ProviderAddFlags,
|
|
687
|
+
[ProviderPresetName],
|
|
688
|
+
CliContext
|
|
689
|
+
>({
|
|
690
|
+
docs: {
|
|
691
|
+
brief: "Add a provider setup preset to a Beignet app.",
|
|
692
|
+
fullDescription: `Updates an existing Beignet app with provider package dependencies, server/provider registration, app port wiring, .env.example entries, and local setup notes.
|
|
693
|
+
|
|
694
|
+
Available presets: ${providerPresetChoices.join(", ")}`,
|
|
695
|
+
},
|
|
696
|
+
parameters: {
|
|
697
|
+
flags: providerAddFlagParameters,
|
|
698
|
+
positional: providerPresetPositional,
|
|
699
|
+
},
|
|
700
|
+
loader: async () => {
|
|
701
|
+
const { addProviderPreset } = await import("./provider-add.js");
|
|
702
|
+
|
|
703
|
+
return async function runProviderAdd(
|
|
704
|
+
this: CliContext,
|
|
705
|
+
flags: ProviderAddFlags,
|
|
706
|
+
name: ProviderPresetName,
|
|
707
|
+
) {
|
|
708
|
+
const result = await addProviderPreset({
|
|
709
|
+
name,
|
|
710
|
+
cwd: flags.cwd,
|
|
711
|
+
dryRun: Boolean(flags.dryRun),
|
|
712
|
+
});
|
|
713
|
+
writeOutput(
|
|
714
|
+
this,
|
|
715
|
+
flags.json
|
|
716
|
+
? JSON.stringify(result, null, 2)
|
|
717
|
+
: providerAddNextSteps(result),
|
|
718
|
+
);
|
|
719
|
+
};
|
|
720
|
+
},
|
|
721
|
+
});
|
|
722
|
+
|
|
642
723
|
const providerRoutes = buildRouteMap({
|
|
643
724
|
docs: {
|
|
644
|
-
brief: "
|
|
725
|
+
brief: "Manage Beignet provider setup.",
|
|
645
726
|
},
|
|
646
727
|
routes: {
|
|
728
|
+
add: providerAddCommand,
|
|
647
729
|
audit: providerAuditCommand,
|
|
648
730
|
},
|
|
649
731
|
});
|
|
@@ -760,6 +842,7 @@ const taskRunCommand = buildCommand<TaskRunFlags, [string], CliContext>({
|
|
|
760
842
|
const result = await runAppTask({
|
|
761
843
|
name,
|
|
762
844
|
input: flags.input,
|
|
845
|
+
tenant: flags.tenant,
|
|
763
846
|
modulePath: flags.module,
|
|
764
847
|
});
|
|
765
848
|
|
|
@@ -1215,7 +1298,9 @@ const makePaymentsCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1215
1298
|
flags: makeFlagParameters,
|
|
1216
1299
|
},
|
|
1217
1300
|
loader: async () => {
|
|
1218
|
-
const { makePayments } = await import(
|
|
1301
|
+
const { makePayments, makePaymentsNextStepLines } = await import(
|
|
1302
|
+
"./make.js"
|
|
1303
|
+
);
|
|
1219
1304
|
|
|
1220
1305
|
return async function runMakePayments(this: CliContext, flags: MakeFlags) {
|
|
1221
1306
|
const result = await makePayments({
|
|
@@ -1226,7 +1311,69 @@ const makePaymentsCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
|
1226
1311
|
this,
|
|
1227
1312
|
flags.json
|
|
1228
1313
|
? JSON.stringify(result, null, 2)
|
|
1229
|
-
:
|
|
1314
|
+
: makeNextSteps(
|
|
1315
|
+
result,
|
|
1316
|
+
"billing slice",
|
|
1317
|
+
makePaymentsNextStepLines(result),
|
|
1318
|
+
),
|
|
1319
|
+
);
|
|
1320
|
+
};
|
|
1321
|
+
},
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
const makeTenancyCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
1325
|
+
docs: {
|
|
1326
|
+
brief: "Generate a workspace tenancy slice.",
|
|
1327
|
+
},
|
|
1328
|
+
parameters: {
|
|
1329
|
+
flags: makeFlagParameters,
|
|
1330
|
+
},
|
|
1331
|
+
loader: async () => {
|
|
1332
|
+
const { makeTenancy, makeTenancyNextStepLines } = await import("./make.js");
|
|
1333
|
+
|
|
1334
|
+
return async function runMakeTenancy(this: CliContext, flags: MakeFlags) {
|
|
1335
|
+
const result = await makeTenancy({
|
|
1336
|
+
force: Boolean(flags.force),
|
|
1337
|
+
dryRun: Boolean(flags.dryRun),
|
|
1338
|
+
});
|
|
1339
|
+
writeOutput(
|
|
1340
|
+
this,
|
|
1341
|
+
flags.json
|
|
1342
|
+
? JSON.stringify(result, null, 2)
|
|
1343
|
+
: makeNextSteps(
|
|
1344
|
+
result,
|
|
1345
|
+
"workspace slice",
|
|
1346
|
+
makeTenancyNextStepLines(),
|
|
1347
|
+
),
|
|
1348
|
+
);
|
|
1349
|
+
};
|
|
1350
|
+
},
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
const makeInboxCommand = buildCommand<MakeFlags, [], CliContext>({
|
|
1354
|
+
docs: {
|
|
1355
|
+
brief: "Generate an in-app inbox notifications slice.",
|
|
1356
|
+
},
|
|
1357
|
+
parameters: {
|
|
1358
|
+
flags: makeFlagParameters,
|
|
1359
|
+
},
|
|
1360
|
+
loader: async () => {
|
|
1361
|
+
const { makeInbox, makeInboxNextStepLines } = await import("./make.js");
|
|
1362
|
+
|
|
1363
|
+
return async function runMakeInbox(this: CliContext, flags: MakeFlags) {
|
|
1364
|
+
const result = await makeInbox({
|
|
1365
|
+
force: Boolean(flags.force),
|
|
1366
|
+
dryRun: Boolean(flags.dryRun),
|
|
1367
|
+
});
|
|
1368
|
+
writeOutput(
|
|
1369
|
+
this,
|
|
1370
|
+
flags.json
|
|
1371
|
+
? JSON.stringify(result, null, 2)
|
|
1372
|
+
: makeNextSteps(
|
|
1373
|
+
result,
|
|
1374
|
+
"notifications slice",
|
|
1375
|
+
makeInboxNextStepLines(),
|
|
1376
|
+
),
|
|
1230
1377
|
);
|
|
1231
1378
|
};
|
|
1232
1379
|
},
|
|
@@ -1283,6 +1430,7 @@ const makeRoutes = buildRouteMap({
|
|
|
1283
1430
|
makeFactoryNextSteps,
|
|
1284
1431
|
),
|
|
1285
1432
|
feature: makeFeatureCommand,
|
|
1433
|
+
inbox: makeInboxCommand,
|
|
1286
1434
|
job: simpleMakeCommand(
|
|
1287
1435
|
"makeJob",
|
|
1288
1436
|
"Generate a feature job.",
|
|
@@ -1318,6 +1466,7 @@ const makeRoutes = buildRouteMap({
|
|
|
1318
1466
|
"Generate a feature operational task.",
|
|
1319
1467
|
makeTaskNextSteps,
|
|
1320
1468
|
),
|
|
1469
|
+
tenancy: makeTenancyCommand,
|
|
1321
1470
|
test: simpleMakeCommand(
|
|
1322
1471
|
"makeTest",
|
|
1323
1472
|
"Generate a use case test.",
|
|
@@ -1432,6 +1581,7 @@ type DatabaseSchemaGenerateNextStepsResult = {
|
|
|
1432
1581
|
type AppTaskRunNextStepsResult = {
|
|
1433
1582
|
name: string;
|
|
1434
1583
|
durationMs: number;
|
|
1584
|
+
tenant?: string;
|
|
1435
1585
|
output: unknown;
|
|
1436
1586
|
};
|
|
1437
1587
|
|
|
@@ -1463,7 +1613,9 @@ function appTaskRunNextSteps(result: AppTaskRunNextStepsResult): string {
|
|
|
1463
1613
|
? "undefined"
|
|
1464
1614
|
: JSON.stringify(result.output, null, 2);
|
|
1465
1615
|
|
|
1466
|
-
|
|
1616
|
+
const tenant = result.tenant ? `\nTenant: ${result.tenant}` : "";
|
|
1617
|
+
|
|
1618
|
+
return `Ran task ${result.name} in ${result.durationMs}ms${tenant}
|
|
1467
1619
|
|
|
1468
1620
|
Output:
|
|
1469
1621
|
${output}`;
|
|
@@ -1617,6 +1769,20 @@ Next steps:
|
|
|
1617
1769
|
${steps.map((step) => ` ${step}`).join("\n")}`;
|
|
1618
1770
|
}
|
|
1619
1771
|
|
|
1772
|
+
function providerAddNextSteps(result: AddProviderPresetResult): string {
|
|
1773
|
+
const { changedFiles, skippedFiles } = changedFileLines(result);
|
|
1774
|
+
const prefix = result.dryRun ? "Would add" : "Added";
|
|
1775
|
+
|
|
1776
|
+
return `${prefix} ${result.name} provider preset in ${result.targetDir}
|
|
1777
|
+
|
|
1778
|
+
Changed files:
|
|
1779
|
+
${changedFiles || " none"}
|
|
1780
|
+
${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
|
|
1781
|
+
|
|
1782
|
+
Next steps:
|
|
1783
|
+
${result.nextSteps.map((step) => ` ${step}`).join("\n")}`;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1620
1786
|
function makeResourceNextSteps(result: MakeNextStepsResult): string {
|
|
1621
1787
|
return makeNextSteps(result, "resource", [
|
|
1622
1788
|
"Use make resource when the feature maps cleanly to a REST resource with repository-backed persistence.",
|
|
@@ -1754,15 +1920,6 @@ function makeNotificationNextSteps(result: MakeNextStepsResult): string {
|
|
|
1754
1920
|
]);
|
|
1755
1921
|
}
|
|
1756
1922
|
|
|
1757
|
-
function makePaymentsNextSteps(result: MakeNextStepsResult): string {
|
|
1758
|
-
return makeNextSteps(result, "billing slice", [
|
|
1759
|
-
"Set BILLING_TEAM_PRICE_ID in .env.local to the provider price ID for your team plan.",
|
|
1760
|
-
"Run beignet db generate and beignet db migrate so billing_accounts exists before handling webhooks.",
|
|
1761
|
-
"Use createMemoryPaymentsProvider() for local development, then swap server/providers.ts to stripePaymentsProvider when STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET are configured.",
|
|
1762
|
-
"Run your app's test, lint, and typecheck commands, then beignet lint and beignet doctor.",
|
|
1763
|
-
]);
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
1923
|
function makeOutboxNextSteps(result: MakeNextStepsResult): string {
|
|
1767
1924
|
return makeNextSteps(result, "outbox runtime", [
|
|
1768
1925
|
"Set CRON_SECRET in your deployment and call /api/cron/outbox/drain from a scheduler with Authorization: Bearer $CRON_SECRET.",
|
package/src/inspect.ts
CHANGED
|
@@ -986,6 +986,24 @@ function parseRouteExports(
|
|
|
986
986
|
const imports = parseNamedImports(source, config);
|
|
987
987
|
const exportRegex =
|
|
988
988
|
/export const\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\s*=\s*([^;\n]+)/g;
|
|
989
|
+
const apiRouteExportRegex =
|
|
990
|
+
/export const\s*\{([^}]+)\}\s*=\s*createApiRoute\s*\(/g;
|
|
991
|
+
|
|
992
|
+
for (const match of source.matchAll(apiRouteExportRegex)) {
|
|
993
|
+
for (const member of match[1].split(",")) {
|
|
994
|
+
const parts = member.split(":");
|
|
995
|
+
const method = (parts[1] ?? parts[0])?.trim();
|
|
996
|
+
if (!method || !isHttpMethod(method)) continue;
|
|
997
|
+
|
|
998
|
+
exports.push({
|
|
999
|
+
method,
|
|
1000
|
+
handlerFile,
|
|
1001
|
+
contractRef: routePath,
|
|
1002
|
+
catchAllPrefix: catchAllRoutePrefix(routePath),
|
|
1003
|
+
source: "next-route",
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
989
1007
|
|
|
990
1008
|
for (const match of source.matchAll(exportRegex)) {
|
|
991
1009
|
const method = match[1] as HttpMethod;
|
|
@@ -1384,7 +1402,7 @@ async function inspectDiagnostics(
|
|
|
1384
1402
|
convention,
|
|
1385
1403
|
contracts,
|
|
1386
1404
|
)),
|
|
1387
|
-
...(await inspectServerlessFootguns(targetDir, files)),
|
|
1405
|
+
...(await inspectServerlessFootguns(targetDir, files, config, convention)),
|
|
1388
1406
|
...(await inspectProductionReadiness(targetDir, files, config, convention)),
|
|
1389
1407
|
...(await inspectFeatureArtifactDrift(
|
|
1390
1408
|
targetDir,
|
|
@@ -3773,6 +3791,8 @@ function isWorkflowTestFile(file: string): boolean {
|
|
|
3773
3791
|
async function inspectServerlessFootguns(
|
|
3774
3792
|
targetDir: string,
|
|
3775
3793
|
files: string[],
|
|
3794
|
+
config: ResolvedBeignetConfig,
|
|
3795
|
+
convention: InspectConvention,
|
|
3776
3796
|
): Promise<InspectDiagnostic[]> {
|
|
3777
3797
|
const diagnostics: InspectDiagnostic[] = [];
|
|
3778
3798
|
|
|
@@ -3792,6 +3812,19 @@ async function inspectServerlessFootguns(
|
|
|
3792
3812
|
/(^|\/)[^/]*provider[^/]*\.ts$/.test(file);
|
|
3793
3813
|
const source = await readFile(path.join(targetDir, file), "utf8");
|
|
3794
3814
|
|
|
3815
|
+
if (
|
|
3816
|
+
convention.resourceGenerator &&
|
|
3817
|
+
isNextRouteFile(file, config) &&
|
|
3818
|
+
importsEagerServer(source, file, files, config)
|
|
3819
|
+
) {
|
|
3820
|
+
diagnostics.push({
|
|
3821
|
+
severity: "warning",
|
|
3822
|
+
code: "BEIGNET_NEXT_ROUTE_EAGER_SERVER_IMPORT",
|
|
3823
|
+
file,
|
|
3824
|
+
message: `${file} imports the eager server singleton. Next.js imports route modules during production builds, so use createNextServerLoader(...) in ${config.paths.server} and pass getServer to createApiRoute(...), createHealthRoute(...), or the focused route helper instead.`,
|
|
3825
|
+
});
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3795
3828
|
if (
|
|
3796
3829
|
isInfraOrServerFile &&
|
|
3797
3830
|
isProviderFile &&
|
|
@@ -3850,6 +3883,37 @@ async function inspectServerlessFootguns(
|
|
|
3850
3883
|
return diagnostics;
|
|
3851
3884
|
}
|
|
3852
3885
|
|
|
3886
|
+
function isNextRouteFile(file: string, config: ResolvedBeignetConfig): boolean {
|
|
3887
|
+
const routesPath = directoryPath(config.paths.routes);
|
|
3888
|
+
|
|
3889
|
+
return (
|
|
3890
|
+
file.startsWith(`${routesPath}/`) &&
|
|
3891
|
+
file.endsWith("/route.ts") &&
|
|
3892
|
+
!file.endsWith(".test.ts")
|
|
3893
|
+
);
|
|
3894
|
+
}
|
|
3895
|
+
|
|
3896
|
+
function importsEagerServer(
|
|
3897
|
+
source: string,
|
|
3898
|
+
importerFile: string,
|
|
3899
|
+
files: string[],
|
|
3900
|
+
config: ResolvedBeignetConfig,
|
|
3901
|
+
): boolean {
|
|
3902
|
+
const importRegex = /import\s+\{([^}]+)\}\s+from\s+["']([^"']+)["']/g;
|
|
3903
|
+
|
|
3904
|
+
for (const match of source.matchAll(importRegex)) {
|
|
3905
|
+
const members = match[1]
|
|
3906
|
+
.split(",")
|
|
3907
|
+
.map((member) => parseImportMember(member));
|
|
3908
|
+
if (!members.some((member) => member?.importedName === "server")) continue;
|
|
3909
|
+
|
|
3910
|
+
const sourceFile = sourceFileFromImport(match[2], importerFile, files);
|
|
3911
|
+
if (sourceFile === config.paths.server) return true;
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
return false;
|
|
3915
|
+
}
|
|
3916
|
+
|
|
3853
3917
|
function hasOutboxRegistry(files: string[]): boolean {
|
|
3854
3918
|
return files.some(isOutboxRegistryFile);
|
|
3855
3919
|
}
|
|
@@ -4076,7 +4140,9 @@ async function inspectDatabaseLifecycleDrift(
|
|
|
4076
4140
|
{
|
|
4077
4141
|
script: "db:seed",
|
|
4078
4142
|
command: "seed",
|
|
4079
|
-
|
|
4143
|
+
// The seed entrypoint lives beside the server runtime because it boots
|
|
4144
|
+
// the app through getServer(), which infra/ must not import.
|
|
4145
|
+
file: `${directoryPath(path.dirname(config.paths.server))}/seed.ts`,
|
|
4080
4146
|
code: "BEIGNET_DB_SEED_ENTRYPOINT_MISSING",
|
|
4081
4147
|
},
|
|
4082
4148
|
{
|