@beignet/cli 0.0.38 → 0.0.39
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 +9 -0
- package/README.md +120 -96
- 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/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/index.d.ts.map +1 -1
- package/dist/index.js +149 -47
- package/dist/index.js.map +1 -1
- package/dist/inspect.js +54 -1
- 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.js +3 -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 +455 -185
- 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/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 +13 -8
- package/src/choices.ts +38 -88
- package/src/create-prompts.ts +20 -21
- package/src/create.ts +54 -36
- package/src/index.ts +193 -65
- package/src/inspect.ts +101 -1
- package/src/lib.ts +1 -1
- package/src/make/inbox.ts +3 -3
- package/src/make/payments.ts +3 -3
- package/src/make/shared.ts +16 -10
- package/src/make.ts +578 -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/shared.ts +10 -10
- package/src/test-helpers/generated-app.ts +1 -0
package/src/inspect.ts
CHANGED
|
@@ -2115,7 +2115,13 @@ async function inspectProductionReadiness(
|
|
|
2115
2115
|
if (
|
|
2116
2116
|
isFeatureUploadDefinition(file, config) &&
|
|
2117
2117
|
containsCallExpression(source, "defineUpload") &&
|
|
2118
|
-
|
|
2118
|
+
!(await uploadHasExplicitSizeLimit(
|
|
2119
|
+
targetDir,
|
|
2120
|
+
file,
|
|
2121
|
+
source,
|
|
2122
|
+
files,
|
|
2123
|
+
sourceCache,
|
|
2124
|
+
))
|
|
2119
2125
|
) {
|
|
2120
2126
|
diagnostics.push({
|
|
2121
2127
|
severity: "warning",
|
|
@@ -2373,6 +2379,100 @@ async function inspectProductionReadiness(
|
|
|
2373
2379
|
return diagnostics;
|
|
2374
2380
|
}
|
|
2375
2381
|
|
|
2382
|
+
async function uploadHasExplicitSizeLimit(
|
|
2383
|
+
targetDir: string,
|
|
2384
|
+
file: string,
|
|
2385
|
+
source: string,
|
|
2386
|
+
files: string[],
|
|
2387
|
+
sourceCache: Map<string, string>,
|
|
2388
|
+
): Promise<boolean> {
|
|
2389
|
+
if (/\bmaxSizeBytes\s*:/.test(source)) return true;
|
|
2390
|
+
|
|
2391
|
+
const fileReference = source.match(
|
|
2392
|
+
/\bfile\s*:\s*([A-Za-z_$][A-Za-z0-9_$]*)\b/,
|
|
2393
|
+
)?.[1];
|
|
2394
|
+
if (!fileReference) return false;
|
|
2395
|
+
|
|
2396
|
+
const importPattern = /import\s*\{([\s\S]*?)\}\s*from\s*["']([^"']+)["']/g;
|
|
2397
|
+
for (const match of source.matchAll(importPattern)) {
|
|
2398
|
+
const moduleName = match[2];
|
|
2399
|
+
if (!moduleName?.startsWith(".")) continue;
|
|
2400
|
+
|
|
2401
|
+
const importedName = importedNameForLocalBinding(
|
|
2402
|
+
match[1] ?? "",
|
|
2403
|
+
fileReference,
|
|
2404
|
+
);
|
|
2405
|
+
if (!importedName) continue;
|
|
2406
|
+
|
|
2407
|
+
const importedFile = resolveLocalTypeScriptModule(file, moduleName, files);
|
|
2408
|
+
if (!importedFile) continue;
|
|
2409
|
+
|
|
2410
|
+
const importedSource = await readCachedSource(
|
|
2411
|
+
targetDir,
|
|
2412
|
+
importedFile,
|
|
2413
|
+
sourceCache,
|
|
2414
|
+
);
|
|
2415
|
+
if (
|
|
2416
|
+
exportedObjectHasProperty(importedSource, importedName, "maxSizeBytes")
|
|
2417
|
+
) {
|
|
2418
|
+
return true;
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
return false;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
function importedNameForLocalBinding(
|
|
2426
|
+
importList: string,
|
|
2427
|
+
localName: string,
|
|
2428
|
+
): string | undefined {
|
|
2429
|
+
for (const specifier of importList.split(",")) {
|
|
2430
|
+
const [importedName, aliasedLocalName] = specifier
|
|
2431
|
+
.trim()
|
|
2432
|
+
.replace(/^type\s+/, "")
|
|
2433
|
+
.split(/\s+as\s+/);
|
|
2434
|
+
if (!importedName) continue;
|
|
2435
|
+
if ((aliasedLocalName ?? importedName) === localName) return importedName;
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
return undefined;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
function exportedObjectHasProperty(
|
|
2442
|
+
source: string,
|
|
2443
|
+
exportName: string,
|
|
2444
|
+
propertyName: string,
|
|
2445
|
+
): boolean {
|
|
2446
|
+
const declaration = new RegExp(
|
|
2447
|
+
`\\bexport\\s+const\\s+${escapeRegExp(exportName)}\\s*=\\s*\\{`,
|
|
2448
|
+
).exec(source);
|
|
2449
|
+
if (!declaration) return false;
|
|
2450
|
+
|
|
2451
|
+
const openIndex = source.indexOf(
|
|
2452
|
+
"{",
|
|
2453
|
+
declaration.index + declaration[0].length - 1,
|
|
2454
|
+
);
|
|
2455
|
+
const closeIndex = matchingDelimiterIndex(source, openIndex, "{", "}");
|
|
2456
|
+
if (closeIndex < 0) return false;
|
|
2457
|
+
|
|
2458
|
+
const initializer = source.slice(openIndex, closeIndex + 1);
|
|
2459
|
+
return new RegExp(`\\b${escapeRegExp(propertyName)}\\s*:`).test(initializer);
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
function resolveLocalTypeScriptModule(
|
|
2463
|
+
importer: string,
|
|
2464
|
+
moduleName: string,
|
|
2465
|
+
files: string[],
|
|
2466
|
+
): string | undefined {
|
|
2467
|
+
const base = normalizePath(
|
|
2468
|
+
path.posix.normalize(
|
|
2469
|
+
path.posix.join(path.posix.dirname(importer), moduleName),
|
|
2470
|
+
),
|
|
2471
|
+
);
|
|
2472
|
+
const candidates = [base, `${base}.ts`, `${base}.tsx`, `${base}/index.ts`];
|
|
2473
|
+
return candidates.find((candidate) => files.includes(candidate));
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2376
2476
|
async function hasReadinessCheck(
|
|
2377
2477
|
targetDir: string,
|
|
2378
2478
|
files: string[],
|
package/src/lib.ts
CHANGED
|
@@ -43,4 +43,4 @@ export {
|
|
|
43
43
|
export { runOutboxDrain } from "./outbox.js";
|
|
44
44
|
export { runAppSchedule } from "./schedule.js";
|
|
45
45
|
export { runAppTask } from "./task.js";
|
|
46
|
-
export type {
|
|
46
|
+
export type { StarterProviderName } from "./templates/index.js";
|
package/src/make/inbox.ts
CHANGED
|
@@ -160,7 +160,7 @@ export async function makeInbox(
|
|
|
160
160
|
.map((file) => file.path);
|
|
161
161
|
const files = generatedFiles.map((file) => file.path);
|
|
162
162
|
const dryRun = Boolean(options.dryRun);
|
|
163
|
-
const inboxSeedNames = seedNames("inbox
|
|
163
|
+
const inboxSeedNames = seedNames("inbox.demo-inbox");
|
|
164
164
|
const seedScript = { "db:seed": `tsx ${seedEntrypointPath(config)}` };
|
|
165
165
|
|
|
166
166
|
const recordSeedEntrypoint = (result: "created" | "updated" | "skipped") => {
|
|
@@ -248,8 +248,8 @@ export async function updateInboxWiring(
|
|
|
248
248
|
await updatePortsIndex(targetDir, inboxNames, config, {
|
|
249
249
|
...options,
|
|
250
250
|
generationOptions: {
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
authorization: false,
|
|
252
|
+
tenantScoped: false,
|
|
253
253
|
events: false,
|
|
254
254
|
softDelete: false,
|
|
255
255
|
},
|
package/src/make/payments.ts
CHANGED
|
@@ -93,7 +93,7 @@ export async function makePayments(
|
|
|
93
93
|
force: Boolean(options.force),
|
|
94
94
|
});
|
|
95
95
|
const billingNames = resourceNames("billing");
|
|
96
|
-
const billingSeedNames = seedNames("billing
|
|
96
|
+
const billingSeedNames = seedNames("billing.demo-billing-account");
|
|
97
97
|
const plannedBillingUpdates = await updatePaymentsWiring(
|
|
98
98
|
targetDir,
|
|
99
99
|
billingNames,
|
|
@@ -241,8 +241,8 @@ export async function updatePaymentsWiring(
|
|
|
241
241
|
await updatePortsIndex(targetDir, billingNames, config, {
|
|
242
242
|
...options,
|
|
243
243
|
generationOptions: {
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
authorization: false,
|
|
245
|
+
tenantScoped: false,
|
|
246
246
|
events: false,
|
|
247
247
|
softDelete: false,
|
|
248
248
|
},
|
package/src/make/shared.ts
CHANGED
|
@@ -45,8 +45,8 @@ export type ResourceNames = {
|
|
|
45
45
|
export type ResourceGenerationMode = "feature" | "resource";
|
|
46
46
|
|
|
47
47
|
export type ResourceGenerationOptions = {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
authorization: boolean;
|
|
49
|
+
tenantScoped: boolean;
|
|
50
50
|
events: boolean;
|
|
51
51
|
softDelete: boolean;
|
|
52
52
|
};
|
|
@@ -220,6 +220,13 @@ export type UploadNames = FeatureArtifactNames & {
|
|
|
220
220
|
uploadExportName: string;
|
|
221
221
|
metadataSchemaName: string;
|
|
222
222
|
metadataTypeName: string;
|
|
223
|
+
fileConstraintsExportName: string;
|
|
224
|
+
manifestExportName: string;
|
|
225
|
+
manifestFileName: string;
|
|
226
|
+
reactUploadsExportName: string;
|
|
227
|
+
clientFileName: string;
|
|
228
|
+
componentExportName: string;
|
|
229
|
+
componentFileName: string;
|
|
223
230
|
};
|
|
224
231
|
|
|
225
232
|
export type FeatureUiNames = ResourceNames & {
|
|
@@ -502,7 +509,7 @@ export function wireListenersProviderSource(
|
|
|
502
509
|
*
|
|
503
510
|
* Each wiring is independent and skipped silently when its port key already
|
|
504
511
|
* appears in the ports file, so apps that wired their own adapter (or scaffolds
|
|
505
|
-
* whose
|
|
512
|
+
* whose providers already contribute the port) are left untouched. All
|
|
506
513
|
* anchors are computed before any file is written; an anchor miss aborts with a
|
|
507
514
|
* copy-pasteable manual instruction so the generator never leaves partial
|
|
508
515
|
* wiring behind. Callers validate anchors with `dryRun: true` before writing
|
|
@@ -529,7 +536,7 @@ export async function wirePortProviders(
|
|
|
529
536
|
}
|
|
530
537
|
|
|
531
538
|
// A port key that already appears in the ports file means the app wired its
|
|
532
|
-
// own adapter or
|
|
539
|
+
// own adapter or a provider already contributes the port.
|
|
533
540
|
const active = wirings.filter(
|
|
534
541
|
(wiring) => !new RegExp(`\\b${wiring.portKey}\\b`).test(portsOriginal),
|
|
535
542
|
);
|
|
@@ -1179,7 +1186,7 @@ export async function updatePortsIndex(
|
|
|
1179
1186
|
next = insertAfterImports(next, importLine);
|
|
1180
1187
|
}
|
|
1181
1188
|
|
|
1182
|
-
if (options.generationOptions?.
|
|
1189
|
+
if (options.generationOptions?.authorization) {
|
|
1183
1190
|
const policyPath = path.join(
|
|
1184
1191
|
config.paths.features,
|
|
1185
1192
|
names.pluralKebab,
|
|
@@ -2911,13 +2918,12 @@ export function artifactNameParts(
|
|
|
2911
2918
|
): [string, string] {
|
|
2912
2919
|
const parts = input
|
|
2913
2920
|
.trim()
|
|
2914
|
-
.split("
|
|
2915
|
-
.map((part) => part.trim())
|
|
2916
|
-
.filter(Boolean);
|
|
2921
|
+
.split(".")
|
|
2922
|
+
.map((part) => part.trim());
|
|
2917
2923
|
|
|
2918
|
-
if (parts.length !== 2) {
|
|
2924
|
+
if (parts.length !== 2 || parts.some((part) => part.length === 0)) {
|
|
2919
2925
|
throw new Error(
|
|
2920
|
-
`${label} name must use feature
|
|
2926
|
+
`${label} name must use feature.name format, for example posts.published.`,
|
|
2921
2927
|
);
|
|
2922
2928
|
}
|
|
2923
2929
|
|