@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.
Files changed (77) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +120 -96
  3. package/dist/choices.d.ts +17 -21
  4. package/dist/choices.d.ts.map +1 -1
  5. package/dist/choices.js +21 -67
  6. package/dist/choices.js.map +1 -1
  7. package/dist/create-prompts.d.ts +5 -6
  8. package/dist/create-prompts.d.ts.map +1 -1
  9. package/dist/create-prompts.js +15 -15
  10. package/dist/create-prompts.js.map +1 -1
  11. package/dist/create.d.ts +11 -2
  12. package/dist/create.d.ts.map +1 -1
  13. package/dist/create.js +38 -28
  14. package/dist/create.js.map +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +149 -47
  17. package/dist/index.js.map +1 -1
  18. package/dist/inspect.js +54 -1
  19. package/dist/inspect.js.map +1 -1
  20. package/dist/lib.d.ts +1 -1
  21. package/dist/lib.d.ts.map +1 -1
  22. package/dist/make/inbox.js +3 -3
  23. package/dist/make/inbox.js.map +1 -1
  24. package/dist/make/payments.js +3 -3
  25. package/dist/make/payments.js.map +1 -1
  26. package/dist/make/shared.d.ts +10 -3
  27. package/dist/make/shared.d.ts.map +1 -1
  28. package/dist/make/shared.js +7 -8
  29. package/dist/make/shared.js.map +1 -1
  30. package/dist/make.d.ts +3 -2
  31. package/dist/make.d.ts.map +1 -1
  32. package/dist/make.js +455 -185
  33. package/dist/make.js.map +1 -1
  34. package/dist/mcp.d.ts.map +1 -1
  35. package/dist/mcp.js +15 -11
  36. package/dist/mcp.js.map +1 -1
  37. package/dist/provider-add.d.ts +21 -3
  38. package/dist/provider-add.d.ts.map +1 -1
  39. package/dist/provider-add.js +101 -65
  40. package/dist/provider-add.js.map +1 -1
  41. package/dist/task.js +1 -1
  42. package/dist/task.js.map +1 -1
  43. package/dist/templates/base.d.ts +1 -1
  44. package/dist/templates/base.d.ts.map +1 -1
  45. package/dist/templates/base.js +15 -15
  46. package/dist/templates/base.js.map +1 -1
  47. package/dist/templates/index.d.ts +2 -2
  48. package/dist/templates/index.d.ts.map +1 -1
  49. package/dist/templates/index.js +5 -5
  50. package/dist/templates/index.js.map +1 -1
  51. package/dist/templates/server.d.ts.map +1 -1
  52. package/dist/templates/server.js +17 -13
  53. package/dist/templates/server.js.map +1 -1
  54. package/dist/templates/shared.d.ts +4 -4
  55. package/dist/templates/shared.d.ts.map +1 -1
  56. package/dist/templates/shared.js +6 -6
  57. package/dist/templates/shared.js.map +1 -1
  58. package/package.json +2 -2
  59. package/skills/app-structure/SKILL.md +13 -8
  60. package/src/choices.ts +38 -88
  61. package/src/create-prompts.ts +20 -21
  62. package/src/create.ts +54 -36
  63. package/src/index.ts +193 -65
  64. package/src/inspect.ts +101 -1
  65. package/src/lib.ts +1 -1
  66. package/src/make/inbox.ts +3 -3
  67. package/src/make/payments.ts +3 -3
  68. package/src/make/shared.ts +16 -10
  69. package/src/make.ts +578 -176
  70. package/src/mcp.ts +20 -13
  71. package/src/provider-add.ts +159 -79
  72. package/src/task.ts +1 -1
  73. package/src/templates/base.ts +16 -16
  74. package/src/templates/index.ts +6 -6
  75. package/src/templates/server.ts +17 -13
  76. package/src/templates/shared.ts +10 -10
  77. 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
- !/\bmaxSizeBytes\s*:/.test(source)
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 { IntegrationName } from "./templates/index.js";
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/demo-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
- auth: false,
252
- tenant: false,
251
+ authorization: false,
252
+ tenantScoped: false,
253
253
  events: false,
254
254
  softDelete: false,
255
255
  },
@@ -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/demo-billing-account");
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
- auth: false,
245
- tenant: false,
244
+ authorization: false,
245
+ tenantScoped: false,
246
246
  events: false,
247
247
  softDelete: false,
248
248
  },
@@ -45,8 +45,8 @@ export type ResourceNames = {
45
45
  export type ResourceGenerationMode = "feature" | "resource";
46
46
 
47
47
  export type ResourceGenerationOptions = {
48
- auth: boolean;
49
- tenant: boolean;
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 integrations already contribute the port) are left untouched. All
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 an integration already contributes the port.
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?.auth) {
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/name format, for example posts/published.`,
2926
+ `${label} name must use feature.name format, for example posts.published.`,
2921
2927
  );
2922
2928
  }
2923
2929