@stardeck-customer-apps/compose 0.9.0 → 0.10.0

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/dist/index.js CHANGED
@@ -2027,6 +2027,7 @@ var require_semver2 = __commonJS({
2027
2027
  // src/index.ts
2028
2028
  var index_exports = {};
2029
2029
  __export(index_exports, {
2030
+ BUILD_TSCONFIG_PATH: () => BUILD_TSCONFIG_PATH,
2030
2031
  COMPOSE_INPUTS_PATH: () => COMPOSE_INPUTS_PATH,
2031
2032
  assertSupportedTypescript: () => assertSupportedTypescript,
2032
2033
  compose: () => compose,
@@ -2098,11 +2099,54 @@ function shellQuote(value) {
2098
2099
  return `'${value.replace(/'/g, `'\\''`)}'`;
2099
2100
  }
2100
2101
 
2101
- // ../../packages/lib/src/shared/module-composition.ts
2102
- var import_zod6 = require("zod");
2102
+ // ../../packages/lib/src/shared/compose-inputs.ts
2103
+ var import_zod = require("zod");
2104
+ var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
2105
+ var composeInputsSchema = import_zod.z.strictObject({
2106
+ connectedStores: import_zod.z.array(
2107
+ import_zod.z.strictObject({
2108
+ storeId: import_zod.z.string().min(1),
2109
+ slug: import_zod.z.string().min(1),
2110
+ // A row with an empty binding key must not fail a deploy: the rail
2111
+ // treats falsy as "no binding key", so normalise rather than reject.
2112
+ bindingKey: import_zod.z.string().nullish().transform((value) => value || null),
2113
+ accessLevel: import_zod.z.enum(["read", "write", "admin"]),
2114
+ // Defaulted so a file written before the platform emitted store types
2115
+ // (database rows only) still parses. The platform starts writing
2116
+ // storage rows, with `type` set, once forks run a compose that reads it.
2117
+ type: import_zod.z.enum(["database", "storage"]).default("database")
2118
+ })
2119
+ ).default([]),
2120
+ installs: import_zod.z.record(
2121
+ import_zod.z.string(),
2122
+ import_zod.z.strictObject({
2123
+ installedVersion: import_zod.z.string().min(1),
2124
+ datastoreBindings: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).nullish()
2125
+ })
2126
+ ).default({})
2127
+ });
2128
+ var STUB_IGNORE_PATH = "apps/web/src/app/.gitignore";
2129
+ var STUB_IGNORE_HEADER = "# Generated by stardeck-compose \u2014 Module-rail stubs are build outputs; do not edit or commit them.";
2130
+ function escapeStubIgnorePattern(pattern) {
2131
+ const escaped = pattern.replace(/[\\[\]*?]/g, (char) => `\\${char}`);
2132
+ return /^[#!]/.test(escaped) ? `\\${escaped}` : escaped;
2133
+ }
2134
+ function buildStubIgnore(artifactPaths) {
2135
+ const prefix = "apps/web/src/app/";
2136
+ const entries = artifactPaths.filter((artifact) => artifact.startsWith(prefix)).map((artifact) => escapeStubIgnorePattern(`/${artifact.slice(prefix.length)}`)).sort();
2137
+ return [STUB_IGNORE_HEADER, ...entries].join("\n") + "\n";
2138
+ }
2139
+
2140
+ // ../../packages/lib/src/shared/module-enablement.ts
2141
+ function isModuleEnabledByList(raw, name, kindOf) {
2142
+ if (!raw) return true;
2143
+ const kind = kindOf(name);
2144
+ if (kind != null && kind !== "feature") return true;
2145
+ return raw.split(",").includes(name);
2146
+ }
2103
2147
 
2104
2148
  // ../../packages/module-contract/src/module-manifest.ts
2105
- var import_zod = require("zod");
2149
+ var import_zod2 = require("zod");
2106
2150
 
2107
2151
  // ../../packages/module-contract/src/slug.ts
2108
2152
  function validateSlug(slug) {
@@ -2137,13 +2181,13 @@ var ROUTE_GROUP_REGEX = /^\([a-z0-9-]+\)$/;
2137
2181
  var ENDPOINT_STATIC_SEGMENT_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2138
2182
  var ENDPOINT_PARAM_NAME_REGEX = /^[a-z][a-z0-9_-]*$/;
2139
2183
  var ENDPOINT_METHODS = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
2140
- var moduleNameSchema = import_zod.z.string().max(40).regex(KEBAB_SLUG_REGEX, "must be a kebab-case slug (lowercase letters, digits, hyphens)");
2184
+ var moduleNameSchema = import_zod2.z.string().max(40).regex(KEBAB_SLUG_REGEX, "must be a kebab-case slug (lowercase letters, digits, hyphens)");
2141
2185
  function isValidModuleName(value) {
2142
2186
  return moduleNameSchema.safeParse(value).success;
2143
2187
  }
2144
- var projectSlugSchema = import_zod.z.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
2145
- var moduleKindSchema = import_zod.z.enum(["feature", "library", "contract"]);
2146
- var endpointMethodSchema = import_zod.z.enum(ENDPOINT_METHODS);
2188
+ var projectSlugSchema = import_zod2.z.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
2189
+ var moduleKindSchema = import_zod2.z.enum(["feature", "library", "contract"]);
2190
+ var endpointMethodSchema = import_zod2.z.enum(ENDPOINT_METHODS);
2147
2191
  function endpointPathValidationError(path4) {
2148
2192
  if (!path4.startsWith("/api/")) {
2149
2193
  return 'must begin with "/api/"';
@@ -2228,21 +2272,21 @@ function normalizeEndpointPathForCollision(path4) {
2228
2272
  return segment;
2229
2273
  }).join("/");
2230
2274
  }
2231
- var endpointPathSchema = import_zod.z.string().superRefine((path4, ctx) => {
2275
+ var endpointPathSchema = import_zod2.z.string().superRefine((path4, ctx) => {
2232
2276
  const error = endpointPathValidationError(path4);
2233
2277
  if (error != null) {
2234
- ctx.addIssue({ code: import_zod.z.ZodIssueCode.custom, message: error });
2278
+ ctx.addIssue({ code: import_zod2.z.ZodIssueCode.custom, message: error });
2235
2279
  }
2236
2280
  });
2237
- var endpointClaimSchema = import_zod.z.object({
2281
+ var endpointClaimSchema = import_zod2.z.object({
2238
2282
  path: endpointPathSchema,
2239
- methods: import_zod.z.array(endpointMethodSchema).min(1, "methods must be non-empty").superRefine((methods, ctx) => {
2283
+ methods: import_zod2.z.array(endpointMethodSchema).min(1, "methods must be non-empty").superRefine((methods, ctx) => {
2240
2284
  const seen = /* @__PURE__ */ new Set();
2241
2285
  for (let i = 0; i < methods.length; i += 1) {
2242
2286
  const method = methods[i];
2243
2287
  if (seen.has(method)) {
2244
2288
  ctx.addIssue({
2245
- code: import_zod.z.ZodIssueCode.custom,
2289
+ code: import_zod2.z.ZodIssueCode.custom,
2246
2290
  message: `duplicate method "${method}"`,
2247
2291
  path: [i]
2248
2292
  });
@@ -2279,14 +2323,14 @@ function mountSegmentValidationError(segment) {
2279
2323
  }
2280
2324
  return null;
2281
2325
  }
2282
- var mountSegmentSchema = import_zod.z.string().superRefine((segment, ctx) => {
2326
+ var mountSegmentSchema = import_zod2.z.string().superRefine((segment, ctx) => {
2283
2327
  const error = mountSegmentValidationError(segment);
2284
2328
  if (error != null) {
2285
- ctx.addIssue({ code: import_zod.z.ZodIssueCode.custom, message: error });
2329
+ ctx.addIssue({ code: import_zod2.z.ZodIssueCode.custom, message: error });
2286
2330
  }
2287
2331
  });
2288
- var mountSchema = import_zod.z.object({
2289
- group: import_zod.z.string().regex(ROUTE_GROUP_REGEX, 'must be a Next.js route group like "(admin)"'),
2332
+ var mountSchema = import_zod2.z.object({
2333
+ group: import_zod2.z.string().regex(ROUTE_GROUP_REGEX, 'must be a Next.js route group like "(admin)"'),
2290
2334
  segment: mountSegmentSchema
2291
2335
  }).strict();
2292
2336
  function splitMountSegment(segment) {
@@ -2299,21 +2343,21 @@ function splitMountSegment(segment) {
2299
2343
  }
2300
2344
  return segment.split("/");
2301
2345
  }
2302
- var tableNameSchema = import_zod.z.string().regex(SNAKE_TABLE_REGEX, "must be snake_case");
2346
+ var tableNameSchema = import_zod2.z.string().regex(SNAKE_TABLE_REGEX, "must be snake_case");
2303
2347
  var NPM_PACKAGE_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
2304
- var npmPackageNameSchema = import_zod.z.string().max(214).regex(NPM_PACKAGE_NAME_REGEX, "must be a valid npm package name");
2305
- var descriptionSchema = import_zod.z.string().max(200, "must be at most 200 characters").refine((value) => value.trim().length > 0, "must be non-empty after trimming");
2306
- var crossAppSchema = import_zod.z.object({
2307
- exposes: import_zod.z.array(import_zod.z.unknown()).max(0, "must be empty until cross-app contracts are defined"),
2308
- consumes: import_zod.z.array(import_zod.z.unknown()).max(0, "must be empty until cross-app contracts are defined")
2348
+ var npmPackageNameSchema = import_zod2.z.string().max(214).regex(NPM_PACKAGE_NAME_REGEX, "must be a valid npm package name");
2349
+ var descriptionSchema = import_zod2.z.string().max(200, "must be at most 200 characters").refine((value) => value.trim().length > 0, "must be non-empty after trimming");
2350
+ var crossAppSchema = import_zod2.z.object({
2351
+ exposes: import_zod2.z.array(import_zod2.z.unknown()).max(0, "must be empty until cross-app contracts are defined"),
2352
+ consumes: import_zod2.z.array(import_zod2.z.unknown()).max(0, "must be empty until cross-app contracts are defined")
2309
2353
  }).strict();
2310
- var enhancementWorkflowsSchema = import_zod.z.record(moduleNameSchema, import_zod.z.array(import_zod.z.string().min(1))).default({});
2311
- var enhancementEndpointsSchema = import_zod.z.record(moduleNameSchema, import_zod.z.array(endpointClaimSchema)).default({});
2312
- var datastoreRequirementSchema = import_zod.z.object({
2354
+ var enhancementWorkflowsSchema = import_zod2.z.record(moduleNameSchema, import_zod2.z.array(import_zod2.z.string().min(1))).default({});
2355
+ var enhancementEndpointsSchema = import_zod2.z.record(moduleNameSchema, import_zod2.z.array(endpointClaimSchema)).default({});
2356
+ var datastoreRequirementSchema = import_zod2.z.object({
2313
2357
  /** Logical name, module-local, snake_case. Never a physical store key. */
2314
2358
  id: tableNameSchema,
2315
2359
  /** "app" = this project's app-local store; "org" = an org-level shared store. */
2316
- scope: import_zod.z.enum(["app", "org"]).default("app"),
2360
+ scope: import_zod2.z.enum(["app", "org"]).default("app"),
2317
2361
  /**
2318
2362
  * Which kind of connected store satisfies this requirement. A "database"
2319
2363
  * requirement only ever binds to a database store and a "storage" one
@@ -2321,34 +2365,34 @@ var datastoreRequirementSchema = import_zod.z.object({
2321
2365
  * rail never crosses the two. Defaults to "database", the only kind the
2322
2366
  * rail resolved before this field existed.
2323
2367
  */
2324
- type: import_zod.z.enum(["database", "storage"]).default("database"),
2368
+ type: import_zod2.z.enum(["database", "storage"]).default("database"),
2325
2369
  /** true → install fails when no store resolves; false → binding omitted, module degrades. */
2326
- required: import_zod.z.boolean().default(true),
2370
+ required: import_zod2.z.boolean().default(true),
2327
2371
  /** Checked against the connected store's accessLevel at install. */
2328
- access: import_zod.z.enum(["read", "write", "admin"]).default("write")
2372
+ access: import_zod2.z.enum(["read", "write", "admin"]).default("write")
2329
2373
  }).strict();
2330
- var permissionClaimSchema = import_zod.z.object({
2374
+ var permissionClaimSchema = import_zod2.z.object({
2331
2375
  /**
2332
2376
  * Lowercase resource:action with one colon and no underscores. This grammar
2333
2377
  * is deliberately narrower than the platform permission tool's charset.
2334
2378
  */
2335
- key: import_zod.z.string().regex(/^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*$/, "must be a lowercase resource:action key").max(100, "must be at most 100 characters (platform permission tool limit)"),
2379
+ key: import_zod2.z.string().regex(/^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*$/, "must be a lowercase resource:action key").max(100, "must be at most 100 characters (platform permission tool limit)"),
2336
2380
  /** Human label for the deployment auth config row. */
2337
2381
  description: descriptionSchema
2338
2382
  }).strict();
2339
- var seedBundleSchema = import_zod.z.object({
2383
+ var seedBundleSchema = import_zod2.z.object({
2340
2384
  table: tableNameSchema,
2341
2385
  /** Columns forming the ON CONFLICT key — must appear in every row. */
2342
- conflictTarget: import_zod.z.array(import_zod.z.string().min(1)).min(1),
2386
+ conflictTarget: import_zod2.z.array(import_zod2.z.string().min(1)).min(1),
2343
2387
  /** Scalar JSON values only (no nested objects/arrays). */
2344
- rows: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.string(), import_zod.z.number(), import_zod.z.boolean(), import_zod.z.null()]))).min(1)
2388
+ rows: import_zod2.z.array(import_zod2.z.record(import_zod2.z.string(), import_zod2.z.union([import_zod2.z.string(), import_zod2.z.number(), import_zod2.z.boolean(), import_zod2.z.null()]))).min(1)
2345
2389
  }).strict().superRefine((bundle, ctx) => {
2346
2390
  const rowKeys = bundle.rows.map((row) => Object.keys(row).sort().join("\0"));
2347
2391
  const canonical = rowKeys[0];
2348
2392
  for (let i = 1; i < rowKeys.length; i += 1) {
2349
2393
  if (rowKeys[i] !== canonical) {
2350
2394
  ctx.addIssue({
2351
- code: import_zod.z.ZodIssueCode.custom,
2395
+ code: import_zod2.z.ZodIssueCode.custom,
2352
2396
  message: "all rows in a seed bundle must have identical key sets",
2353
2397
  path: ["rows", i]
2354
2398
  });
@@ -2360,7 +2404,7 @@ var seedBundleSchema = import_zod.z.object({
2360
2404
  for (const col of bundle.conflictTarget) {
2361
2405
  if (!keys.has(col)) {
2362
2406
  ctx.addIssue({
2363
- code: import_zod.z.ZodIssueCode.custom,
2407
+ code: import_zod2.z.ZodIssueCode.custom,
2364
2408
  message: `conflictTarget column "${col}" must be present in every row`,
2365
2409
  path: ["rows", i]
2366
2410
  });
@@ -2368,35 +2412,35 @@ var seedBundleSchema = import_zod.z.object({
2368
2412
  }
2369
2413
  }
2370
2414
  });
2371
- var moduleManifestSchema = import_zod.z.object({
2415
+ var moduleManifestSchema = import_zod2.z.object({
2372
2416
  name: moduleNameSchema,
2373
2417
  kind: moduleKindSchema,
2374
2418
  // Release versions are platform-owned in module_versions. Accept this
2375
2419
  // legacy field while existing Module source ages out, but strip it from the
2376
2420
  // parsed contract so no runtime can treat module.json as version authority.
2377
- version: import_zod.z.unknown().optional(),
2421
+ version: import_zod2.z.unknown().optional(),
2378
2422
  home: projectSlugSchema,
2379
2423
  /** Machine-checkable purpose line — required, ≤200 code units, non-blank when trimmed. */
2380
2424
  description: descriptionSchema,
2381
- uses: import_zod.z.array(moduleNameSchema).default([]),
2425
+ uses: import_zod2.z.array(moduleNameSchema).default([]),
2382
2426
  /**
2383
2427
  * Soft peers: this module ships `enhancements/<peer>/` directories that are
2384
2428
  * composition-pruned — the installer includes them only when the peer is
2385
2429
  * present, so the peer is NOT an install-time requirement. Disjoint from
2386
2430
  * `uses`; entries may name modules absent from the composition.
2387
2431
  */
2388
- enhancements: import_zod.z.array(moduleNameSchema).default([]),
2389
- tables: import_zod.z.array(tableNameSchema).default([]),
2390
- mounts: import_zod.z.array(mountSchema).default([]),
2391
- integration: import_zod.z.array(import_zod.z.string()).default([]),
2392
- workflows: import_zod.z.array(import_zod.z.string().min(1)).default([]),
2432
+ enhancements: import_zod2.z.array(moduleNameSchema).default([]),
2433
+ tables: import_zod2.z.array(tableNameSchema).default([]),
2434
+ mounts: import_zod2.z.array(mountSchema).default([]),
2435
+ integration: import_zod2.z.array(import_zod2.z.string()).default([]),
2436
+ workflows: import_zod2.z.array(import_zod2.z.string().min(1)).default([]),
2393
2437
  /**
2394
2438
  * Slice-scoped workflow names keyed by peer. Keys must be ⊆ `enhancements`;
2395
2439
  * names must be unique across root `workflows` and every slice list.
2396
2440
  */
2397
2441
  enhancementWorkflows: enhancementWorkflowsSchema,
2398
2442
  /** Root API endpoint path claims. */
2399
- endpoints: import_zod.z.array(endpointClaimSchema).default([]),
2443
+ endpoints: import_zod2.z.array(endpointClaimSchema).default([]),
2400
2444
  /**
2401
2445
  * Slice-scoped endpoint claims keyed by peer. Keys must be ⊆ `enhancements`;
2402
2446
  * normalized paths must be unique across root and every slice.
@@ -2412,38 +2456,38 @@ var moduleManifestSchema = import_zod.z.object({
2412
2456
  * to a physical connected store and generates module-datastores.gen.ts;
2413
2457
  * unlike seeds, this field drives generated output.
2414
2458
  */
2415
- datastores: import_zod.z.array(datastoreRequirementSchema).optional(),
2459
+ datastores: import_zod2.z.array(datastoreRequirementSchema).optional(),
2416
2460
  /**
2417
2461
  * Keys this module's guards enforce. Install registers them in deployment
2418
2462
  * auth config; registration only — declaring is never granting.
2419
2463
  */
2420
- permissions: import_zod.z.array(permissionClaimSchema).optional(),
2464
+ permissions: import_zod2.z.array(permissionClaimSchema).optional(),
2421
2465
  /**
2422
2466
  * Optional starter rows for tables this module owns. Replay is
2423
2467
  * `INSERT ... ON CONFLICT (conflictTarget) DO NOTHING` — idempotent by
2424
2468
  * construction; the rail (not this schema) performs the replay.
2425
2469
  */
2426
- seeds: import_zod.z.array(seedBundleSchema).optional(),
2470
+ seeds: import_zod2.z.array(seedBundleSchema).optional(),
2427
2471
  /** npm packages the source imports beyond the base app. Names only; the rail installs each at the home app's range. */
2428
- packages: import_zod.z.array(npmPackageNameSchema).optional(),
2472
+ packages: import_zod2.z.array(npmPackageNameSchema).optional(),
2429
2473
  /**
2430
2474
  * UI-layer contract. `separable: true` asserts the Module's components/ and
2431
2475
  * routes/ hold presentation only — the Blueprint's
2432
2476
  * `module-boundaries/ui-layer` lint rule enforces it — so a fork may
2433
2477
  * soft-eject them. See docs/module-ui-soft-eject-plan.md.
2434
2478
  */
2435
- ui: import_zod.z.object({ separable: import_zod.z.boolean() }).strict().optional()
2479
+ ui: import_zod2.z.object({ separable: import_zod2.z.boolean() }).strict().optional()
2436
2480
  }).strict().superRefine((manifest, ctx) => {
2437
2481
  if (manifest.uses.includes(manifest.name)) {
2438
2482
  ctx.addIssue({
2439
- code: import_zod.z.ZodIssueCode.custom,
2483
+ code: import_zod2.z.ZodIssueCode.custom,
2440
2484
  message: "a module cannot list itself in uses",
2441
2485
  path: ["uses"]
2442
2486
  });
2443
2487
  }
2444
2488
  if (manifest.enhancements.includes(manifest.name)) {
2445
2489
  ctx.addIssue({
2446
- code: import_zod.z.ZodIssueCode.custom,
2490
+ code: import_zod2.z.ZodIssueCode.custom,
2447
2491
  message: "a module cannot list itself in enhancements",
2448
2492
  path: ["enhancements"]
2449
2493
  });
@@ -2451,7 +2495,7 @@ var moduleManifestSchema = import_zod.z.object({
2451
2495
  const hardAndSoft = manifest.enhancements.filter((peer) => manifest.uses.includes(peer));
2452
2496
  if (hardAndSoft.length > 0) {
2453
2497
  ctx.addIssue({
2454
- code: import_zod.z.ZodIssueCode.custom,
2498
+ code: import_zod2.z.ZodIssueCode.custom,
2455
2499
  message: `uses and enhancements must be disjoint (a peer is either a hard dep or a soft one): ${hardAndSoft.join(", ")}`,
2456
2500
  path: ["enhancements"]
2457
2501
  });
@@ -2460,7 +2504,7 @@ var moduleManifestSchema = import_zod.z.object({
2460
2504
  for (const peer of Object.keys(manifest.enhancementWorkflows)) {
2461
2505
  if (!enhancementPeers.has(peer)) {
2462
2506
  ctx.addIssue({
2463
- code: import_zod.z.ZodIssueCode.custom,
2507
+ code: import_zod2.z.ZodIssueCode.custom,
2464
2508
  message: `enhancementWorkflows key "${peer}" must be listed in enhancements`,
2465
2509
  path: ["enhancementWorkflows", peer]
2466
2510
  });
@@ -2469,7 +2513,7 @@ var moduleManifestSchema = import_zod.z.object({
2469
2513
  for (const peer of Object.keys(manifest.enhancementEndpoints)) {
2470
2514
  if (!enhancementPeers.has(peer)) {
2471
2515
  ctx.addIssue({
2472
- code: import_zod.z.ZodIssueCode.custom,
2516
+ code: import_zod2.z.ZodIssueCode.custom,
2473
2517
  message: `enhancementEndpoints key "${peer}" must be listed in enhancements`,
2474
2518
  path: ["enhancementEndpoints", peer]
2475
2519
  });
@@ -2480,7 +2524,7 @@ var moduleManifestSchema = import_zod.z.object({
2480
2524
  const existing = seenWorkflows.get(name);
2481
2525
  if (existing != null) {
2482
2526
  ctx.addIssue({
2483
- code: import_zod.z.ZodIssueCode.custom,
2527
+ code: import_zod2.z.ZodIssueCode.custom,
2484
2528
  message: `duplicate workflow name "${name}" (also at ${existing})`,
2485
2529
  path: path4
2486
2530
  });
@@ -2507,7 +2551,7 @@ var moduleManifestSchema = import_zod.z.object({
2507
2551
  const existing = seenEndpointKeys.get(key);
2508
2552
  if (existing != null) {
2509
2553
  ctx.addIssue({
2510
- code: import_zod.z.ZodIssueCode.custom,
2554
+ code: import_zod2.z.ZodIssueCode.custom,
2511
2555
  message: `duplicate normalized endpoint path "${key}" (also at ${existing})`,
2512
2556
  path: path4
2513
2557
  });
@@ -2529,7 +2573,7 @@ var moduleManifestSchema = import_zod.z.object({
2529
2573
  const id = manifest.datastores[i].id;
2530
2574
  if (seenDatastoreIds.has(id)) {
2531
2575
  ctx.addIssue({
2532
- code: import_zod.z.ZodIssueCode.custom,
2576
+ code: import_zod2.z.ZodIssueCode.custom,
2533
2577
  message: `duplicate datastore id "${id}"`,
2534
2578
  path: ["datastores", i, "id"]
2535
2579
  });
@@ -2544,7 +2588,7 @@ var moduleManifestSchema = import_zod.z.object({
2544
2588
  const key = manifest.permissions[i].key;
2545
2589
  if (seenPermissionKeys.has(key)) {
2546
2590
  ctx.addIssue({
2547
- code: import_zod.z.ZodIssueCode.custom,
2591
+ code: import_zod2.z.ZodIssueCode.custom,
2548
2592
  message: `duplicate permission key "${key}"`,
2549
2593
  path: ["permissions", i, "key"]
2550
2594
  });
@@ -2556,35 +2600,35 @@ var moduleManifestSchema = import_zod.z.object({
2556
2600
  if (manifest.kind === "library") {
2557
2601
  if (manifest.tables.length > 0) {
2558
2602
  ctx.addIssue({
2559
- code: import_zod.z.ZodIssueCode.custom,
2603
+ code: import_zod2.z.ZodIssueCode.custom,
2560
2604
  message: "library modules must not declare tables",
2561
2605
  path: ["tables"]
2562
2606
  });
2563
2607
  }
2564
2608
  if (manifest.mounts.length > 0) {
2565
2609
  ctx.addIssue({
2566
- code: import_zod.z.ZodIssueCode.custom,
2610
+ code: import_zod2.z.ZodIssueCode.custom,
2567
2611
  message: "library modules must not declare mounts",
2568
2612
  path: ["mounts"]
2569
2613
  });
2570
2614
  }
2571
2615
  if (manifest.seeds != null && manifest.seeds.length > 0) {
2572
2616
  ctx.addIssue({
2573
- code: import_zod.z.ZodIssueCode.custom,
2617
+ code: import_zod2.z.ZodIssueCode.custom,
2574
2618
  message: "library modules must not declare seeds",
2575
2619
  path: ["seeds"]
2576
2620
  });
2577
2621
  }
2578
2622
  if (manifest.datastores != null && manifest.datastores.length > 0) {
2579
2623
  ctx.addIssue({
2580
- code: import_zod.z.ZodIssueCode.custom,
2624
+ code: import_zod2.z.ZodIssueCode.custom,
2581
2625
  message: "library modules must not declare datastores",
2582
2626
  path: ["datastores"]
2583
2627
  });
2584
2628
  }
2585
2629
  if (manifest.permissions != null && manifest.permissions.length > 0) {
2586
2630
  ctx.addIssue({
2587
- code: import_zod.z.ZodIssueCode.custom,
2631
+ code: import_zod2.z.ZodIssueCode.custom,
2588
2632
  message: "library modules must not declare permissions",
2589
2633
  path: ["permissions"]
2590
2634
  });
@@ -2592,7 +2636,7 @@ var moduleManifestSchema = import_zod.z.object({
2592
2636
  }
2593
2637
  if (manifest.kind === "contract" && manifest.mounts.length > 0) {
2594
2638
  ctx.addIssue({
2595
- code: import_zod.z.ZodIssueCode.custom,
2639
+ code: import_zod2.z.ZodIssueCode.custom,
2596
2640
  message: "contract modules must not declare mounts",
2597
2641
  path: ["mounts"]
2598
2642
  });
@@ -2603,7 +2647,7 @@ var moduleManifestSchema = import_zod.z.object({
2603
2647
  const bundle = manifest.seeds[i];
2604
2648
  if (!ownedTables.has(bundle.table)) {
2605
2649
  ctx.addIssue({
2606
- code: import_zod.z.ZodIssueCode.custom,
2650
+ code: import_zod2.z.ZodIssueCode.custom,
2607
2651
  message: `seeds may only target tables listed in tables (got "${bundle.table}")`,
2608
2652
  path: ["seeds", i, "table"]
2609
2653
  });
@@ -2654,10 +2698,10 @@ var MANDATORY_MODULE_CHECK_DESCRIPTORS = Object.freeze([
2654
2698
  ]);
2655
2699
 
2656
2700
  // ../../packages/module-contract/src/module-structure.ts
2657
- var import_zod3 = require("zod");
2701
+ var import_zod4 = require("zod");
2658
2702
 
2659
2703
  // ../../packages/module-contract/src/module-e2e-manifest.ts
2660
- var import_zod2 = require("zod");
2704
+ var import_zod3 = require("zod");
2661
2705
  function e2eSpecFileValidationError(file) {
2662
2706
  if (file.length === 0) {
2663
2707
  return "must be a non-empty relative path ending in .spec.ts";
@@ -2685,22 +2729,22 @@ function e2eSpecFileValidationError(file) {
2685
2729
  }
2686
2730
  return null;
2687
2731
  }
2688
- var e2eSpecFileSchema = import_zod2.z.string().superRefine((file, ctx) => {
2732
+ var e2eSpecFileSchema = import_zod3.z.string().superRefine((file, ctx) => {
2689
2733
  const error = e2eSpecFileValidationError(file);
2690
2734
  if (error != null) {
2691
- ctx.addIssue({ code: import_zod2.z.ZodIssueCode.custom, message: error });
2735
+ ctx.addIssue({ code: import_zod3.z.ZodIssueCode.custom, message: error });
2692
2736
  }
2693
2737
  });
2694
- var e2eSpecSchema = import_zod2.z.object({
2738
+ var e2eSpecSchema = import_zod3.z.object({
2695
2739
  file: e2eSpecFileSchema,
2696
- requires: import_zod2.z.array(moduleNameSchema).min(1, "requires must be non-empty")
2740
+ requires: import_zod3.z.array(moduleNameSchema).min(1, "requires must be non-empty")
2697
2741
  }).strict().superRefine((spec, ctx) => {
2698
2742
  const seen = /* @__PURE__ */ new Set();
2699
2743
  for (let i = 0; i < spec.requires.length; i += 1) {
2700
2744
  const name = spec.requires[i];
2701
2745
  if (seen.has(name)) {
2702
2746
  ctx.addIssue({
2703
- code: import_zod2.z.ZodIssueCode.custom,
2747
+ code: import_zod3.z.ZodIssueCode.custom,
2704
2748
  message: `duplicate requirement "${name}"`,
2705
2749
  path: ["requires", i]
2706
2750
  });
@@ -2709,15 +2753,15 @@ var e2eSpecSchema = import_zod2.z.object({
2709
2753
  }
2710
2754
  }
2711
2755
  });
2712
- var moduleE2eManifestSchema = import_zod2.z.object({
2713
- specs: import_zod2.z.array(e2eSpecSchema).min(1, "specs must contain at least one entry")
2756
+ var moduleE2eManifestSchema = import_zod3.z.object({
2757
+ specs: import_zod3.z.array(e2eSpecSchema).min(1, "specs must contain at least one entry")
2714
2758
  }).strict().superRefine((manifest, ctx) => {
2715
2759
  const seenFiles = /* @__PURE__ */ new Set();
2716
2760
  for (let i = 0; i < manifest.specs.length; i += 1) {
2717
2761
  const file = manifest.specs[i].file;
2718
2762
  if (seenFiles.has(file)) {
2719
2763
  ctx.addIssue({
2720
- code: import_zod2.z.ZodIssueCode.custom,
2764
+ code: import_zod3.z.ZodIssueCode.custom,
2721
2765
  message: `duplicate file "${file}"`,
2722
2766
  path: ["specs", i, "file"]
2723
2767
  });
@@ -2959,7 +3003,7 @@ function compareCodeUnit(a, b) {
2959
3003
  // ../../packages/module-contract/src/module-structure.ts
2960
3004
  var MODULE_STRUCTURE_JSON_BYTE_CAP = 64 * 1024;
2961
3005
  function uniqueSortedStringArray(label) {
2962
- return import_zod3.z.array(import_zod3.z.string()).superRefine((arr, ctx) => {
3006
+ return import_zod4.z.array(import_zod4.z.string()).superRefine((arr, ctx) => {
2963
3007
  if (new Set(arr).size !== arr.length) {
2964
3008
  ctx.addIssue({ code: "custom", message: `${label} must be unique` });
2965
3009
  return;
@@ -2975,10 +3019,10 @@ function uniqueSortedStringArray(label) {
2975
3019
  });
2976
3020
  }
2977
3021
  function contributionPermissionsSchema(label) {
2978
- return import_zod3.z.array(
2979
- import_zod3.z.object({
2980
- contributionId: import_zod3.z.string().min(1),
2981
- permission: import_zod3.z.string().min(1)
3022
+ return import_zod4.z.array(
3023
+ import_zod4.z.object({
3024
+ contributionId: import_zod4.z.string().min(1),
3025
+ permission: import_zod4.z.string().min(1)
2982
3026
  }).strict()
2983
3027
  ).superRefine((entries, ctx) => {
2984
3028
  const keys = entries.map((entry) => `${entry.contributionId}\0${entry.permission}`);
@@ -2996,17 +3040,17 @@ function contributionPermissionsSchema(label) {
2996
3040
  }
2997
3041
  }).optional();
2998
3042
  }
2999
- var collectedFilePayloadSchema = import_zod3.z.discriminatedUnion("status", [
3000
- import_zod3.z.object({ status: import_zod3.z.literal("ok"), text: import_zod3.z.string() }).strict(),
3001
- import_zod3.z.object({ status: import_zod3.z.literal("missing") }).strict(),
3002
- import_zod3.z.object({ status: import_zod3.z.literal("too-large") }).strict(),
3003
- import_zod3.z.object({ status: import_zod3.z.literal("unreadable") }).strict()
3043
+ var collectedFilePayloadSchema = import_zod4.z.discriminatedUnion("status", [
3044
+ import_zod4.z.object({ status: import_zod4.z.literal("ok"), text: import_zod4.z.string() }).strict(),
3045
+ import_zod4.z.object({ status: import_zod4.z.literal("missing") }).strict(),
3046
+ import_zod4.z.object({ status: import_zod4.z.literal("too-large") }).strict(),
3047
+ import_zod4.z.object({ status: import_zod4.z.literal("unreadable") }).strict()
3004
3048
  ]);
3005
- var collectedLocaleFileSchema = import_zod3.z.object({
3006
- locale: import_zod3.z.string().min(1),
3049
+ var collectedLocaleFileSchema = import_zod4.z.object({
3050
+ locale: import_zod4.z.string().min(1),
3007
3051
  payload: collectedFilePayloadSchema
3008
3052
  }).strict();
3009
- var collectedE2eFactsSchema = import_zod3.z.object({
3053
+ var collectedE2eFactsSchema = import_zod4.z.object({
3010
3054
  manifest: collectedFilePayloadSchema,
3011
3055
  specFiles: uniqueSortedStringArray("specFiles"),
3012
3056
  escapingSymlinks: uniqueSortedStringArray("escapingSymlinks")
@@ -3028,20 +3072,20 @@ function validateRouteExportEvidenceCongruence(input) {
3028
3072
  }
3029
3073
  }
3030
3074
  }
3031
- var collectedEnhancementFactsSchema = import_zod3.z.object({
3032
- peer: import_zod3.z.string().min(1),
3033
- hasContributionsTs: import_zod3.z.boolean(),
3075
+ var collectedEnhancementFactsSchema = import_zod4.z.object({
3076
+ peer: import_zod4.z.string().min(1),
3077
+ hasContributionsTs: import_zod4.z.boolean(),
3034
3078
  contributionPermissions: contributionPermissionsSchema("enhancement contributionPermissions"),
3035
- hasInitializeServerTs: import_zod3.z.boolean(),
3079
+ hasInitializeServerTs: import_zod4.z.boolean(),
3036
3080
  contributionsCollectionErrors: uniqueSortedStringArray(
3037
3081
  "enhancement contributionsCollectionErrors"
3038
3082
  ),
3039
3083
  initializeServerCollectionErrors: uniqueSortedStringArray(
3040
3084
  "enhancement initializeServerCollectionErrors"
3041
3085
  ),
3042
- hasRoutesDir: import_zod3.z.boolean(),
3086
+ hasRoutesDir: import_zod4.z.boolean(),
3043
3087
  routeCollectionErrors: uniqueSortedStringArray("enhancement routeCollectionErrors"),
3044
- locales: import_zod3.z.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
3088
+ locales: import_zod4.z.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
3045
3089
  const names = locales.map((l) => l.locale);
3046
3090
  if (new Set(names).size !== names.length) {
3047
3091
  ctx.addIssue({ code: "custom", message: "enhancement locales must be unique by locale" });
@@ -3056,27 +3100,27 @@ var collectedEnhancementFactsSchema = import_zod3.z.object({
3056
3100
  }),
3057
3101
  e2e: collectedE2eFactsSchema.nullable()
3058
3102
  }).strict();
3059
- var moduleStructureFactsSchema = import_zod3.z.object({
3060
- collected: import_zod3.z.literal(true),
3061
- dirName: import_zod3.z.string().min(1),
3062
- hasIndexTs: import_zod3.z.boolean(),
3063
- hasContributionsTs: import_zod3.z.boolean(),
3103
+ var moduleStructureFactsSchema = import_zod4.z.object({
3104
+ collected: import_zod4.z.literal(true),
3105
+ dirName: import_zod4.z.string().min(1),
3106
+ hasIndexTs: import_zod4.z.boolean(),
3107
+ hasContributionsTs: import_zod4.z.boolean(),
3064
3108
  contributionPermissions: contributionPermissionsSchema("contributionPermissions"),
3065
- hasSlotsTs: import_zod3.z.boolean(),
3109
+ hasSlotsTs: import_zod4.z.boolean(),
3066
3110
  contributionsCollectionErrors: uniqueSortedStringArray("contributionsCollectionErrors"),
3067
3111
  slotsCollectionErrors: uniqueSortedStringArray("slotsCollectionErrors"),
3068
- hasTestsDir: import_zod3.z.boolean(),
3069
- hasDatastoreDir: import_zod3.z.boolean(),
3070
- datastoreFileCount: import_zod3.z.number().int().nonnegative(),
3071
- hasServerIndexTs: import_zod3.z.boolean(),
3072
- hasOtherServerTs: import_zod3.z.boolean(),
3073
- hasE2eDir: import_zod3.z.boolean(),
3074
- hasRoutesDir: import_zod3.z.boolean(),
3112
+ hasTestsDir: import_zod4.z.boolean(),
3113
+ hasDatastoreDir: import_zod4.z.boolean(),
3114
+ datastoreFileCount: import_zod4.z.number().int().nonnegative(),
3115
+ hasServerIndexTs: import_zod4.z.boolean(),
3116
+ hasOtherServerTs: import_zod4.z.boolean(),
3117
+ hasE2eDir: import_zod4.z.boolean(),
3118
+ hasRoutesDir: import_zod4.z.boolean(),
3075
3119
  routeEntries: uniqueSortedStringArray("routeEntries"),
3076
- routePageExports: import_zod3.z.array(
3077
- import_zod3.z.object({
3078
- nextRelativePath: import_zod3.z.string().min(1),
3079
- hasGenerateMetadata: import_zod3.z.boolean()
3120
+ routePageExports: import_zod4.z.array(
3121
+ import_zod4.z.object({
3122
+ nextRelativePath: import_zod4.z.string().min(1),
3123
+ hasGenerateMetadata: import_zod4.z.boolean()
3080
3124
  }).strict()
3081
3125
  ).superRefine((entries, ctx) => {
3082
3126
  const paths = entries.map((e) => e.nextRelativePath);
@@ -3098,7 +3142,7 @@ var moduleStructureFactsSchema = import_zod3.z.object({
3098
3142
  }
3099
3143
  }),
3100
3144
  routeCollectionErrors: uniqueSortedStringArray("routeCollectionErrors"),
3101
- rootLocales: import_zod3.z.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
3145
+ rootLocales: import_zod4.z.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
3102
3146
  const names = locales.map((l) => l.locale);
3103
3147
  if (new Set(names).size !== names.length) {
3104
3148
  ctx.addIssue({ code: "custom", message: "rootLocales must be unique by locale" });
@@ -3112,7 +3156,7 @@ var moduleStructureFactsSchema = import_zod3.z.object({
3112
3156
  }
3113
3157
  }),
3114
3158
  rootE2e: collectedE2eFactsSchema.nullable(),
3115
- enhancements: import_zod3.z.array(collectedEnhancementFactsSchema).superRefine((enhancements, ctx) => {
3159
+ enhancements: import_zod4.z.array(collectedEnhancementFactsSchema).superRefine((enhancements, ctx) => {
3116
3160
  const peers = enhancements.map((e) => e.peer);
3117
3161
  if (new Set(peers).size !== peers.length) {
3118
3162
  ctx.addIssue({ code: "custom", message: "enhancement peers must be unique" });
@@ -3133,10 +3177,10 @@ var moduleStructureFactsSchema = import_zod3.z.object({
3133
3177
  onIssue: (message) => ctx.addIssue({ code: "custom", message })
3134
3178
  });
3135
3179
  });
3136
- var moduleStructureCollectionSchema = import_zod3.z.object({
3180
+ var moduleStructureCollectionSchema = import_zod4.z.object({
3137
3181
  homeLocales: uniqueSortedStringArray("homeLocales"),
3138
- modules: import_zod3.z.array(moduleStructureFactsSchema),
3139
- truncated: import_zod3.z.boolean().optional(),
3182
+ modules: import_zod4.z.array(moduleStructureFactsSchema),
3183
+ truncated: import_zod4.z.boolean().optional(),
3140
3184
  collectionErrors: uniqueSortedStringArray("collectionErrors").optional()
3141
3185
  }).strict().superRefine((collection, ctx) => {
3142
3186
  const dirs = collection.modules.map((m) => m.dirName);
@@ -3153,9 +3197,9 @@ var moduleStructureCollectionSchema = import_zod3.z.object({
3153
3197
  });
3154
3198
 
3155
3199
  // ../../packages/module-contract/src/locale.ts
3156
- var import_zod4 = require("zod");
3200
+ var import_zod5 = require("zod");
3157
3201
  var LOCALE_BASENAME_REGEX = /^[a-z]{2,3}(-[A-Za-z0-9]+)*$/;
3158
- var localeBasenameSchema = import_zod4.z.string().max(35).regex(LOCALE_BASENAME_REGEX, "must be a BCP47-like locale tag (e.g. en, th, en-US)");
3202
+ var localeBasenameSchema = import_zod5.z.string().max(35).regex(LOCALE_BASENAME_REGEX, "must be a BCP47-like locale tag (e.g. en, th, en-US)");
3159
3203
  function isValidLocaleBasename(value) {
3160
3204
  return localeBasenameSchema.safeParse(value).success;
3161
3205
  }
@@ -3558,43 +3602,43 @@ function formatRoutePageExportErrors(nextRelativePath, validation) {
3558
3602
  var import_typescript2 = __toESM(require("typescript"), 1);
3559
3603
 
3560
3604
  // ../../packages/module-contract/src/module-registry.ts
3561
- var import_zod5 = require("zod");
3562
- var projectSlugSchema2 = import_zod5.z.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
3563
- var registryEnhancementSchema = import_zod5.z.object({
3605
+ var import_zod6 = require("zod");
3606
+ var projectSlugSchema2 = import_zod6.z.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
3607
+ var registryEnhancementSchema = import_zod6.z.object({
3564
3608
  peer: moduleNameSchema,
3565
- active: import_zod5.z.boolean()
3609
+ active: import_zod6.z.boolean()
3566
3610
  }).strict();
3567
- var registryModuleSchema = import_zod5.z.object({
3611
+ var registryModuleSchema = import_zod6.z.object({
3568
3612
  name: moduleNameSchema,
3569
3613
  /** Installed version as recorded by the rail (non-empty string). */
3570
- version: import_zod5.z.string().min(1),
3614
+ version: import_zod6.z.string().min(1),
3571
3615
  home: projectSlugSchema2,
3572
3616
  kind: moduleKindSchema,
3573
- mounts: import_zod5.z.array(mountSchema),
3574
- enhancements: import_zod5.z.array(registryEnhancementSchema)
3617
+ mounts: import_zod6.z.array(mountSchema),
3618
+ enhancements: import_zod6.z.array(registryEnhancementSchema)
3575
3619
  }).strict().superRefine((mod, ctx) => {
3576
3620
  for (let i = 0; i < mod.enhancements.length; i += 1) {
3577
3621
  if (mod.enhancements[i].peer === mod.name) {
3578
3622
  ctx.addIssue({
3579
- code: import_zod5.z.ZodIssueCode.custom,
3623
+ code: import_zod6.z.ZodIssueCode.custom,
3580
3624
  message: "enhancement peer must not equal the module's own name",
3581
3625
  path: ["enhancements", i, "peer"]
3582
3626
  });
3583
3627
  }
3584
3628
  }
3585
3629
  });
3586
- var generatedModuleRegistrySchema = import_zod5.z.object({
3587
- registryVersion: import_zod5.z.literal(1),
3630
+ var generatedModuleRegistrySchema = import_zod6.z.object({
3631
+ registryVersion: import_zod6.z.literal(1),
3588
3632
  /** Rail run id, or `"manual"` for fixtures. */
3589
- generatedBy: import_zod5.z.string().min(1),
3590
- modules: import_zod5.z.array(registryModuleSchema)
3633
+ generatedBy: import_zod6.z.string().min(1),
3634
+ modules: import_zod6.z.array(registryModuleSchema)
3591
3635
  }).strict().superRefine((registry, ctx) => {
3592
3636
  const seen = /* @__PURE__ */ new Set();
3593
3637
  for (let i = 0; i < registry.modules.length; i += 1) {
3594
3638
  const name = registry.modules[i].name;
3595
3639
  if (seen.has(name)) {
3596
3640
  ctx.addIssue({
3597
- code: import_zod5.z.ZodIssueCode.custom,
3641
+ code: import_zod6.z.ZodIssueCode.custom,
3598
3642
  message: `duplicate module name "${name}"`,
3599
3643
  path: ["modules", i, "name"]
3600
3644
  });
@@ -3965,169 +4009,6 @@ function analyzeClientSafeEntryImports(sourceText, fileName) {
3965
4009
  return analyzeClientSafeEntryImportsWithTs(import_typescript3.default, sourceText, fileName);
3966
4010
  }
3967
4011
 
3968
- // ../../packages/lib/src/shared/module-composition.ts
3969
- var moduleRefSchema = import_zod6.z.object({
3970
- homeProjectId: import_zod6.z.string().uuid(),
3971
- moduleName: moduleNameSchema
3972
- });
3973
- var creationSourceBlankSchema = import_zod6.z.object({
3974
- type: import_zod6.z.literal("blank")
3975
- });
3976
- var creationSourceBlueprintSchema = import_zod6.z.object({
3977
- type: import_zod6.z.literal("blueprint"),
3978
- /** Internal template/fork project id — keep template naming in identifiers. */
3979
- blueprintProjectId: import_zod6.z.string().uuid(),
3980
- /**
3981
- * `null`/absent means every feature Module. `[]` is refused: the platform
3982
- * serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
3983
- * enablement parser reads back as "all" (`module-enablement.ts`) — the
3984
- * opposite of what an empty selection means.
3985
- */
3986
- enabledModules: import_zod6.z.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
3987
- });
3988
- var creationSourceModulesSchema = import_zod6.z.object({
3989
- type: import_zod6.z.literal("modules"),
3990
- requested: import_zod6.z.array(moduleRefSchema).min(1)
3991
- });
3992
- var creationSourceSchema = import_zod6.z.discriminatedUnion("type", [
3993
- creationSourceBlankSchema,
3994
- creationSourceBlueprintSchema,
3995
- creationSourceModulesSchema
3996
- ]);
3997
- var moduleCompositionStatusSchema = import_zod6.z.enum([
3998
- "pending",
3999
- "installing",
4000
- "ready",
4001
- "partial",
4002
- "failed"
4003
- ]);
4004
- var resolvedModuleSnapshotSchema = moduleRefSchema.extend({
4005
- version: import_zod6.z.string().min(1),
4006
- homeCommitSha: import_zod6.z.string().min(1)
4007
- });
4008
- var moduleInstallHandoffSchema = import_zod6.z.object({
4009
- moduleName: import_zod6.z.string().min(1),
4010
- homeProjectId: import_zod6.z.string().uuid(),
4011
- installedVersion: import_zod6.z.string().min(1),
4012
- baselineSha: import_zod6.z.string().min(1),
4013
- mounts: import_zod6.z.array(
4014
- import_zod6.z.object({
4015
- group: import_zod6.z.string(),
4016
- segment: import_zod6.z.string()
4017
- })
4018
- ),
4019
- integration: import_zod6.z.array(import_zod6.z.string()),
4020
- workflows: import_zod6.z.array(import_zod6.z.string()),
4021
- prunedEnhancements: import_zod6.z.array(import_zod6.z.string()),
4022
- restoredEnhancements: import_zod6.z.array(import_zod6.z.string()).optional(),
4023
- permissions: import_zod6.z.array(
4024
- import_zod6.z.object({
4025
- key: import_zod6.z.string().min(1),
4026
- description: import_zod6.z.string().min(1)
4027
- })
4028
- ).optional()
4029
- });
4030
- var moduleCompositionRunAttemptSchema = import_zod6.z.object({
4031
- module: moduleRefSchema,
4032
- runId: import_zod6.z.string().min(1),
4033
- status: import_zod6.z.string().min(1),
4034
- schemaApplied: import_zod6.z.boolean(),
4035
- error: import_zod6.z.string().optional(),
4036
- /** Prefer full ModuleInstallHandoff; identity fields optional for older rows. */
4037
- handoff: moduleInstallHandoffSchema.partial({ moduleName: true, homeProjectId: true }).optional()
4038
- });
4039
- var initialModuleCompositionSchema = import_zod6.z.object({
4040
- version: import_zod6.z.literal(1),
4041
- status: moduleCompositionStatusSchema,
4042
- requested: import_zod6.z.array(moduleRefSchema).min(1),
4043
- resolved: import_zod6.z.array(resolvedModuleSnapshotSchema),
4044
- installOrder: import_zod6.z.array(moduleRefSchema),
4045
- runs: import_zod6.z.array(moduleCompositionRunAttemptSchema).default([]),
4046
- /**
4047
- * True when any failed/partial attempt applied schema before failing.
4048
- * Never claim transactional rollback across git/schema.
4049
- */
4050
- schemaApplied: import_zod6.z.boolean().default(false),
4051
- /**
4052
- * Present when retry would silently change pinned home SHAs — caller must
4053
- * reconfirm the new plan rather than continue.
4054
- */
4055
- reconfirmationRequired: import_zod6.z.object({
4056
- reason: import_zod6.z.string(),
4057
- previous: import_zod6.z.array(resolvedModuleSnapshotSchema),
4058
- next: import_zod6.z.array(resolvedModuleSnapshotSchema)
4059
- }).optional(),
4060
- error: import_zod6.z.string().optional(),
4061
- /**
4062
- * First-turn system handoff lifecycle. Absent/`pending` means inject when
4063
- * status is ready; `consumed` means a successful agent turn already used it.
4064
- */
4065
- systemHandoffStatus: import_zod6.z.enum(["pending", "consumed"]).optional(),
4066
- /**
4067
- * CAS ownership token for concurrent retry attempts. Only the attempt that
4068
- * currently owns this value may reset or compensate durable composition state.
4069
- */
4070
- retryAttemptId: import_zod6.z.string().min(1).optional(),
4071
- /**
4072
- * When the current `installing` attempt was claimed. A setup run that dies
4073
- * with its host (a killed Vercel instance) leaves the composition `installing`
4074
- * forever, and the creating page's poll only stops on ready/partial/failed —
4075
- * so staleness, not a queue's stall detector, is what settles it. Absent on
4076
- * rows claimed before this field existed; treated as stale.
4077
- */
4078
- attemptStartedAt: import_zod6.z.string().datetime().optional(),
4079
- /** Outside-module files the agent changed during connection work. */
4080
- integrationFiles: import_zod6.z.array(import_zod6.z.string()).optional(),
4081
- verificationSummary: import_zod6.z.string().optional()
4082
- });
4083
- var MODULE_SETUP_ATTEMPT_STALE_MS = 10 * 60 * 1e3;
4084
-
4085
- // ../../packages/lib/src/shared/compose-inputs.ts
4086
- var import_zod7 = require("zod");
4087
- var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
4088
- var composeInputsSchema = import_zod7.z.strictObject({
4089
- connectedStores: import_zod7.z.array(
4090
- import_zod7.z.strictObject({
4091
- storeId: import_zod7.z.string().min(1),
4092
- slug: import_zod7.z.string().min(1),
4093
- // A row with an empty binding key must not fail a deploy: the rail
4094
- // treats falsy as "no binding key", so normalise rather than reject.
4095
- bindingKey: import_zod7.z.string().nullish().transform((value) => value || null),
4096
- accessLevel: import_zod7.z.enum(["read", "write", "admin"]),
4097
- // Defaulted so a file written before the platform emitted store types
4098
- // (database rows only) still parses. The platform starts writing
4099
- // storage rows, with `type` set, once forks run a compose that reads it.
4100
- type: import_zod7.z.enum(["database", "storage"]).default("database")
4101
- })
4102
- ).default([]),
4103
- installs: import_zod7.z.record(
4104
- import_zod7.z.string(),
4105
- import_zod7.z.strictObject({
4106
- installedVersion: import_zod7.z.string().min(1),
4107
- datastoreBindings: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.string()).nullish()
4108
- })
4109
- ).default({})
4110
- });
4111
- var STUB_IGNORE_PATH = "apps/web/src/app/.gitignore";
4112
- var STUB_IGNORE_HEADER = "# Generated by stardeck-compose \u2014 Module-rail stubs are build outputs; do not edit or commit them.";
4113
- function escapeStubIgnorePattern(pattern) {
4114
- const escaped = pattern.replace(/[\\[\]*?]/g, (char) => `\\${char}`);
4115
- return /^[#!]/.test(escaped) ? `\\${escaped}` : escaped;
4116
- }
4117
- function buildStubIgnore(artifactPaths) {
4118
- const prefix = "apps/web/src/app/";
4119
- const entries = artifactPaths.filter((artifact) => artifact.startsWith(prefix)).map((artifact) => escapeStubIgnorePattern(`/${artifact.slice(prefix.length)}`)).sort();
4120
- return [STUB_IGNORE_HEADER, ...entries].join("\n") + "\n";
4121
- }
4122
-
4123
- // ../../packages/lib/src/shared/module-enablement.ts
4124
- function isModuleEnabledByList(raw, name, kindOf) {
4125
- if (!raw) return true;
4126
- const kind = kindOf(name);
4127
- if (kind != null && kind !== "feature") return true;
4128
- return raw.split(",").includes(name);
4129
- }
4130
-
4131
4012
  // ../../packages/lib/src/shared/platform-owned-paths.ts
4132
4013
  var APP_WEB_PREFIX = "apps/web/";
4133
4014
  var MODULE_STUB_MARKER = "@stardeck-module-rail-generated";
@@ -6054,6 +5935,50 @@ function rejectPseudoModuleEntries(entries, parentDir, label) {
6054
5935
  return dirs;
6055
5936
  }
6056
5937
 
5938
+ // ../../packages/lib/src/shared/module-composition.ts
5939
+ var import_zod7 = require("zod");
5940
+ var creationSourceBlankSchema = import_zod7.z.object({
5941
+ type: import_zod7.z.literal("blank")
5942
+ });
5943
+ var creationSourceBlueprintSchema = import_zod7.z.object({
5944
+ type: import_zod7.z.literal("blueprint"),
5945
+ /** Internal template/fork project id — keep template naming in identifiers. */
5946
+ blueprintProjectId: import_zod7.z.string().uuid(),
5947
+ /**
5948
+ * `null`/absent means every feature Module. `[]` is refused: the platform
5949
+ * serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
5950
+ * enablement parser reads back as "all" (`module-enablement.ts`) — the
5951
+ * opposite of what an empty selection means.
5952
+ */
5953
+ enabledModules: import_zod7.z.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
5954
+ });
5955
+ var creationSourceSchema = import_zod7.z.discriminatedUnion("type", [
5956
+ creationSourceBlankSchema,
5957
+ creationSourceBlueprintSchema
5958
+ ]);
5959
+ var moduleInstallHandoffSchema = import_zod7.z.object({
5960
+ moduleName: import_zod7.z.string().min(1),
5961
+ homeProjectId: import_zod7.z.string().uuid(),
5962
+ installedVersion: import_zod7.z.string().min(1),
5963
+ baselineSha: import_zod7.z.string().min(1),
5964
+ mounts: import_zod7.z.array(
5965
+ import_zod7.z.object({
5966
+ group: import_zod7.z.string(),
5967
+ segment: import_zod7.z.string()
5968
+ })
5969
+ ),
5970
+ integration: import_zod7.z.array(import_zod7.z.string()),
5971
+ workflows: import_zod7.z.array(import_zod7.z.string()),
5972
+ prunedEnhancements: import_zod7.z.array(import_zod7.z.string()),
5973
+ restoredEnhancements: import_zod7.z.array(import_zod7.z.string()).optional(),
5974
+ permissions: import_zod7.z.array(
5975
+ import_zod7.z.object({
5976
+ key: import_zod7.z.string().min(1),
5977
+ description: import_zod7.z.string().min(1)
5978
+ })
5979
+ ).optional()
5980
+ });
5981
+
6057
5982
  // ../../packages/lib/src/shared/schema-ops.ts
6058
5983
  var import_zod8 = require("zod");
6059
5984
  var columnSpecSchema = import_zod8.z.object({
@@ -7517,6 +7442,9 @@ async function reconcileCompositionArtifacts(context, options = {}) {
7517
7442
  var HOME_I18N_SUBSTRATE_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/substrate`;
7518
7443
  var HOME_I18N_MESSAGES_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/messages`;
7519
7444
 
7445
+ // src/index.ts
7446
+ var import_typescript6 = __toESM(require("typescript"));
7447
+
7520
7448
  // src/module-boundaries.ts
7521
7449
  var import_node_fs2 = __toESM(require("fs"));
7522
7450
  var import_node_path2 = __toESM(require("path"));
@@ -7786,6 +7714,41 @@ function assertNoAppLayerImporters(cwd, excluded) {
7786
7714
  );
7787
7715
  }
7788
7716
  }
7717
+ var TSCONFIG_PATH = "apps/web/tsconfig.json";
7718
+ var BUILD_TSCONFIG_PATH = "apps/web/tsconfig.build.gen.json";
7719
+ var BUILD_TSCONFIG_HEADER = "// Generated by stardeck-compose \u2014 the tsconfig `next build` type-checks. Do not edit or commit.";
7720
+ function writeBuildTsconfig(cwd, excluded) {
7721
+ const baseFile = import_node_path3.default.join(cwd, TSCONFIG_PATH);
7722
+ if (!import_node_fs3.default.existsSync(import_node_path3.default.join(cwd, MODULES_DIR2)) || !import_node_fs3.default.existsSync(baseFile)) return;
7723
+ const base = import_typescript6.default.readConfigFile(baseFile, import_typescript6.default.sys.readFile);
7724
+ if (base.error) {
7725
+ throw new Error(
7726
+ `[compose] cannot read ${TSCONFIG_PATH}: ${import_typescript6.default.flattenDiagnosticMessageText(base.error.messageText, "\n")}`
7727
+ );
7728
+ }
7729
+ const baseExclude = base.config?.exclude ?? ["node_modules"];
7730
+ const modulesDir = import_node_path3.default.posix.relative("apps/web", MODULES_DIR2);
7731
+ const config = {
7732
+ extends: "./tsconfig.json",
7733
+ exclude: [
7734
+ ...baseExclude,
7735
+ ...excluded.flatMap((name) => [
7736
+ `${modulesDir}/${name}`,
7737
+ `${modulesDir}/*/enhancements/${name}`
7738
+ ])
7739
+ ]
7740
+ };
7741
+ const content = `${BUILD_TSCONFIG_HEADER}
7742
+ ${JSON.stringify(config, null, 2)}
7743
+ `;
7744
+ const file = import_node_path3.default.join(cwd, BUILD_TSCONFIG_PATH);
7745
+ if (!import_node_fs3.default.existsSync(file) || import_node_fs3.default.readFileSync(file, "utf8") !== content) {
7746
+ import_node_fs3.default.writeFileSync(file, content);
7747
+ }
7748
+ console.log(
7749
+ `[compose] ${BUILD_TSCONFIG_PATH} excludes ${excluded.length} Module(s): ${excluded.join(",") || "none"}`
7750
+ );
7751
+ }
7789
7752
  function removeDir(absolute) {
7790
7753
  if (!import_node_fs3.default.existsSync(absolute)) return false;
7791
7754
  import_node_fs3.default.rmSync(absolute, { recursive: true, force: true });
@@ -7833,6 +7796,7 @@ async function compose(options) {
7833
7796
  skipComposeInputs: true
7834
7797
  });
7835
7798
  const gitignoreEntries = options.enabled ? null : writeStubGitignore(options.cwd, result.artifactPaths);
7799
+ writeBuildTsconfig(options.cwd, result.excludedModules);
7836
7800
  let pruned = 0;
7837
7801
  if (options.prune) {
7838
7802
  for (const name of result.excludedModules) {
@@ -7855,6 +7819,7 @@ async function compose(options) {
7855
7819
  }
7856
7820
  // Annotate the CommonJS export names for ESM import in node:
7857
7821
  0 && (module.exports = {
7822
+ BUILD_TSCONFIG_PATH,
7858
7823
  COMPOSE_INPUTS_PATH,
7859
7824
  assertSupportedTypescript,
7860
7825
  compose,