@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 CHANGED
@@ -18,6 +18,12 @@ Compose turns that declaration into the code Next.js actually builds:
18
18
  per composed Module that ships `server/registrations.ts`
19
19
  - one `page.tsx` / `route.ts` stub under `apps/web/src/app/**` per declared
20
20
  mount and endpoint
21
+ - `apps/web/tsconfig.build.gen.json` (apps with a Module tree only) — extends
22
+ `tsconfig.json` and excludes every Module `--enabled` left out, plus each
23
+ kept Module's `enhancements/<excluded>/`. Their source stays on disk but their
24
+ stubs are gone, so `next build` must type-check through this file
25
+ (`typescript.tsconfigPath` in `next.config.ts`), never through `tsconfig.json`.
26
+ Gitignore it; do not hand-maintain an exclude list.
21
27
 
22
28
  ## Running it
23
29
 
package/dist/cli.js CHANGED
@@ -3901,7 +3901,7 @@ var MODULES_GEN_PATH = `${APP_WEB_PREFIX}src/modules.gen.ts`;
3901
3901
  var APP_EXTENSIONS_PATH = `${APP_WEB_PREFIX}src/lib/modules/app-extensions.ts`;
3902
3902
 
3903
3903
  // src/cli.ts
3904
- var import_typescript6 = __toESM(require("typescript"));
3904
+ var import_typescript7 = __toESM(require("typescript"));
3905
3905
  var import_node_path4 = __toESM(require("path"));
3906
3906
 
3907
3907
  // src/index.ts
