@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/SKILL.md +6 -0
- package/dist/cli.js +99 -134
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +261 -296
- package/dist/index.mjs +260 -296
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2080,11 +2080,54 @@ function shellQuote(value) {
|
|
|
2080
2080
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
2081
2081
|
}
|
|
2082
2082
|
|
|
2083
|
-
// ../../packages/lib/src/shared/
|
|
2084
|
-
import { z
|
|
2083
|
+
// ../../packages/lib/src/shared/compose-inputs.ts
|
|
2084
|
+
import { z } from "zod";
|
|
2085
|
+
var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
|
|
2086
|
+
var composeInputsSchema = z.strictObject({
|
|
2087
|
+
connectedStores: z.array(
|
|
2088
|
+
z.strictObject({
|
|
2089
|
+
storeId: z.string().min(1),
|
|
2090
|
+
slug: z.string().min(1),
|
|
2091
|
+
// A row with an empty binding key must not fail a deploy: the rail
|
|
2092
|
+
// treats falsy as "no binding key", so normalise rather than reject.
|
|
2093
|
+
bindingKey: z.string().nullish().transform((value) => value || null),
|
|
2094
|
+
accessLevel: z.enum(["read", "write", "admin"]),
|
|
2095
|
+
// Defaulted so a file written before the platform emitted store types
|
|
2096
|
+
// (database rows only) still parses. The platform starts writing
|
|
2097
|
+
// storage rows, with `type` set, once forks run a compose that reads it.
|
|
2098
|
+
type: z.enum(["database", "storage"]).default("database")
|
|
2099
|
+
})
|
|
2100
|
+
).default([]),
|
|
2101
|
+
installs: z.record(
|
|
2102
|
+
z.string(),
|
|
2103
|
+
z.strictObject({
|
|
2104
|
+
installedVersion: z.string().min(1),
|
|
2105
|
+
datastoreBindings: z.record(z.string(), z.string()).nullish()
|
|
2106
|
+
})
|
|
2107
|
+
).default({})
|
|
2108
|
+
});
|
|
2109
|
+
var STUB_IGNORE_PATH = "apps/web/src/app/.gitignore";
|
|
2110
|
+
var STUB_IGNORE_HEADER = "# Generated by stardeck-compose \u2014 Module-rail stubs are build outputs; do not edit or commit them.";
|
|
2111
|
+
function escapeStubIgnorePattern(pattern) {
|
|
2112
|
+
const escaped = pattern.replace(/[\\[\]*?]/g, (char) => `\\${char}`);
|
|
2113
|
+
return /^[#!]/.test(escaped) ? `\\${escaped}` : escaped;
|
|
2114
|
+
}
|
|
2115
|
+
function buildStubIgnore(artifactPaths) {
|
|
2116
|
+
const prefix = "apps/web/src/app/";
|
|
2117
|
+
const entries = artifactPaths.filter((artifact) => artifact.startsWith(prefix)).map((artifact) => escapeStubIgnorePattern(`/${artifact.slice(prefix.length)}`)).sort();
|
|
2118
|
+
return [STUB_IGNORE_HEADER, ...entries].join("\n") + "\n";
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
// ../../packages/lib/src/shared/module-enablement.ts
|
|
2122
|
+
function isModuleEnabledByList(raw, name, kindOf) {
|
|
2123
|
+
if (!raw) return true;
|
|
2124
|
+
const kind = kindOf(name);
|
|
2125
|
+
if (kind != null && kind !== "feature") return true;
|
|
2126
|
+
return raw.split(",").includes(name);
|
|
2127
|
+
}
|
|
2085
2128
|
|
|
2086
2129
|
// ../../packages/module-contract/src/module-manifest.ts
|
|
2087
|
-
import { z } from "zod";
|
|
2130
|
+
import { z as z2 } from "zod";
|
|
2088
2131
|
|
|
2089
2132
|
// ../../packages/module-contract/src/slug.ts
|
|
2090
2133
|
function validateSlug(slug) {
|
|
@@ -2119,13 +2162,13 @@ var ROUTE_GROUP_REGEX = /^\([a-z0-9-]+\)$/;
|
|
|
2119
2162
|
var ENDPOINT_STATIC_SEGMENT_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2120
2163
|
var ENDPOINT_PARAM_NAME_REGEX = /^[a-z][a-z0-9_-]*$/;
|
|
2121
2164
|
var ENDPOINT_METHODS = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
|
|
2122
|
-
var moduleNameSchema =
|
|
2165
|
+
var moduleNameSchema = z2.string().max(40).regex(KEBAB_SLUG_REGEX, "must be a kebab-case slug (lowercase letters, digits, hyphens)");
|
|
2123
2166
|
function isValidModuleName(value) {
|
|
2124
2167
|
return moduleNameSchema.safeParse(value).success;
|
|
2125
2168
|
}
|
|
2126
|
-
var projectSlugSchema =
|
|
2127
|
-
var moduleKindSchema =
|
|
2128
|
-
var endpointMethodSchema =
|
|
2169
|
+
var projectSlugSchema = z2.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
|
|
2170
|
+
var moduleKindSchema = z2.enum(["feature", "library", "contract"]);
|
|
2171
|
+
var endpointMethodSchema = z2.enum(ENDPOINT_METHODS);
|
|
2129
2172
|
function endpointPathValidationError(path4) {
|
|
2130
2173
|
if (!path4.startsWith("/api/")) {
|
|
2131
2174
|
return 'must begin with "/api/"';
|
|
@@ -2210,21 +2253,21 @@ function normalizeEndpointPathForCollision(path4) {
|
|
|
2210
2253
|
return segment;
|
|
2211
2254
|
}).join("/");
|
|
2212
2255
|
}
|
|
2213
|
-
var endpointPathSchema =
|
|
2256
|
+
var endpointPathSchema = z2.string().superRefine((path4, ctx) => {
|
|
2214
2257
|
const error = endpointPathValidationError(path4);
|
|
2215
2258
|
if (error != null) {
|
|
2216
|
-
ctx.addIssue({ code:
|
|
2259
|
+
ctx.addIssue({ code: z2.ZodIssueCode.custom, message: error });
|
|
2217
2260
|
}
|
|
2218
2261
|
});
|
|
2219
|
-
var endpointClaimSchema =
|
|
2262
|
+
var endpointClaimSchema = z2.object({
|
|
2220
2263
|
path: endpointPathSchema,
|
|
2221
|
-
methods:
|
|
2264
|
+
methods: z2.array(endpointMethodSchema).min(1, "methods must be non-empty").superRefine((methods, ctx) => {
|
|
2222
2265
|
const seen = /* @__PURE__ */ new Set();
|
|
2223
2266
|
for (let i = 0; i < methods.length; i += 1) {
|
|
2224
2267
|
const method = methods[i];
|
|
2225
2268
|
if (seen.has(method)) {
|
|
2226
2269
|
ctx.addIssue({
|
|
2227
|
-
code:
|
|
2270
|
+
code: z2.ZodIssueCode.custom,
|
|
2228
2271
|
message: `duplicate method "${method}"`,
|
|
2229
2272
|
path: [i]
|
|
2230
2273
|
});
|
|
@@ -2261,14 +2304,14 @@ function mountSegmentValidationError(segment) {
|
|
|
2261
2304
|
}
|
|
2262
2305
|
return null;
|
|
2263
2306
|
}
|
|
2264
|
-
var mountSegmentSchema =
|
|
2307
|
+
var mountSegmentSchema = z2.string().superRefine((segment, ctx) => {
|
|
2265
2308
|
const error = mountSegmentValidationError(segment);
|
|
2266
2309
|
if (error != null) {
|
|
2267
|
-
ctx.addIssue({ code:
|
|
2310
|
+
ctx.addIssue({ code: z2.ZodIssueCode.custom, message: error });
|
|
2268
2311
|
}
|
|
2269
2312
|
});
|
|
2270
|
-
var mountSchema =
|
|
2271
|
-
group:
|
|
2313
|
+
var mountSchema = z2.object({
|
|
2314
|
+
group: z2.string().regex(ROUTE_GROUP_REGEX, 'must be a Next.js route group like "(admin)"'),
|
|
2272
2315
|
segment: mountSegmentSchema
|
|
2273
2316
|
}).strict();
|
|
2274
2317
|
function splitMountSegment(segment) {
|
|
@@ -2281,21 +2324,21 @@ function splitMountSegment(segment) {
|
|
|
2281
2324
|
}
|
|
2282
2325
|
return segment.split("/");
|
|
2283
2326
|
}
|
|
2284
|
-
var tableNameSchema =
|
|
2327
|
+
var tableNameSchema = z2.string().regex(SNAKE_TABLE_REGEX, "must be snake_case");
|
|
2285
2328
|
var NPM_PACKAGE_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
2286
|
-
var npmPackageNameSchema =
|
|
2287
|
-
var descriptionSchema =
|
|
2288
|
-
var crossAppSchema =
|
|
2289
|
-
exposes:
|
|
2290
|
-
consumes:
|
|
2329
|
+
var npmPackageNameSchema = z2.string().max(214).regex(NPM_PACKAGE_NAME_REGEX, "must be a valid npm package name");
|
|
2330
|
+
var descriptionSchema = z2.string().max(200, "must be at most 200 characters").refine((value) => value.trim().length > 0, "must be non-empty after trimming");
|
|
2331
|
+
var crossAppSchema = z2.object({
|
|
2332
|
+
exposes: z2.array(z2.unknown()).max(0, "must be empty until cross-app contracts are defined"),
|
|
2333
|
+
consumes: z2.array(z2.unknown()).max(0, "must be empty until cross-app contracts are defined")
|
|
2291
2334
|
}).strict();
|
|
2292
|
-
var enhancementWorkflowsSchema =
|
|
2293
|
-
var enhancementEndpointsSchema =
|
|
2294
|
-
var datastoreRequirementSchema =
|
|
2335
|
+
var enhancementWorkflowsSchema = z2.record(moduleNameSchema, z2.array(z2.string().min(1))).default({});
|
|
2336
|
+
var enhancementEndpointsSchema = z2.record(moduleNameSchema, z2.array(endpointClaimSchema)).default({});
|
|
2337
|
+
var datastoreRequirementSchema = z2.object({
|
|
2295
2338
|
/** Logical name, module-local, snake_case. Never a physical store key. */
|
|
2296
2339
|
id: tableNameSchema,
|
|
2297
2340
|
/** "app" = this project's app-local store; "org" = an org-level shared store. */
|
|
2298
|
-
scope:
|
|
2341
|
+
scope: z2.enum(["app", "org"]).default("app"),
|
|
2299
2342
|
/**
|
|
2300
2343
|
* Which kind of connected store satisfies this requirement. A "database"
|
|
2301
2344
|
* requirement only ever binds to a database store and a "storage" one
|
|
@@ -2303,34 +2346,34 @@ var datastoreRequirementSchema = z.object({
|
|
|
2303
2346
|
* rail never crosses the two. Defaults to "database", the only kind the
|
|
2304
2347
|
* rail resolved before this field existed.
|
|
2305
2348
|
*/
|
|
2306
|
-
type:
|
|
2349
|
+
type: z2.enum(["database", "storage"]).default("database"),
|
|
2307
2350
|
/** true → install fails when no store resolves; false → binding omitted, module degrades. */
|
|
2308
|
-
required:
|
|
2351
|
+
required: z2.boolean().default(true),
|
|
2309
2352
|
/** Checked against the connected store's accessLevel at install. */
|
|
2310
|
-
access:
|
|
2353
|
+
access: z2.enum(["read", "write", "admin"]).default("write")
|
|
2311
2354
|
}).strict();
|
|
2312
|
-
var permissionClaimSchema =
|
|
2355
|
+
var permissionClaimSchema = z2.object({
|
|
2313
2356
|
/**
|
|
2314
2357
|
* Lowercase resource:action with one colon and no underscores. This grammar
|
|
2315
2358
|
* is deliberately narrower than the platform permission tool's charset.
|
|
2316
2359
|
*/
|
|
2317
|
-
key:
|
|
2360
|
+
key: z2.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)"),
|
|
2318
2361
|
/** Human label for the deployment auth config row. */
|
|
2319
2362
|
description: descriptionSchema
|
|
2320
2363
|
}).strict();
|
|
2321
|
-
var seedBundleSchema =
|
|
2364
|
+
var seedBundleSchema = z2.object({
|
|
2322
2365
|
table: tableNameSchema,
|
|
2323
2366
|
/** Columns forming the ON CONFLICT key — must appear in every row. */
|
|
2324
|
-
conflictTarget:
|
|
2367
|
+
conflictTarget: z2.array(z2.string().min(1)).min(1),
|
|
2325
2368
|
/** Scalar JSON values only (no nested objects/arrays). */
|
|
2326
|
-
rows:
|
|
2369
|
+
rows: z2.array(z2.record(z2.string(), z2.union([z2.string(), z2.number(), z2.boolean(), z2.null()]))).min(1)
|
|
2327
2370
|
}).strict().superRefine((bundle, ctx) => {
|
|
2328
2371
|
const rowKeys = bundle.rows.map((row) => Object.keys(row).sort().join("\0"));
|
|
2329
2372
|
const canonical = rowKeys[0];
|
|
2330
2373
|
for (let i = 1; i < rowKeys.length; i += 1) {
|
|
2331
2374
|
if (rowKeys[i] !== canonical) {
|
|
2332
2375
|
ctx.addIssue({
|
|
2333
|
-
code:
|
|
2376
|
+
code: z2.ZodIssueCode.custom,
|
|
2334
2377
|
message: "all rows in a seed bundle must have identical key sets",
|
|
2335
2378
|
path: ["rows", i]
|
|
2336
2379
|
});
|
|
@@ -2342,7 +2385,7 @@ var seedBundleSchema = z.object({
|
|
|
2342
2385
|
for (const col of bundle.conflictTarget) {
|
|
2343
2386
|
if (!keys.has(col)) {
|
|
2344
2387
|
ctx.addIssue({
|
|
2345
|
-
code:
|
|
2388
|
+
code: z2.ZodIssueCode.custom,
|
|
2346
2389
|
message: `conflictTarget column "${col}" must be present in every row`,
|
|
2347
2390
|
path: ["rows", i]
|
|
2348
2391
|
});
|
|
@@ -2350,35 +2393,35 @@ var seedBundleSchema = z.object({
|
|
|
2350
2393
|
}
|
|
2351
2394
|
}
|
|
2352
2395
|
});
|
|
2353
|
-
var moduleManifestSchema =
|
|
2396
|
+
var moduleManifestSchema = z2.object({
|
|
2354
2397
|
name: moduleNameSchema,
|
|
2355
2398
|
kind: moduleKindSchema,
|
|
2356
2399
|
// Release versions are platform-owned in module_versions. Accept this
|
|
2357
2400
|
// legacy field while existing Module source ages out, but strip it from the
|
|
2358
2401
|
// parsed contract so no runtime can treat module.json as version authority.
|
|
2359
|
-
version:
|
|
2402
|
+
version: z2.unknown().optional(),
|
|
2360
2403
|
home: projectSlugSchema,
|
|
2361
2404
|
/** Machine-checkable purpose line — required, ≤200 code units, non-blank when trimmed. */
|
|
2362
2405
|
description: descriptionSchema,
|
|
2363
|
-
uses:
|
|
2406
|
+
uses: z2.array(moduleNameSchema).default([]),
|
|
2364
2407
|
/**
|
|
2365
2408
|
* Soft peers: this module ships `enhancements/<peer>/` directories that are
|
|
2366
2409
|
* composition-pruned — the installer includes them only when the peer is
|
|
2367
2410
|
* present, so the peer is NOT an install-time requirement. Disjoint from
|
|
2368
2411
|
* `uses`; entries may name modules absent from the composition.
|
|
2369
2412
|
*/
|
|
2370
|
-
enhancements:
|
|
2371
|
-
tables:
|
|
2372
|
-
mounts:
|
|
2373
|
-
integration:
|
|
2374
|
-
workflows:
|
|
2413
|
+
enhancements: z2.array(moduleNameSchema).default([]),
|
|
2414
|
+
tables: z2.array(tableNameSchema).default([]),
|
|
2415
|
+
mounts: z2.array(mountSchema).default([]),
|
|
2416
|
+
integration: z2.array(z2.string()).default([]),
|
|
2417
|
+
workflows: z2.array(z2.string().min(1)).default([]),
|
|
2375
2418
|
/**
|
|
2376
2419
|
* Slice-scoped workflow names keyed by peer. Keys must be ⊆ `enhancements`;
|
|
2377
2420
|
* names must be unique across root `workflows` and every slice list.
|
|
2378
2421
|
*/
|
|
2379
2422
|
enhancementWorkflows: enhancementWorkflowsSchema,
|
|
2380
2423
|
/** Root API endpoint path claims. */
|
|
2381
|
-
endpoints:
|
|
2424
|
+
endpoints: z2.array(endpointClaimSchema).default([]),
|
|
2382
2425
|
/**
|
|
2383
2426
|
* Slice-scoped endpoint claims keyed by peer. Keys must be ⊆ `enhancements`;
|
|
2384
2427
|
* normalized paths must be unique across root and every slice.
|
|
@@ -2394,38 +2437,38 @@ var moduleManifestSchema = z.object({
|
|
|
2394
2437
|
* to a physical connected store and generates module-datastores.gen.ts;
|
|
2395
2438
|
* unlike seeds, this field drives generated output.
|
|
2396
2439
|
*/
|
|
2397
|
-
datastores:
|
|
2440
|
+
datastores: z2.array(datastoreRequirementSchema).optional(),
|
|
2398
2441
|
/**
|
|
2399
2442
|
* Keys this module's guards enforce. Install registers them in deployment
|
|
2400
2443
|
* auth config; registration only — declaring is never granting.
|
|
2401
2444
|
*/
|
|
2402
|
-
permissions:
|
|
2445
|
+
permissions: z2.array(permissionClaimSchema).optional(),
|
|
2403
2446
|
/**
|
|
2404
2447
|
* Optional starter rows for tables this module owns. Replay is
|
|
2405
2448
|
* `INSERT ... ON CONFLICT (conflictTarget) DO NOTHING` — idempotent by
|
|
2406
2449
|
* construction; the rail (not this schema) performs the replay.
|
|
2407
2450
|
*/
|
|
2408
|
-
seeds:
|
|
2451
|
+
seeds: z2.array(seedBundleSchema).optional(),
|
|
2409
2452
|
/** npm packages the source imports beyond the base app. Names only; the rail installs each at the home app's range. */
|
|
2410
|
-
packages:
|
|
2453
|
+
packages: z2.array(npmPackageNameSchema).optional(),
|
|
2411
2454
|
/**
|
|
2412
2455
|
* UI-layer contract. `separable: true` asserts the Module's components/ and
|
|
2413
2456
|
* routes/ hold presentation only — the Blueprint's
|
|
2414
2457
|
* `module-boundaries/ui-layer` lint rule enforces it — so a fork may
|
|
2415
2458
|
* soft-eject them. See docs/module-ui-soft-eject-plan.md.
|
|
2416
2459
|
*/
|
|
2417
|
-
ui:
|
|
2460
|
+
ui: z2.object({ separable: z2.boolean() }).strict().optional()
|
|
2418
2461
|
}).strict().superRefine((manifest, ctx) => {
|
|
2419
2462
|
if (manifest.uses.includes(manifest.name)) {
|
|
2420
2463
|
ctx.addIssue({
|
|
2421
|
-
code:
|
|
2464
|
+
code: z2.ZodIssueCode.custom,
|
|
2422
2465
|
message: "a module cannot list itself in uses",
|
|
2423
2466
|
path: ["uses"]
|
|
2424
2467
|
});
|
|
2425
2468
|
}
|
|
2426
2469
|
if (manifest.enhancements.includes(manifest.name)) {
|
|
2427
2470
|
ctx.addIssue({
|
|
2428
|
-
code:
|
|
2471
|
+
code: z2.ZodIssueCode.custom,
|
|
2429
2472
|
message: "a module cannot list itself in enhancements",
|
|
2430
2473
|
path: ["enhancements"]
|
|
2431
2474
|
});
|
|
@@ -2433,7 +2476,7 @@ var moduleManifestSchema = z.object({
|
|
|
2433
2476
|
const hardAndSoft = manifest.enhancements.filter((peer) => manifest.uses.includes(peer));
|
|
2434
2477
|
if (hardAndSoft.length > 0) {
|
|
2435
2478
|
ctx.addIssue({
|
|
2436
|
-
code:
|
|
2479
|
+
code: z2.ZodIssueCode.custom,
|
|
2437
2480
|
message: `uses and enhancements must be disjoint (a peer is either a hard dep or a soft one): ${hardAndSoft.join(", ")}`,
|
|
2438
2481
|
path: ["enhancements"]
|
|
2439
2482
|
});
|
|
@@ -2442,7 +2485,7 @@ var moduleManifestSchema = z.object({
|
|
|
2442
2485
|
for (const peer of Object.keys(manifest.enhancementWorkflows)) {
|
|
2443
2486
|
if (!enhancementPeers.has(peer)) {
|
|
2444
2487
|
ctx.addIssue({
|
|
2445
|
-
code:
|
|
2488
|
+
code: z2.ZodIssueCode.custom,
|
|
2446
2489
|
message: `enhancementWorkflows key "${peer}" must be listed in enhancements`,
|
|
2447
2490
|
path: ["enhancementWorkflows", peer]
|
|
2448
2491
|
});
|
|
@@ -2451,7 +2494,7 @@ var moduleManifestSchema = z.object({
|
|
|
2451
2494
|
for (const peer of Object.keys(manifest.enhancementEndpoints)) {
|
|
2452
2495
|
if (!enhancementPeers.has(peer)) {
|
|
2453
2496
|
ctx.addIssue({
|
|
2454
|
-
code:
|
|
2497
|
+
code: z2.ZodIssueCode.custom,
|
|
2455
2498
|
message: `enhancementEndpoints key "${peer}" must be listed in enhancements`,
|
|
2456
2499
|
path: ["enhancementEndpoints", peer]
|
|
2457
2500
|
});
|
|
@@ -2462,7 +2505,7 @@ var moduleManifestSchema = z.object({
|
|
|
2462
2505
|
const existing = seenWorkflows.get(name);
|
|
2463
2506
|
if (existing != null) {
|
|
2464
2507
|
ctx.addIssue({
|
|
2465
|
-
code:
|
|
2508
|
+
code: z2.ZodIssueCode.custom,
|
|
2466
2509
|
message: `duplicate workflow name "${name}" (also at ${existing})`,
|
|
2467
2510
|
path: path4
|
|
2468
2511
|
});
|
|
@@ -2489,7 +2532,7 @@ var moduleManifestSchema = z.object({
|
|
|
2489
2532
|
const existing = seenEndpointKeys.get(key);
|
|
2490
2533
|
if (existing != null) {
|
|
2491
2534
|
ctx.addIssue({
|
|
2492
|
-
code:
|
|
2535
|
+
code: z2.ZodIssueCode.custom,
|
|
2493
2536
|
message: `duplicate normalized endpoint path "${key}" (also at ${existing})`,
|
|
2494
2537
|
path: path4
|
|
2495
2538
|
});
|
|
@@ -2511,7 +2554,7 @@ var moduleManifestSchema = z.object({
|
|
|
2511
2554
|
const id = manifest.datastores[i].id;
|
|
2512
2555
|
if (seenDatastoreIds.has(id)) {
|
|
2513
2556
|
ctx.addIssue({
|
|
2514
|
-
code:
|
|
2557
|
+
code: z2.ZodIssueCode.custom,
|
|
2515
2558
|
message: `duplicate datastore id "${id}"`,
|
|
2516
2559
|
path: ["datastores", i, "id"]
|
|
2517
2560
|
});
|
|
@@ -2526,7 +2569,7 @@ var moduleManifestSchema = z.object({
|
|
|
2526
2569
|
const key = manifest.permissions[i].key;
|
|
2527
2570
|
if (seenPermissionKeys.has(key)) {
|
|
2528
2571
|
ctx.addIssue({
|
|
2529
|
-
code:
|
|
2572
|
+
code: z2.ZodIssueCode.custom,
|
|
2530
2573
|
message: `duplicate permission key "${key}"`,
|
|
2531
2574
|
path: ["permissions", i, "key"]
|
|
2532
2575
|
});
|
|
@@ -2538,35 +2581,35 @@ var moduleManifestSchema = z.object({
|
|
|
2538
2581
|
if (manifest.kind === "library") {
|
|
2539
2582
|
if (manifest.tables.length > 0) {
|
|
2540
2583
|
ctx.addIssue({
|
|
2541
|
-
code:
|
|
2584
|
+
code: z2.ZodIssueCode.custom,
|
|
2542
2585
|
message: "library modules must not declare tables",
|
|
2543
2586
|
path: ["tables"]
|
|
2544
2587
|
});
|
|
2545
2588
|
}
|
|
2546
2589
|
if (manifest.mounts.length > 0) {
|
|
2547
2590
|
ctx.addIssue({
|
|
2548
|
-
code:
|
|
2591
|
+
code: z2.ZodIssueCode.custom,
|
|
2549
2592
|
message: "library modules must not declare mounts",
|
|
2550
2593
|
path: ["mounts"]
|
|
2551
2594
|
});
|
|
2552
2595
|
}
|
|
2553
2596
|
if (manifest.seeds != null && manifest.seeds.length > 0) {
|
|
2554
2597
|
ctx.addIssue({
|
|
2555
|
-
code:
|
|
2598
|
+
code: z2.ZodIssueCode.custom,
|
|
2556
2599
|
message: "library modules must not declare seeds",
|
|
2557
2600
|
path: ["seeds"]
|
|
2558
2601
|
});
|
|
2559
2602
|
}
|
|
2560
2603
|
if (manifest.datastores != null && manifest.datastores.length > 0) {
|
|
2561
2604
|
ctx.addIssue({
|
|
2562
|
-
code:
|
|
2605
|
+
code: z2.ZodIssueCode.custom,
|
|
2563
2606
|
message: "library modules must not declare datastores",
|
|
2564
2607
|
path: ["datastores"]
|
|
2565
2608
|
});
|
|
2566
2609
|
}
|
|
2567
2610
|
if (manifest.permissions != null && manifest.permissions.length > 0) {
|
|
2568
2611
|
ctx.addIssue({
|
|
2569
|
-
code:
|
|
2612
|
+
code: z2.ZodIssueCode.custom,
|
|
2570
2613
|
message: "library modules must not declare permissions",
|
|
2571
2614
|
path: ["permissions"]
|
|
2572
2615
|
});
|
|
@@ -2574,7 +2617,7 @@ var moduleManifestSchema = z.object({
|
|
|
2574
2617
|
}
|
|
2575
2618
|
if (manifest.kind === "contract" && manifest.mounts.length > 0) {
|
|
2576
2619
|
ctx.addIssue({
|
|
2577
|
-
code:
|
|
2620
|
+
code: z2.ZodIssueCode.custom,
|
|
2578
2621
|
message: "contract modules must not declare mounts",
|
|
2579
2622
|
path: ["mounts"]
|
|
2580
2623
|
});
|
|
@@ -2585,7 +2628,7 @@ var moduleManifestSchema = z.object({
|
|
|
2585
2628
|
const bundle = manifest.seeds[i];
|
|
2586
2629
|
if (!ownedTables.has(bundle.table)) {
|
|
2587
2630
|
ctx.addIssue({
|
|
2588
|
-
code:
|
|
2631
|
+
code: z2.ZodIssueCode.custom,
|
|
2589
2632
|
message: `seeds may only target tables listed in tables (got "${bundle.table}")`,
|
|
2590
2633
|
path: ["seeds", i, "table"]
|
|
2591
2634
|
});
|
|
@@ -2636,10 +2679,10 @@ var MANDATORY_MODULE_CHECK_DESCRIPTORS = Object.freeze([
|
|
|
2636
2679
|
]);
|
|
2637
2680
|
|
|
2638
2681
|
// ../../packages/module-contract/src/module-structure.ts
|
|
2639
|
-
import { z as
|
|
2682
|
+
import { z as z4 } from "zod";
|
|
2640
2683
|
|
|
2641
2684
|
// ../../packages/module-contract/src/module-e2e-manifest.ts
|
|
2642
|
-
import { z as
|
|
2685
|
+
import { z as z3 } from "zod";
|
|
2643
2686
|
function e2eSpecFileValidationError(file) {
|
|
2644
2687
|
if (file.length === 0) {
|
|
2645
2688
|
return "must be a non-empty relative path ending in .spec.ts";
|
|
@@ -2667,22 +2710,22 @@ function e2eSpecFileValidationError(file) {
|
|
|
2667
2710
|
}
|
|
2668
2711
|
return null;
|
|
2669
2712
|
}
|
|
2670
|
-
var e2eSpecFileSchema =
|
|
2713
|
+
var e2eSpecFileSchema = z3.string().superRefine((file, ctx) => {
|
|
2671
2714
|
const error = e2eSpecFileValidationError(file);
|
|
2672
2715
|
if (error != null) {
|
|
2673
|
-
ctx.addIssue({ code:
|
|
2716
|
+
ctx.addIssue({ code: z3.ZodIssueCode.custom, message: error });
|
|
2674
2717
|
}
|
|
2675
2718
|
});
|
|
2676
|
-
var e2eSpecSchema =
|
|
2719
|
+
var e2eSpecSchema = z3.object({
|
|
2677
2720
|
file: e2eSpecFileSchema,
|
|
2678
|
-
requires:
|
|
2721
|
+
requires: z3.array(moduleNameSchema).min(1, "requires must be non-empty")
|
|
2679
2722
|
}).strict().superRefine((spec, ctx) => {
|
|
2680
2723
|
const seen = /* @__PURE__ */ new Set();
|
|
2681
2724
|
for (let i = 0; i < spec.requires.length; i += 1) {
|
|
2682
2725
|
const name = spec.requires[i];
|
|
2683
2726
|
if (seen.has(name)) {
|
|
2684
2727
|
ctx.addIssue({
|
|
2685
|
-
code:
|
|
2728
|
+
code: z3.ZodIssueCode.custom,
|
|
2686
2729
|
message: `duplicate requirement "${name}"`,
|
|
2687
2730
|
path: ["requires", i]
|
|
2688
2731
|
});
|
|
@@ -2691,15 +2734,15 @@ var e2eSpecSchema = z2.object({
|
|
|
2691
2734
|
}
|
|
2692
2735
|
}
|
|
2693
2736
|
});
|
|
2694
|
-
var moduleE2eManifestSchema =
|
|
2695
|
-
specs:
|
|
2737
|
+
var moduleE2eManifestSchema = z3.object({
|
|
2738
|
+
specs: z3.array(e2eSpecSchema).min(1, "specs must contain at least one entry")
|
|
2696
2739
|
}).strict().superRefine((manifest, ctx) => {
|
|
2697
2740
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
2698
2741
|
for (let i = 0; i < manifest.specs.length; i += 1) {
|
|
2699
2742
|
const file = manifest.specs[i].file;
|
|
2700
2743
|
if (seenFiles.has(file)) {
|
|
2701
2744
|
ctx.addIssue({
|
|
2702
|
-
code:
|
|
2745
|
+
code: z3.ZodIssueCode.custom,
|
|
2703
2746
|
message: `duplicate file "${file}"`,
|
|
2704
2747
|
path: ["specs", i, "file"]
|
|
2705
2748
|
});
|
|
@@ -2941,7 +2984,7 @@ function compareCodeUnit(a, b) {
|
|
|
2941
2984
|
// ../../packages/module-contract/src/module-structure.ts
|
|
2942
2985
|
var MODULE_STRUCTURE_JSON_BYTE_CAP = 64 * 1024;
|
|
2943
2986
|
function uniqueSortedStringArray(label) {
|
|
2944
|
-
return
|
|
2987
|
+
return z4.array(z4.string()).superRefine((arr, ctx) => {
|
|
2945
2988
|
if (new Set(arr).size !== arr.length) {
|
|
2946
2989
|
ctx.addIssue({ code: "custom", message: `${label} must be unique` });
|
|
2947
2990
|
return;
|
|
@@ -2957,10 +3000,10 @@ function uniqueSortedStringArray(label) {
|
|
|
2957
3000
|
});
|
|
2958
3001
|
}
|
|
2959
3002
|
function contributionPermissionsSchema(label) {
|
|
2960
|
-
return
|
|
2961
|
-
|
|
2962
|
-
contributionId:
|
|
2963
|
-
permission:
|
|
3003
|
+
return z4.array(
|
|
3004
|
+
z4.object({
|
|
3005
|
+
contributionId: z4.string().min(1),
|
|
3006
|
+
permission: z4.string().min(1)
|
|
2964
3007
|
}).strict()
|
|
2965
3008
|
).superRefine((entries, ctx) => {
|
|
2966
3009
|
const keys = entries.map((entry) => `${entry.contributionId}\0${entry.permission}`);
|
|
@@ -2978,17 +3021,17 @@ function contributionPermissionsSchema(label) {
|
|
|
2978
3021
|
}
|
|
2979
3022
|
}).optional();
|
|
2980
3023
|
}
|
|
2981
|
-
var collectedFilePayloadSchema =
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3024
|
+
var collectedFilePayloadSchema = z4.discriminatedUnion("status", [
|
|
3025
|
+
z4.object({ status: z4.literal("ok"), text: z4.string() }).strict(),
|
|
3026
|
+
z4.object({ status: z4.literal("missing") }).strict(),
|
|
3027
|
+
z4.object({ status: z4.literal("too-large") }).strict(),
|
|
3028
|
+
z4.object({ status: z4.literal("unreadable") }).strict()
|
|
2986
3029
|
]);
|
|
2987
|
-
var collectedLocaleFileSchema =
|
|
2988
|
-
locale:
|
|
3030
|
+
var collectedLocaleFileSchema = z4.object({
|
|
3031
|
+
locale: z4.string().min(1),
|
|
2989
3032
|
payload: collectedFilePayloadSchema
|
|
2990
3033
|
}).strict();
|
|
2991
|
-
var collectedE2eFactsSchema =
|
|
3034
|
+
var collectedE2eFactsSchema = z4.object({
|
|
2992
3035
|
manifest: collectedFilePayloadSchema,
|
|
2993
3036
|
specFiles: uniqueSortedStringArray("specFiles"),
|
|
2994
3037
|
escapingSymlinks: uniqueSortedStringArray("escapingSymlinks")
|
|
@@ -3010,20 +3053,20 @@ function validateRouteExportEvidenceCongruence(input) {
|
|
|
3010
3053
|
}
|
|
3011
3054
|
}
|
|
3012
3055
|
}
|
|
3013
|
-
var collectedEnhancementFactsSchema =
|
|
3014
|
-
peer:
|
|
3015
|
-
hasContributionsTs:
|
|
3056
|
+
var collectedEnhancementFactsSchema = z4.object({
|
|
3057
|
+
peer: z4.string().min(1),
|
|
3058
|
+
hasContributionsTs: z4.boolean(),
|
|
3016
3059
|
contributionPermissions: contributionPermissionsSchema("enhancement contributionPermissions"),
|
|
3017
|
-
hasInitializeServerTs:
|
|
3060
|
+
hasInitializeServerTs: z4.boolean(),
|
|
3018
3061
|
contributionsCollectionErrors: uniqueSortedStringArray(
|
|
3019
3062
|
"enhancement contributionsCollectionErrors"
|
|
3020
3063
|
),
|
|
3021
3064
|
initializeServerCollectionErrors: uniqueSortedStringArray(
|
|
3022
3065
|
"enhancement initializeServerCollectionErrors"
|
|
3023
3066
|
),
|
|
3024
|
-
hasRoutesDir:
|
|
3067
|
+
hasRoutesDir: z4.boolean(),
|
|
3025
3068
|
routeCollectionErrors: uniqueSortedStringArray("enhancement routeCollectionErrors"),
|
|
3026
|
-
locales:
|
|
3069
|
+
locales: z4.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
|
|
3027
3070
|
const names = locales.map((l) => l.locale);
|
|
3028
3071
|
if (new Set(names).size !== names.length) {
|
|
3029
3072
|
ctx.addIssue({ code: "custom", message: "enhancement locales must be unique by locale" });
|
|
@@ -3038,27 +3081,27 @@ var collectedEnhancementFactsSchema = z3.object({
|
|
|
3038
3081
|
}),
|
|
3039
3082
|
e2e: collectedE2eFactsSchema.nullable()
|
|
3040
3083
|
}).strict();
|
|
3041
|
-
var moduleStructureFactsSchema =
|
|
3042
|
-
collected:
|
|
3043
|
-
dirName:
|
|
3044
|
-
hasIndexTs:
|
|
3045
|
-
hasContributionsTs:
|
|
3084
|
+
var moduleStructureFactsSchema = z4.object({
|
|
3085
|
+
collected: z4.literal(true),
|
|
3086
|
+
dirName: z4.string().min(1),
|
|
3087
|
+
hasIndexTs: z4.boolean(),
|
|
3088
|
+
hasContributionsTs: z4.boolean(),
|
|
3046
3089
|
contributionPermissions: contributionPermissionsSchema("contributionPermissions"),
|
|
3047
|
-
hasSlotsTs:
|
|
3090
|
+
hasSlotsTs: z4.boolean(),
|
|
3048
3091
|
contributionsCollectionErrors: uniqueSortedStringArray("contributionsCollectionErrors"),
|
|
3049
3092
|
slotsCollectionErrors: uniqueSortedStringArray("slotsCollectionErrors"),
|
|
3050
|
-
hasTestsDir:
|
|
3051
|
-
hasDatastoreDir:
|
|
3052
|
-
datastoreFileCount:
|
|
3053
|
-
hasServerIndexTs:
|
|
3054
|
-
hasOtherServerTs:
|
|
3055
|
-
hasE2eDir:
|
|
3056
|
-
hasRoutesDir:
|
|
3093
|
+
hasTestsDir: z4.boolean(),
|
|
3094
|
+
hasDatastoreDir: z4.boolean(),
|
|
3095
|
+
datastoreFileCount: z4.number().int().nonnegative(),
|
|
3096
|
+
hasServerIndexTs: z4.boolean(),
|
|
3097
|
+
hasOtherServerTs: z4.boolean(),
|
|
3098
|
+
hasE2eDir: z4.boolean(),
|
|
3099
|
+
hasRoutesDir: z4.boolean(),
|
|
3057
3100
|
routeEntries: uniqueSortedStringArray("routeEntries"),
|
|
3058
|
-
routePageExports:
|
|
3059
|
-
|
|
3060
|
-
nextRelativePath:
|
|
3061
|
-
hasGenerateMetadata:
|
|
3101
|
+
routePageExports: z4.array(
|
|
3102
|
+
z4.object({
|
|
3103
|
+
nextRelativePath: z4.string().min(1),
|
|
3104
|
+
hasGenerateMetadata: z4.boolean()
|
|
3062
3105
|
}).strict()
|
|
3063
3106
|
).superRefine((entries, ctx) => {
|
|
3064
3107
|
const paths = entries.map((e) => e.nextRelativePath);
|
|
@@ -3080,7 +3123,7 @@ var moduleStructureFactsSchema = z3.object({
|
|
|
3080
3123
|
}
|
|
3081
3124
|
}),
|
|
3082
3125
|
routeCollectionErrors: uniqueSortedStringArray("routeCollectionErrors"),
|
|
3083
|
-
rootLocales:
|
|
3126
|
+
rootLocales: z4.array(collectedLocaleFileSchema).superRefine((locales, ctx) => {
|
|
3084
3127
|
const names = locales.map((l) => l.locale);
|
|
3085
3128
|
if (new Set(names).size !== names.length) {
|
|
3086
3129
|
ctx.addIssue({ code: "custom", message: "rootLocales must be unique by locale" });
|
|
@@ -3094,7 +3137,7 @@ var moduleStructureFactsSchema = z3.object({
|
|
|
3094
3137
|
}
|
|
3095
3138
|
}),
|
|
3096
3139
|
rootE2e: collectedE2eFactsSchema.nullable(),
|
|
3097
|
-
enhancements:
|
|
3140
|
+
enhancements: z4.array(collectedEnhancementFactsSchema).superRefine((enhancements, ctx) => {
|
|
3098
3141
|
const peers = enhancements.map((e) => e.peer);
|
|
3099
3142
|
if (new Set(peers).size !== peers.length) {
|
|
3100
3143
|
ctx.addIssue({ code: "custom", message: "enhancement peers must be unique" });
|
|
@@ -3115,10 +3158,10 @@ var moduleStructureFactsSchema = z3.object({
|
|
|
3115
3158
|
onIssue: (message) => ctx.addIssue({ code: "custom", message })
|
|
3116
3159
|
});
|
|
3117
3160
|
});
|
|
3118
|
-
var moduleStructureCollectionSchema =
|
|
3161
|
+
var moduleStructureCollectionSchema = z4.object({
|
|
3119
3162
|
homeLocales: uniqueSortedStringArray("homeLocales"),
|
|
3120
|
-
modules:
|
|
3121
|
-
truncated:
|
|
3163
|
+
modules: z4.array(moduleStructureFactsSchema),
|
|
3164
|
+
truncated: z4.boolean().optional(),
|
|
3122
3165
|
collectionErrors: uniqueSortedStringArray("collectionErrors").optional()
|
|
3123
3166
|
}).strict().superRefine((collection, ctx) => {
|
|
3124
3167
|
const dirs = collection.modules.map((m) => m.dirName);
|
|
@@ -3135,9 +3178,9 @@ var moduleStructureCollectionSchema = z3.object({
|
|
|
3135
3178
|
});
|
|
3136
3179
|
|
|
3137
3180
|
// ../../packages/module-contract/src/locale.ts
|
|
3138
|
-
import { z as
|
|
3181
|
+
import { z as z5 } from "zod";
|
|
3139
3182
|
var LOCALE_BASENAME_REGEX = /^[a-z]{2,3}(-[A-Za-z0-9]+)*$/;
|
|
3140
|
-
var localeBasenameSchema =
|
|
3183
|
+
var localeBasenameSchema = z5.string().max(35).regex(LOCALE_BASENAME_REGEX, "must be a BCP47-like locale tag (e.g. en, th, en-US)");
|
|
3141
3184
|
function isValidLocaleBasename(value) {
|
|
3142
3185
|
return localeBasenameSchema.safeParse(value).success;
|
|
3143
3186
|
}
|
|
@@ -3540,43 +3583,43 @@ function formatRoutePageExportErrors(nextRelativePath, validation) {
|
|
|
3540
3583
|
import ts2 from "typescript";
|
|
3541
3584
|
|
|
3542
3585
|
// ../../packages/module-contract/src/module-registry.ts
|
|
3543
|
-
import { z as
|
|
3544
|
-
var projectSlugSchema2 =
|
|
3545
|
-
var registryEnhancementSchema =
|
|
3586
|
+
import { z as z6 } from "zod";
|
|
3587
|
+
var projectSlugSchema2 = z6.string().refine((value) => validateSlug(value).valid, "must be a valid project slug");
|
|
3588
|
+
var registryEnhancementSchema = z6.object({
|
|
3546
3589
|
peer: moduleNameSchema,
|
|
3547
|
-
active:
|
|
3590
|
+
active: z6.boolean()
|
|
3548
3591
|
}).strict();
|
|
3549
|
-
var registryModuleSchema =
|
|
3592
|
+
var registryModuleSchema = z6.object({
|
|
3550
3593
|
name: moduleNameSchema,
|
|
3551
3594
|
/** Installed version as recorded by the rail (non-empty string). */
|
|
3552
|
-
version:
|
|
3595
|
+
version: z6.string().min(1),
|
|
3553
3596
|
home: projectSlugSchema2,
|
|
3554
3597
|
kind: moduleKindSchema,
|
|
3555
|
-
mounts:
|
|
3556
|
-
enhancements:
|
|
3598
|
+
mounts: z6.array(mountSchema),
|
|
3599
|
+
enhancements: z6.array(registryEnhancementSchema)
|
|
3557
3600
|
}).strict().superRefine((mod, ctx) => {
|
|
3558
3601
|
for (let i = 0; i < mod.enhancements.length; i += 1) {
|
|
3559
3602
|
if (mod.enhancements[i].peer === mod.name) {
|
|
3560
3603
|
ctx.addIssue({
|
|
3561
|
-
code:
|
|
3604
|
+
code: z6.ZodIssueCode.custom,
|
|
3562
3605
|
message: "enhancement peer must not equal the module's own name",
|
|
3563
3606
|
path: ["enhancements", i, "peer"]
|
|
3564
3607
|
});
|
|
3565
3608
|
}
|
|
3566
3609
|
}
|
|
3567
3610
|
});
|
|
3568
|
-
var generatedModuleRegistrySchema =
|
|
3569
|
-
registryVersion:
|
|
3611
|
+
var generatedModuleRegistrySchema = z6.object({
|
|
3612
|
+
registryVersion: z6.literal(1),
|
|
3570
3613
|
/** Rail run id, or `"manual"` for fixtures. */
|
|
3571
|
-
generatedBy:
|
|
3572
|
-
modules:
|
|
3614
|
+
generatedBy: z6.string().min(1),
|
|
3615
|
+
modules: z6.array(registryModuleSchema)
|
|
3573
3616
|
}).strict().superRefine((registry, ctx) => {
|
|
3574
3617
|
const seen = /* @__PURE__ */ new Set();
|
|
3575
3618
|
for (let i = 0; i < registry.modules.length; i += 1) {
|
|
3576
3619
|
const name = registry.modules[i].name;
|
|
3577
3620
|
if (seen.has(name)) {
|
|
3578
3621
|
ctx.addIssue({
|
|
3579
|
-
code:
|
|
3622
|
+
code: z6.ZodIssueCode.custom,
|
|
3580
3623
|
message: `duplicate module name "${name}"`,
|
|
3581
3624
|
path: ["modules", i, "name"]
|
|
3582
3625
|
});
|
|
@@ -3947,169 +3990,6 @@ function analyzeClientSafeEntryImports(sourceText, fileName) {
|
|
|
3947
3990
|
return analyzeClientSafeEntryImportsWithTs(ts3, sourceText, fileName);
|
|
3948
3991
|
}
|
|
3949
3992
|
|
|
3950
|
-
// ../../packages/lib/src/shared/module-composition.ts
|
|
3951
|
-
var moduleRefSchema = z6.object({
|
|
3952
|
-
homeProjectId: z6.string().uuid(),
|
|
3953
|
-
moduleName: moduleNameSchema
|
|
3954
|
-
});
|
|
3955
|
-
var creationSourceBlankSchema = z6.object({
|
|
3956
|
-
type: z6.literal("blank")
|
|
3957
|
-
});
|
|
3958
|
-
var creationSourceBlueprintSchema = z6.object({
|
|
3959
|
-
type: z6.literal("blueprint"),
|
|
3960
|
-
/** Internal template/fork project id — keep template naming in identifiers. */
|
|
3961
|
-
blueprintProjectId: z6.string().uuid(),
|
|
3962
|
-
/**
|
|
3963
|
-
* `null`/absent means every feature Module. `[]` is refused: the platform
|
|
3964
|
-
* serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
|
|
3965
|
-
* enablement parser reads back as "all" (`module-enablement.ts`) — the
|
|
3966
|
-
* opposite of what an empty selection means.
|
|
3967
|
-
*/
|
|
3968
|
-
enabledModules: z6.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
|
|
3969
|
-
});
|
|
3970
|
-
var creationSourceModulesSchema = z6.object({
|
|
3971
|
-
type: z6.literal("modules"),
|
|
3972
|
-
requested: z6.array(moduleRefSchema).min(1)
|
|
3973
|
-
});
|
|
3974
|
-
var creationSourceSchema = z6.discriminatedUnion("type", [
|
|
3975
|
-
creationSourceBlankSchema,
|
|
3976
|
-
creationSourceBlueprintSchema,
|
|
3977
|
-
creationSourceModulesSchema
|
|
3978
|
-
]);
|
|
3979
|
-
var moduleCompositionStatusSchema = z6.enum([
|
|
3980
|
-
"pending",
|
|
3981
|
-
"installing",
|
|
3982
|
-
"ready",
|
|
3983
|
-
"partial",
|
|
3984
|
-
"failed"
|
|
3985
|
-
]);
|
|
3986
|
-
var resolvedModuleSnapshotSchema = moduleRefSchema.extend({
|
|
3987
|
-
version: z6.string().min(1),
|
|
3988
|
-
homeCommitSha: z6.string().min(1)
|
|
3989
|
-
});
|
|
3990
|
-
var moduleInstallHandoffSchema = z6.object({
|
|
3991
|
-
moduleName: z6.string().min(1),
|
|
3992
|
-
homeProjectId: z6.string().uuid(),
|
|
3993
|
-
installedVersion: z6.string().min(1),
|
|
3994
|
-
baselineSha: z6.string().min(1),
|
|
3995
|
-
mounts: z6.array(
|
|
3996
|
-
z6.object({
|
|
3997
|
-
group: z6.string(),
|
|
3998
|
-
segment: z6.string()
|
|
3999
|
-
})
|
|
4000
|
-
),
|
|
4001
|
-
integration: z6.array(z6.string()),
|
|
4002
|
-
workflows: z6.array(z6.string()),
|
|
4003
|
-
prunedEnhancements: z6.array(z6.string()),
|
|
4004
|
-
restoredEnhancements: z6.array(z6.string()).optional(),
|
|
4005
|
-
permissions: z6.array(
|
|
4006
|
-
z6.object({
|
|
4007
|
-
key: z6.string().min(1),
|
|
4008
|
-
description: z6.string().min(1)
|
|
4009
|
-
})
|
|
4010
|
-
).optional()
|
|
4011
|
-
});
|
|
4012
|
-
var moduleCompositionRunAttemptSchema = z6.object({
|
|
4013
|
-
module: moduleRefSchema,
|
|
4014
|
-
runId: z6.string().min(1),
|
|
4015
|
-
status: z6.string().min(1),
|
|
4016
|
-
schemaApplied: z6.boolean(),
|
|
4017
|
-
error: z6.string().optional(),
|
|
4018
|
-
/** Prefer full ModuleInstallHandoff; identity fields optional for older rows. */
|
|
4019
|
-
handoff: moduleInstallHandoffSchema.partial({ moduleName: true, homeProjectId: true }).optional()
|
|
4020
|
-
});
|
|
4021
|
-
var initialModuleCompositionSchema = z6.object({
|
|
4022
|
-
version: z6.literal(1),
|
|
4023
|
-
status: moduleCompositionStatusSchema,
|
|
4024
|
-
requested: z6.array(moduleRefSchema).min(1),
|
|
4025
|
-
resolved: z6.array(resolvedModuleSnapshotSchema),
|
|
4026
|
-
installOrder: z6.array(moduleRefSchema),
|
|
4027
|
-
runs: z6.array(moduleCompositionRunAttemptSchema).default([]),
|
|
4028
|
-
/**
|
|
4029
|
-
* True when any failed/partial attempt applied schema before failing.
|
|
4030
|
-
* Never claim transactional rollback across git/schema.
|
|
4031
|
-
*/
|
|
4032
|
-
schemaApplied: z6.boolean().default(false),
|
|
4033
|
-
/**
|
|
4034
|
-
* Present when retry would silently change pinned home SHAs — caller must
|
|
4035
|
-
* reconfirm the new plan rather than continue.
|
|
4036
|
-
*/
|
|
4037
|
-
reconfirmationRequired: z6.object({
|
|
4038
|
-
reason: z6.string(),
|
|
4039
|
-
previous: z6.array(resolvedModuleSnapshotSchema),
|
|
4040
|
-
next: z6.array(resolvedModuleSnapshotSchema)
|
|
4041
|
-
}).optional(),
|
|
4042
|
-
error: z6.string().optional(),
|
|
4043
|
-
/**
|
|
4044
|
-
* First-turn system handoff lifecycle. Absent/`pending` means inject when
|
|
4045
|
-
* status is ready; `consumed` means a successful agent turn already used it.
|
|
4046
|
-
*/
|
|
4047
|
-
systemHandoffStatus: z6.enum(["pending", "consumed"]).optional(),
|
|
4048
|
-
/**
|
|
4049
|
-
* CAS ownership token for concurrent retry attempts. Only the attempt that
|
|
4050
|
-
* currently owns this value may reset or compensate durable composition state.
|
|
4051
|
-
*/
|
|
4052
|
-
retryAttemptId: z6.string().min(1).optional(),
|
|
4053
|
-
/**
|
|
4054
|
-
* When the current `installing` attempt was claimed. A setup run that dies
|
|
4055
|
-
* with its host (a killed Vercel instance) leaves the composition `installing`
|
|
4056
|
-
* forever, and the creating page's poll only stops on ready/partial/failed —
|
|
4057
|
-
* so staleness, not a queue's stall detector, is what settles it. Absent on
|
|
4058
|
-
* rows claimed before this field existed; treated as stale.
|
|
4059
|
-
*/
|
|
4060
|
-
attemptStartedAt: z6.string().datetime().optional(),
|
|
4061
|
-
/** Outside-module files the agent changed during connection work. */
|
|
4062
|
-
integrationFiles: z6.array(z6.string()).optional(),
|
|
4063
|
-
verificationSummary: z6.string().optional()
|
|
4064
|
-
});
|
|
4065
|
-
var MODULE_SETUP_ATTEMPT_STALE_MS = 10 * 60 * 1e3;
|
|
4066
|
-
|
|
4067
|
-
// ../../packages/lib/src/shared/compose-inputs.ts
|
|
4068
|
-
import { z as z7 } from "zod";
|
|
4069
|
-
var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
|
|
4070
|
-
var composeInputsSchema = z7.strictObject({
|
|
4071
|
-
connectedStores: z7.array(
|
|
4072
|
-
z7.strictObject({
|
|
4073
|
-
storeId: z7.string().min(1),
|
|
4074
|
-
slug: z7.string().min(1),
|
|
4075
|
-
// A row with an empty binding key must not fail a deploy: the rail
|
|
4076
|
-
// treats falsy as "no binding key", so normalise rather than reject.
|
|
4077
|
-
bindingKey: z7.string().nullish().transform((value) => value || null),
|
|
4078
|
-
accessLevel: z7.enum(["read", "write", "admin"]),
|
|
4079
|
-
// Defaulted so a file written before the platform emitted store types
|
|
4080
|
-
// (database rows only) still parses. The platform starts writing
|
|
4081
|
-
// storage rows, with `type` set, once forks run a compose that reads it.
|
|
4082
|
-
type: z7.enum(["database", "storage"]).default("database")
|
|
4083
|
-
})
|
|
4084
|
-
).default([]),
|
|
4085
|
-
installs: z7.record(
|
|
4086
|
-
z7.string(),
|
|
4087
|
-
z7.strictObject({
|
|
4088
|
-
installedVersion: z7.string().min(1),
|
|
4089
|
-
datastoreBindings: z7.record(z7.string(), z7.string()).nullish()
|
|
4090
|
-
})
|
|
4091
|
-
).default({})
|
|
4092
|
-
});
|
|
4093
|
-
var STUB_IGNORE_PATH = "apps/web/src/app/.gitignore";
|
|
4094
|
-
var STUB_IGNORE_HEADER = "# Generated by stardeck-compose \u2014 Module-rail stubs are build outputs; do not edit or commit them.";
|
|
4095
|
-
function escapeStubIgnorePattern(pattern) {
|
|
4096
|
-
const escaped = pattern.replace(/[\\[\]*?]/g, (char) => `\\${char}`);
|
|
4097
|
-
return /^[#!]/.test(escaped) ? `\\${escaped}` : escaped;
|
|
4098
|
-
}
|
|
4099
|
-
function buildStubIgnore(artifactPaths) {
|
|
4100
|
-
const prefix = "apps/web/src/app/";
|
|
4101
|
-
const entries = artifactPaths.filter((artifact) => artifact.startsWith(prefix)).map((artifact) => escapeStubIgnorePattern(`/${artifact.slice(prefix.length)}`)).sort();
|
|
4102
|
-
return [STUB_IGNORE_HEADER, ...entries].join("\n") + "\n";
|
|
4103
|
-
}
|
|
4104
|
-
|
|
4105
|
-
// ../../packages/lib/src/shared/module-enablement.ts
|
|
4106
|
-
function isModuleEnabledByList(raw, name, kindOf) {
|
|
4107
|
-
if (!raw) return true;
|
|
4108
|
-
const kind = kindOf(name);
|
|
4109
|
-
if (kind != null && kind !== "feature") return true;
|
|
4110
|
-
return raw.split(",").includes(name);
|
|
4111
|
-
}
|
|
4112
|
-
|
|
4113
3993
|
// ../../packages/lib/src/shared/platform-owned-paths.ts
|
|
4114
3994
|
var APP_WEB_PREFIX = "apps/web/";
|
|
4115
3995
|
var MODULE_STUB_MARKER = "@stardeck-module-rail-generated";
|
|
@@ -6036,6 +5916,50 @@ function rejectPseudoModuleEntries(entries, parentDir, label) {
|
|
|
6036
5916
|
return dirs;
|
|
6037
5917
|
}
|
|
6038
5918
|
|
|
5919
|
+
// ../../packages/lib/src/shared/module-composition.ts
|
|
5920
|
+
import { z as z7 } from "zod";
|
|
5921
|
+
var creationSourceBlankSchema = z7.object({
|
|
5922
|
+
type: z7.literal("blank")
|
|
5923
|
+
});
|
|
5924
|
+
var creationSourceBlueprintSchema = z7.object({
|
|
5925
|
+
type: z7.literal("blueprint"),
|
|
5926
|
+
/** Internal template/fork project id — keep template naming in identifiers. */
|
|
5927
|
+
blueprintProjectId: z7.string().uuid(),
|
|
5928
|
+
/**
|
|
5929
|
+
* `null`/absent means every feature Module. `[]` is refused: the platform
|
|
5930
|
+
* serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
|
|
5931
|
+
* enablement parser reads back as "all" (`module-enablement.ts`) — the
|
|
5932
|
+
* opposite of what an empty selection means.
|
|
5933
|
+
*/
|
|
5934
|
+
enabledModules: z7.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
|
|
5935
|
+
});
|
|
5936
|
+
var creationSourceSchema = z7.discriminatedUnion("type", [
|
|
5937
|
+
creationSourceBlankSchema,
|
|
5938
|
+
creationSourceBlueprintSchema
|
|
5939
|
+
]);
|
|
5940
|
+
var moduleInstallHandoffSchema = z7.object({
|
|
5941
|
+
moduleName: z7.string().min(1),
|
|
5942
|
+
homeProjectId: z7.string().uuid(),
|
|
5943
|
+
installedVersion: z7.string().min(1),
|
|
5944
|
+
baselineSha: z7.string().min(1),
|
|
5945
|
+
mounts: z7.array(
|
|
5946
|
+
z7.object({
|
|
5947
|
+
group: z7.string(),
|
|
5948
|
+
segment: z7.string()
|
|
5949
|
+
})
|
|
5950
|
+
),
|
|
5951
|
+
integration: z7.array(z7.string()),
|
|
5952
|
+
workflows: z7.array(z7.string()),
|
|
5953
|
+
prunedEnhancements: z7.array(z7.string()),
|
|
5954
|
+
restoredEnhancements: z7.array(z7.string()).optional(),
|
|
5955
|
+
permissions: z7.array(
|
|
5956
|
+
z7.object({
|
|
5957
|
+
key: z7.string().min(1),
|
|
5958
|
+
description: z7.string().min(1)
|
|
5959
|
+
})
|
|
5960
|
+
).optional()
|
|
5961
|
+
});
|
|
5962
|
+
|
|
6039
5963
|
// ../../packages/lib/src/shared/schema-ops.ts
|
|
6040
5964
|
import { z as z8 } from "zod";
|
|
6041
5965
|
var columnSpecSchema = z8.object({
|
|
@@ -7499,6 +7423,9 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
7499
7423
|
var HOME_I18N_SUBSTRATE_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/substrate`;
|
|
7500
7424
|
var HOME_I18N_MESSAGES_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/messages`;
|
|
7501
7425
|
|
|
7426
|
+
// src/index.ts
|
|
7427
|
+
import ts6 from "typescript";
|
|
7428
|
+
|
|
7502
7429
|
// src/module-boundaries.ts
|
|
7503
7430
|
import fs2 from "fs";
|
|
7504
7431
|
import path2 from "path";
|
|
@@ -7768,6 +7695,41 @@ function assertNoAppLayerImporters(cwd, excluded) {
|
|
|
7768
7695
|
);
|
|
7769
7696
|
}
|
|
7770
7697
|
}
|
|
7698
|
+
var TSCONFIG_PATH = "apps/web/tsconfig.json";
|
|
7699
|
+
var BUILD_TSCONFIG_PATH = "apps/web/tsconfig.build.gen.json";
|
|
7700
|
+
var BUILD_TSCONFIG_HEADER = "// Generated by stardeck-compose \u2014 the tsconfig `next build` type-checks. Do not edit or commit.";
|
|
7701
|
+
function writeBuildTsconfig(cwd, excluded) {
|
|
7702
|
+
const baseFile = path3.join(cwd, TSCONFIG_PATH);
|
|
7703
|
+
if (!fs3.existsSync(path3.join(cwd, MODULES_DIR2)) || !fs3.existsSync(baseFile)) return;
|
|
7704
|
+
const base = ts6.readConfigFile(baseFile, ts6.sys.readFile);
|
|
7705
|
+
if (base.error) {
|
|
7706
|
+
throw new Error(
|
|
7707
|
+
`[compose] cannot read ${TSCONFIG_PATH}: ${ts6.flattenDiagnosticMessageText(base.error.messageText, "\n")}`
|
|
7708
|
+
);
|
|
7709
|
+
}
|
|
7710
|
+
const baseExclude = base.config?.exclude ?? ["node_modules"];
|
|
7711
|
+
const modulesDir = path3.posix.relative("apps/web", MODULES_DIR2);
|
|
7712
|
+
const config = {
|
|
7713
|
+
extends: "./tsconfig.json",
|
|
7714
|
+
exclude: [
|
|
7715
|
+
...baseExclude,
|
|
7716
|
+
...excluded.flatMap((name) => [
|
|
7717
|
+
`${modulesDir}/${name}`,
|
|
7718
|
+
`${modulesDir}/*/enhancements/${name}`
|
|
7719
|
+
])
|
|
7720
|
+
]
|
|
7721
|
+
};
|
|
7722
|
+
const content = `${BUILD_TSCONFIG_HEADER}
|
|
7723
|
+
${JSON.stringify(config, null, 2)}
|
|
7724
|
+
`;
|
|
7725
|
+
const file = path3.join(cwd, BUILD_TSCONFIG_PATH);
|
|
7726
|
+
if (!fs3.existsSync(file) || fs3.readFileSync(file, "utf8") !== content) {
|
|
7727
|
+
fs3.writeFileSync(file, content);
|
|
7728
|
+
}
|
|
7729
|
+
console.log(
|
|
7730
|
+
`[compose] ${BUILD_TSCONFIG_PATH} excludes ${excluded.length} Module(s): ${excluded.join(",") || "none"}`
|
|
7731
|
+
);
|
|
7732
|
+
}
|
|
7771
7733
|
function removeDir(absolute) {
|
|
7772
7734
|
if (!fs3.existsSync(absolute)) return false;
|
|
7773
7735
|
fs3.rmSync(absolute, { recursive: true, force: true });
|
|
@@ -7815,6 +7777,7 @@ async function compose(options) {
|
|
|
7815
7777
|
skipComposeInputs: true
|
|
7816
7778
|
});
|
|
7817
7779
|
const gitignoreEntries = options.enabled ? null : writeStubGitignore(options.cwd, result.artifactPaths);
|
|
7780
|
+
writeBuildTsconfig(options.cwd, result.excludedModules);
|
|
7818
7781
|
let pruned = 0;
|
|
7819
7782
|
if (options.prune) {
|
|
7820
7783
|
for (const name of result.excludedModules) {
|
|
@@ -7836,6 +7799,7 @@ async function compose(options) {
|
|
|
7836
7799
|
};
|
|
7837
7800
|
}
|
|
7838
7801
|
export {
|
|
7802
|
+
BUILD_TSCONFIG_PATH,
|
|
7839
7803
|
COMPOSE_INPUTS_PATH,
|
|
7840
7804
|
assertSupportedTypescript,
|
|
7841
7805
|
compose,
|