@@ -3966,147 +3966,29 @@ function shellQuote(value) {
3966
3966
  return `'${value.replace(/'/g, `'\\''`)}'`;
3967
3967
  }
3968
3968
 
3969
- // ../../packages/lib/src/shared/module-composition.ts
3970
- var import_zod6 = require("zod");
3971
- var moduleRefSchema = import_zod6.z.object({
3972
- homeProjectId: import_zod6.z.string().uuid(),
3973
- moduleName: moduleNameSchema
3974
- });
3975
- var creationSourceBlankSchema = import_zod6.z.object({
3976
- type: import_zod6.z.literal("blank")
3977
- });
3978
- var creationSourceBlueprintSchema = import_zod6.z.object({
3979
- type: import_zod6.z.literal("blueprint"),
3980
- /** Internal template/fork project id — keep template naming in identifiers. */
3981
- blueprintProjectId: import_zod6.z.string().uuid(),
3982
- /**
3983
- * `null`/absent means every feature Module. `[]` is refused: the platform
3984
- * serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
3985
- * enablement parser reads back as "all" (`module-enablement.ts`) — the
3986
- * opposite of what an empty selection means.
3987
- */
3988
- enabledModules: import_zod6.z.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
3989
- });
3990
- var creationSourceModulesSchema = import_zod6.z.object({
3991
- type: import_zod6.z.literal("modules"),
3992
- requested: import_zod6.z.array(moduleRefSchema).min(1)
3993
- });
3994
- var creationSourceSchema = import_zod6.z.discriminatedUnion("type", [
3995
- creationSourceBlankSchema,
3996
- creationSourceBlueprintSchema,
3997
- creationSourceModulesSchema
3998
- ]);
3999
- var moduleCompositionStatusSchema = import_zod6.z.enum([
4000
- "pending",
4001
- "installing",
4002
- "ready",
4003
- "partial",
4004
- "failed"
4005
- ]);
4006
- var resolvedModuleSnapshotSchema = moduleRefSchema.extend({
4007
- version: import_zod6.z.string().min(1),
4008
- homeCommitSha: import_zod6.z.string().min(1)
4009
- });
4010
- var moduleInstallHandoffSchema = import_zod6.z.object({
4011
- moduleName: import_zod6.z.string().min(1),
4012
- homeProjectId: import_zod6.z.string().uuid(),
4013
- installedVersion: import_zod6.z.string().min(1),
4014
- baselineSha: import_zod6.z.string().min(1),
4015
- mounts: import_zod6.z.array(
4016
- import_zod6.z.object({
4017
- group: import_zod6.z.string(),
4018
- segment: import_zod6.z.string()
4019
- })
4020
- ),
4021
- integration: import_zod6.z.array(import_zod6.z.string()),
4022
- workflows: import_zod6.z.array(import_zod6.z.string()),
4023
- prunedEnhancements: import_zod6.z.array(import_zod6.z.string()),
4024
- restoredEnhancements: import_zod6.z.array(import_zod6.z.string()).optional(),
4025
- permissions: import_zod6.z.array(
4026
- import_zod6.z.object({
4027
- key: import_zod6.z.string().min(1),
4028
- description: import_zod6.z.string().min(1)
4029
- })
4030
- ).optional()
4031
- });
4032
- var moduleCompositionRunAttemptSchema = import_zod6.z.object({
4033
- module: moduleRefSchema,
4034
- runId: import_zod6.z.string().min(1),
4035
- status: import_zod6.z.string().min(1),
4036
- schemaApplied: import_zod6.z.boolean(),
4037
- error: import_zod6.z.string().optional(),
4038
- /** Prefer full ModuleInstallHandoff; identity fields optional for older rows. */
4039
- handoff: moduleInstallHandoffSchema.partial({ moduleName: true, homeProjectId: true }).optional()
4040
- });
4041
- var initialModuleCompositionSchema = import_zod6.z.object({
4042
- version: import_zod6.z.literal(1),
4043
- status: moduleCompositionStatusSchema,
4044
- requested: import_zod6.z.array(moduleRefSchema).min(1),
4045
- resolved: import_zod6.z.array(resolvedModuleSnapshotSchema),
4046
- installOrder: import_zod6.z.array(moduleRefSchema),
4047
- runs: import_zod6.z.array(moduleCompositionRunAttemptSchema).default([]),
4048
- /**
4049
- * True when any failed/partial attempt applied schema before failing.
4050
- * Never claim transactional rollback across git/schema.
4051
- */
4052
- schemaApplied: import_zod6.z.boolean().default(false),
4053
- /**
4054
- * Present when retry would silently change pinned home SHAs — caller must
4055
- * reconfirm the new plan rather than continue.
4056
- */
4057
- reconfirmationRequired: import_zod6.z.object({
4058
- reason: import_zod6.z.string(),
4059
- previous: import_zod6.z.array(resolvedModuleSnapshotSchema),
4060
- next: import_zod6.z.array(resolvedModuleSnapshotSchema)
4061
- }).optional(),
4062
- error: import_zod6.z.string().optional(),
4063
- /**
4064
- * First-turn system handoff lifecycle. Absent/`pending` means inject when
4065
- * status is ready; `consumed` means a successful agent turn already used it.
4066
- */
4067
- systemHandoffStatus: import_zod6.z.enum(["pending", "consumed"]).optional(),
4068
- /**
4069
- * CAS ownership token for concurrent retry attempts. Only the attempt that
4070
- * currently owns this value may reset or compensate durable composition state.
4071
- */
4072
- retryAttemptId: import_zod6.z.string().min(1).optional(),
4073
- /**
4074
- * When the current `installing` attempt was claimed. A setup run that dies
4075
- * with its host (a killed Vercel instance) leaves the composition `installing`
4076
- * forever, and the creating page's poll only stops on ready/partial/failed —
4077
- * so staleness, not a queue's stall detector, is what settles it. Absent on
4078
- * rows claimed before this field existed; treated as stale.
4079
- */
4080
- attemptStartedAt: import_zod6.z.string().datetime().optional(),
4081
- /** Outside-module files the agent changed during connection work. */
4082
- integrationFiles: import_zod6.z.array(import_zod6.z.string()).optional(),
4083
- verificationSummary: import_zod6.z.string().optional()
4084
- });
4085
- var MODULE_SETUP_ATTEMPT_STALE_MS = 10 * 60 * 1e3;
4086
-
4087
3969
  // ../../packages/lib/src/shared/compose-inputs.ts
4088
- var import_zod7 = require("zod");
3970
+ var import_zod6 = require("zod");
4089
3971
  var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
4090
- var composeInputsSchema = import_zod7.z.strictObject({
4091
- connectedStores: import_zod7.z.array(
4092
- import_zod7.z.strictObject({
4093
- storeId: import_zod7.z.string().min(1),
4094
- slug: import_zod7.z.string().min(1),
3972
+ var composeInputsSchema = import_zod6.z.strictObject({
3973
+ connectedStores: import_zod6.z.array(
3974
+ import_zod6.z.strictObject({
3975
+ storeId: import_zod6.z.string().min(1),
3976
+ slug: import_zod6.z.string().min(1),
4095
3977
  // A row with an empty binding key must not fail a deploy: the rail
4096
3978
  // treats falsy as "no binding key", so normalise rather than reject.
4097
- bindingKey: import_zod7.z.string().nullish().transform((value) => value || null),
4098
- accessLevel: import_zod7.z.enum(["read", "write", "admin"]),
3979
+ bindingKey: import_zod6.z.string().nullish().transform((value) => value || null),
3980
+ accessLevel: import_zod6.z.enum(["read", "write", "admin"]),
4099
3981
  // Defaulted so a file written before the platform emitted store types
4100
3982
  // (database rows only) still parses. The platform starts writing
4101
3983
  // storage rows, with `type` set, once forks run a compose that reads it.
4102
- type: import_zod7.z.enum(["database", "storage"]).default("database")
3984
+ type: import_zod6.z.enum(["database", "storage"]).default("database")
4103
3985
  })
4104
3986
  ).default([]),
4105
- installs: import_zod7.z.record(
4106
- import_zod7.z.string(),
4107
- import_zod7.z.strictObject({
4108
- installedVersion: import_zod7.z.string().min(1),
4109
- datastoreBindings: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.string()).nullish()
3987
+ installs: import_zod6.z.record(
3988
+ import_zod6.z.string(),
3989
+ import_zod6.z.strictObject({
3990
+ installedVersion: import_zod6.z.string().min(1),
3991
+ datastoreBindings: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).nullish()
4110
3992
  })
4111
3993
  ).default({})
4112
3994
  });
@@ -6043,6 +5925,50 @@ function rejectPseudoModuleEntries(entries, parentDir, label) {
6043
5925
  return dirs;
6044
5926
  }
6045
5927
 
5928
+ // ../../packages/lib/src/shared/module-composition.ts
5929
+ var import_zod7 = require("zod");
5930
+ var creationSourceBlankSchema = import_zod7.z.object({
5931
+ type: import_zod7.z.literal("blank")
5932
+ });
5933
+ var creationSourceBlueprintSchema = import_zod7.z.object({
5934
+ type: import_zod7.z.literal("blueprint"),
5935
+ /** Internal template/fork project id — keep template naming in identifiers. */
5936
+ blueprintProjectId: import_zod7.z.string().uuid(),
5937
+ /**
5938
+ * `null`/absent means every feature Module. `[]` is refused: the platform
5939
+ * serialises it to an empty `NEXT_PUBLIC_STARDECK_ENABLED_MODULES`, which the
5940
+ * enablement parser reads back as "all" (`module-enablement.ts`) — the
5941
+ * opposite of what an empty selection means.
5942
+ */
5943
+ enabledModules: import_zod7.z.array(moduleNameSchema).min(1, "Enable at least one Module").max(100).nullable().optional()
5944
+ });
5945
+ var creationSourceSchema = import_zod7.z.discriminatedUnion("type", [
5946
+ creationSourceBlankSchema,
5947
+ creationSourceBlueprintSchema
5948
+ ]);
5949
+ var moduleInstallHandoffSchema = import_zod7.z.object({
5950
+ moduleName: import_zod7.z.string().min(1),
5951
+ homeProjectId: import_zod7.z.string().uuid(),
5952
+ installedVersion: import_zod7.z.string().min(1),
5953
+ baselineSha: import_zod7.z.string().min(1),
5954
+ mounts: import_zod7.z.array(
5955
+ import_zod7.z.object({
5956
+ group: import_zod7.z.string(),
5957
+ segment: import_zod7.z.string()
5958
+ })
5959
+ ),
5960
+ integration: import_zod7.z.array(import_zod7.z.string()),
5961
+ workflows: import_zod7.z.array(import_zod7.z.string()),
5962
+ prunedEnhancements: import_zod7.z.array(import_zod7.z.string()),
5963
+ restoredEnhancements: import_zod7.z.array(import_zod7.z.string()).optional(),
5964
+ permissions: import_zod7.z.array(
5965
+ import_zod7.z.object({
5966
+ key: import_zod7.z.string().min(1),
5967
+ description: import_zod7.z.string().min(1)
5968
+ })
5969
+ ).optional()
5970
+ });
5971
+
6046
5972
  // ../../packages/lib/src/shared/schema-ops.ts
6047
5973
  var import_zod8 = require("zod");
6048
5974
  var columnSpecSchema = import_zod8.z.object({
@@ -7506,6 +7432,9 @@ async function reconcileCompositionArtifacts(context, options = {}) {
7506
7432
  var HOME_I18N_SUBSTRATE_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/substrate`;
7507
7433
  var HOME_I18N_MESSAGES_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/messages`;
7508
7434
 
7435
+ // src/index.ts
7436
+ var import_typescript6 = __toESM(require("typescript"));
7437
+
7509
7438
  // src/module-boundaries.ts
7510
7439
  var import_node_fs2 = __toESM(require("fs"));
7511
7440
  var import_node_path2 = __toESM(require("path"));
@@ -7775,6 +7704,41 @@ function assertNoAppLayerImporters(cwd, excluded) {
7775
7704
  );
7776
7705
  }
7777
7706
  }
7707
+ var TSCONFIG_PATH = "apps/web/tsconfig.json";
7708
+ var BUILD_TSCONFIG_PATH = "apps/web/tsconfig.build.gen.json";
7709
+ var BUILD_TSCONFIG_HEADER = "// Generated by stardeck-compose \u2014 the tsconfig `next build` type-checks. Do not edit or commit.";
7710
+ function writeBuildTsconfig(cwd, excluded) {
7711
+ const baseFile = import_node_path3.default.join(cwd, TSCONFIG_PATH);
7712
+ if (!import_node_fs3.default.existsSync(import_node_path3.default.join(cwd, MODULES_DIR2)) || !import_node_fs3.default.existsSync(baseFile)) return;
7713
+ const base = import_typescript6.default.readConfigFile(baseFile, import_typescript6.default.sys.readFile);
7714
+ if (base.error) {
7715
+ throw new Error(
7716
+ `[compose] cannot read ${TSCONFIG_PATH}: ${import_typescript6.default.flattenDiagnosticMessageText(base.error.messageText, "\n")}`
7717
+ );
7718
+ }
7719
+ const baseExclude = base.config?.exclude ?? ["node_modules"];
7720
+ const modulesDir = import_node_path3.default.posix.relative("apps/web", MODULES_DIR2);
7721
+ const config = {
7722
+ extends: "./tsconfig.json",
7723
+ exclude: [
7724
+ ...baseExclude,
7725
+ ...excluded.flatMap((name) => [
7726
+ `${modulesDir}/${name}`,
7727
+ `${modulesDir}/*/enhancements/${name}`
7728
+ ])
7729
+ ]
7730
+ };
7731
+ const content = `${BUILD_TSCONFIG_HEADER}
7732
+ ${JSON.stringify(config, null, 2)}
7733
+ `;
7734
+ const file = import_node_path3.default.join(cwd, BUILD_TSCONFIG_PATH);
7735
+ if (!import_node_fs3.default.existsSync(file) || import_node_fs3.default.readFileSync(file, "utf8") !== content) {
7736
+ import_node_fs3.default.writeFileSync(file, content);
7737
+ }
7738
+ console.log(
7739
+ `[compose] ${BUILD_TSCONFIG_PATH} excludes ${excluded.length} Module(s): ${excluded.join(",") || "none"}`
7740
+ );
7741
+ }
7778
7742
  function removeDir(absolute) {
7779
7743
  if (!import_node_fs3.default.existsSync(absolute)) return false;
7780
7744
  import_node_fs3.default.rmSync(absolute, { recursive: true, force: true });
@@ -7822,6 +7786,7 @@ async function compose(options) {
7822
7786
  skipComposeInputs: true
7823
7787
  });
7824
7788
  const gitignoreEntries = options.enabled ? null : writeStubGitignore(options.cwd, result.artifactPaths);
7789
+ writeBuildTsconfig(options.cwd, result.excludedModules);
7825
7790
  let pruned = 0;
7826
7791
  if (options.prune) {
7827
7792
  for (const name of result.excludedModules) {
@@ -7845,7 +7810,7 @@ async function compose(options) {
7845
7810
 
7846
7811
  // src/cli.ts
7847
7812
  async function main() {
7848
- assertSupportedTypescript(import_typescript6.default.versionMajorMinor);
7813
+ assertSupportedTypescript(import_typescript7.default.versionMajorMinor);
7849
7814
  const { values } = (0, import_node_util.parseArgs)({
7850
7815
  options: {
7851
7816
  enabled: { type: "string" },
package/dist/index.d.mts CHANGED
@@ -129,10 +129,11 @@ declare function assertSupportedTypescript(versionMajorMinor: string): void;
129
129
  * rules those out today; a total helper keeps it that way).
130
130
  */
131
131
  declare function escapeGitignore(pattern: string): string;
132
+ declare const BUILD_TSCONFIG_PATH = "apps/web/tsconfig.build.gen.json";
132
133
  /**
133
134
  * Regenerate the Module-rail artifacts (the six `src/*.gen.ts` files and every
134
135
  * route/endpoint stub under `src/app`) for the app rooted at `options.cwd`.
135
136
  */
136
137
  declare function compose(options: ComposeOptions): Promise<ComposeResult>;
137
138
 
138
- export { type BoundaryViolation, COMPOSE_INPUTS_PATH, type ComposeInputs, type ComposeOptions, type ComposeResult, assertSupportedTypescript, compose, escapeGitignore, findModuleBoundaryViolations, findOptionalPeerViolations, formatBoundaryViolations, readComposeInputs };
139
+ export { BUILD_TSCONFIG_PATH, type BoundaryViolation, COMPOSE_INPUTS_PATH, type ComposeInputs, type ComposeOptions, type ComposeResult, assertSupportedTypescript, compose, escapeGitignore, findModuleBoundaryViolations, findOptionalPeerViolations, formatBoundaryViolations, readComposeInputs };
package/dist/index.d.ts CHANGED
@@ -129,10 +129,11 @@ declare function assertSupportedTypescript(versionMajorMinor: string): void;
129
129
  * rules those out today; a total helper keeps it that way).
130
130
  */
131
131
  declare function escapeGitignore(pattern: string): string;
132
+ declare const BUILD_TSCONFIG_PATH = "apps/web/tsconfig.build.gen.json";
132
133
  /**
133
134
  * Regenerate the Module-rail artifacts (the six `src/*.gen.ts` files and every
134
135
  * route/endpoint stub under `src/app`) for the app rooted at `options.cwd`.
135
136
  */
136
137
  declare function compose(options: ComposeOptions): Promise<ComposeResult>;
137
138
 
138
- export { type BoundaryViolation, COMPOSE_INPUTS_PATH, type ComposeInputs, type ComposeOptions, type ComposeResult, assertSupportedTypescript, compose, escapeGitignore, findModuleBoundaryViolations, findOptionalPeerViolations, formatBoundaryViolations, readComposeInputs };
139
+ export { BUILD_TSCONFIG_PATH, type BoundaryViolation, COMPOSE_INPUTS_PATH, type ComposeInputs, type ComposeOptions, type ComposeResult, assertSupportedTypescript, compose, escapeGitignore, findModuleBoundaryViolations, findOptionalPeerViolations, formatBoundaryViolations, readComposeInputs };