@orkestrel/scaffold 0.0.7 → 0.0.8

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.
@@ -76,6 +76,8 @@ var SRC_MATRIX = Object.freeze({
76
76
  formats: Object.freeze(["es", "cjs"])
77
77
  })
78
78
  });
79
+ /** The computed configuration files required by a workspace-owned executable. */
80
+ var BIN_CONFIGS = Object.freeze(["configs/src/vite.bin.config.ts", "configs/src/tsconfig.bin.json"]);
79
81
  /**
80
82
  * The per-environment application matrix: thin config artifacts, Vitest project
81
83
  * label, and executable entry where the environment produces a runtime bundle.
@@ -105,7 +107,7 @@ var APP_MATRIX = Object.freeze({
105
107
  * `scripts/codex.sh` / `scripts/ollama.sh`), the repository coding-law policy module,
106
108
  * the line's seven byte-identical root dotfiles, and the two guides-grouped
107
109
  * mirror candidates: the line-wide dev-tooling guide
108
- * (`guides/src/guide.md`) and the scaffold engine's own self-guide
110
+ * (`guides/src/guide.md`) and the scaffold bin's own self-guide
109
111
  * (`guides/src/scaffold.md`). `stageHost` vendors both; each plan carries the
110
112
  * subset selected by `selectHostPaths`, omitting the target blueprint's own
111
113
  * guide.
@@ -138,6 +140,8 @@ var HOST_PATHS = Object.freeze([
138
140
  "guides/src/guide.md",
139
141
  "guides/src/scaffold.md"
140
142
  ]);
143
+ /** The consumer-owned live-service provisioner expected only by service workspaces. */
144
+ var SERVICE_SCRIPT_PATH = "scripts/service.sh";
141
145
  /** The package-name RegExp — lowercase alphanumeric-with-hyphens, letter-first. */
142
146
  var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
143
147
  /** Maximum bare workspace name length beneath the generated `@orkestrel/` scope. */
@@ -220,11 +224,11 @@ var DEFAULT_VERSION = "0.0.1";
220
224
  /** The `engines.node` range the `blueprint` builder fills. */
221
225
  var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
222
226
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
223
- var SCAFFOLD_RANGE = "^0.0.7";
227
+ var SCAFFOLD_RANGE = "^0.0.8";
224
228
  /** Tooling versions shared by scaffold and every generated workspace. */
225
229
  var BASE_DEV_DEPENDENCIES = Object.freeze({
226
230
  "@microsoft/api-extractor": "^7.58.12",
227
- "@orkestrel/guide": "^0.0.5",
231
+ "@orkestrel/guide": "^0.0.7",
228
232
  "@orkestrel/scaffold": SCAFFOLD_RANGE,
229
233
  "@types/node": "^26.1.2",
230
234
  oxfmt: "^0.61.0",
@@ -419,9 +423,9 @@ function member(name, category, summary, environment = "core") {
419
423
  * @remarks
420
424
  * `version` / `engines` default `DEFAULT_VERSION` / `DEFAULT_ENGINES`,
421
425
  * `src` defaults `['core']`, and `app` / `keywords` / `dependencies` /
422
- * `peers` / `extras` / `overrides` default `[]`. `description` is OMITTED
423
- * entirely when absent, so the result round-trips the exact-record
424
- * `Blueprint` guard.
426
+ * `peers` / `extras` / `overrides` default `[]`, and `bin` / `integration` /
427
+ * `service` default `false`. `description` is OMITTED entirely when absent, so
428
+ * the result round-trips the exact-record `Blueprint` guard.
425
429
  * @returns A complete `Blueprint`.
426
430
  *
427
431
  * @example
@@ -443,7 +447,9 @@ function blueprint(name, options) {
443
447
  version: options?.version ?? "0.0.1",
444
448
  engines: options?.engines ?? DEFAULT_ENGINES,
445
449
  overrides: options?.overrides ?? [],
446
- engine: options?.engine ?? false
450
+ bin: options?.bin ?? false,
451
+ integration: options?.integration ?? false,
452
+ service: options?.service ?? false
447
453
  };
448
454
  return options?.description === void 0 ? base : {
449
455
  ...base,
@@ -1794,7 +1800,9 @@ function blueprintShape() {
1794
1800
  max: MAX_RANGE_LENGTH
1795
1801
  }),
1796
1802
  overrides: arrayShape(overrideShape(), { max: MAX_COLLECTION_ITEMS }),
1797
- engine: booleanShape()
1803
+ bin: booleanShape(),
1804
+ integration: booleanShape(),
1805
+ service: booleanShape()
1798
1806
  });
1799
1807
  }
1800
1808
  /**
@@ -5522,24 +5530,28 @@ function compareCodeUnit(a, b) {
5522
5530
  return a < b ? -1 : a > b ? 1 : 0;
5523
5531
  }
5524
5532
  /**
5525
- * The host-neutral devDependency baseline every generated workspace needs.
5526
- * Browser providers are added only by browser selections or the scaffold
5527
- * engine's generated-browser consumer proof. A package's `extras` (code-unit
5528
- * sorted) merge in on top, the extras' declared range winning on a name
5529
- * collision with the baseline.
5533
+ * The complete development dependency set one blueprint emits. The shared
5534
+ * baseline is extended by package extras, dev-installed peers, selected
5535
+ * browser environments, and the bin axis's browser test provider.
5530
5536
  *
5531
- * @param extras - The blueprint's package-specific `extras` `Dependency[]`.
5537
+ * @param spec - The blueprint whose development dependencies are required.
5532
5538
  * @returns The merged `devDependencies` record.
5533
5539
  *
5534
5540
  * @example
5535
5541
  * ```ts
5536
- * devDependenciesFor([])['typescript'] // '^6.0.3'
5542
+ * devDependenciesFor(blueprint('router'))['typescript'] // '^6.0.3'
5537
5543
  * ```
5538
5544
  */
5539
- function devDependenciesFor(extras) {
5540
- const baseline = { ...BASE_DEV_DEPENDENCIES };
5541
- for (const extra of [...extras].sort((a, b) => compareCodeUnit(a.name, b.name))) baseline[extra.name] = extra.range;
5542
- return baseline;
5545
+ function devDependenciesFor(spec) {
5546
+ const dependencies = { ...BASE_DEV_DEPENDENCIES };
5547
+ for (const extra of [...spec.extras].sort((a, b) => compareCodeUnit(a.name, b.name))) dependencies[extra.name] = extra.range;
5548
+ for (const peer of [...spec.peers].sort((a, b) => compareCodeUnit(a.name, b.name))) dependencies[peer.name] = peer.range;
5549
+ return {
5550
+ ...dependencies,
5551
+ ...spec.src.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
5552
+ ...spec.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
5553
+ ...spec.bin ? { "@vitest/browser-playwright": SOURCE_BROWSER_DEV_DEPENDENCIES["@vitest/browser-playwright"] } : {}
5554
+ };
5543
5555
  }
5544
5556
  /**
5545
5557
  * Compute the `package.json` artifact's `content`, applying the manifest and
@@ -5564,24 +5576,22 @@ function packageManifest(spec) {
5564
5576
  for (const peer of [...spec.peers].sort((a, b) => compareCodeUnit(a.name, b.name))) peerDependencies[peer.name] = peer.range;
5565
5577
  const peerDependenciesMeta = {};
5566
5578
  for (const peer of spec.peers) if (peer.optional === true) peerDependenciesMeta[peer.name] = { optional: true };
5567
- const peerDevDependencies = {};
5568
- for (const peer of [...spec.peers].sort((a, b) => compareCodeUnit(a.name, b.name))) peerDevDependencies[peer.name] = peer.range;
5569
5579
  const scripts = {
5570
5580
  clean: "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
5571
5581
  copy: "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
5572
- scaffold: spec.engine ? "node ./dist/bin/scaffold.js" : "scaffold",
5582
+ scaffold: spec.bin ? "node ./dist/bin/scaffold.js" : "scaffold",
5573
5583
  lint: "oxlint --config .oxlintrc.json --fix --deny-warnings .",
5574
5584
  check: [
5575
5585
  "tsc --noEmit --project tsconfig.json",
5576
- ...hasSource || spec.engine ? ["npm run check:src"] : [],
5586
+ ...hasSource || spec.bin ? ["npm run check:src"] : [],
5577
5587
  ...spec.app.length > 0 ? ["npm run check:app"] : []
5578
5588
  ].join(" && ")
5579
5589
  };
5580
- if (hasSource || spec.engine) {
5581
- scripts["check:src"] = spec.src.map((environment) => `npm run check:src:${environment}`).join(" && ") + (spec.engine ? `${spec.src.length > 0 ? " && " : ""}npm run check:src:bin` : "");
5590
+ if (hasSource || spec.bin) {
5591
+ scripts["check:src"] = spec.src.map((environment) => `npm run check:src:${environment}`).join(" && ") + (spec.bin ? `${spec.src.length > 0 ? " && " : ""}npm run check:src:bin` : "");
5582
5592
  for (const environment of spec.src) scripts[`check:src:${environment}`] = `tsc --noEmit -p configs/src/tsconfig.${environment}.json`;
5583
5593
  }
5584
- if (spec.engine) scripts["check:src:bin"] = "tsc --noEmit -p configs/src/tsconfig.bin.json";
5594
+ if (spec.bin) scripts["check:src:bin"] = "tsc --noEmit -p configs/src/tsconfig.bin.json";
5585
5595
  if (spec.app.length > 0) {
5586
5596
  scripts["check:app"] = spec.app.map((environment) => `npm run check:app:${environment}`).join(" && ");
5587
5597
  for (const environment of spec.app) scripts[`check:app:${environment}`] = environment === "browser" ? "vue-tsc --noEmit -p configs/app/tsconfig.browser.json" : `tsc --noEmit -p configs/app/tsconfig.${environment}.json`;
@@ -5590,18 +5600,19 @@ function packageManifest(spec) {
5590
5600
  scripts["format:check"] = "oxfmt --config .oxfmtrc.json --check .";
5591
5601
  scripts["lint:check"] = "oxlint --config .oxlintrc.json --deny-warnings .";
5592
5602
  scripts.test = [
5593
- ...hasSource || spec.engine ? ["npm run test:src"] : [],
5603
+ ...hasSource || spec.bin ? ["npm run test:src"] : [],
5594
5604
  ...spec.app.length > 0 ? ["npm run test:app"] : [],
5595
5605
  "npm run test:policy",
5596
5606
  "npm run test:guides"
5597
5607
  ].join(" && ");
5598
- if (hasSource || spec.engine) {
5599
- scripts["test:src"] = "vitest run --config vite.config.ts --no-cache --reporter=dot " + spec.src.map((environment) => `--project src:${environment}`).join(" ") + (spec.engine ? `${spec.src.length > 0 ? " " : ""}--project src:bin` : "");
5608
+ if (hasSource || spec.bin) {
5609
+ scripts["test:src"] = "vitest run --config vite.config.ts --no-cache --reporter=dot " + spec.src.map((environment) => `--project src:${environment}`).join(" ") + (spec.bin ? `${spec.src.length > 0 ? " " : ""}--project src:bin` : "");
5600
5610
  for (const environment of spec.src) scripts[`test:src:${environment}`] = `vitest run --config vite.config.ts --no-cache --reporter=dot --project src:${environment}`;
5601
5611
  }
5602
- if (spec.engine) scripts["test:src:bin"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin";
5603
- if (spec.engine) scripts["test:integration"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project integration";
5604
- if (spec.engine) scripts["test:equivalence"] = "node -e \"const c=require('node:child_process'),n=process.platform==='win32'?'npm.cmd':'npm',r=c.spawnSync(n,['run','test:integration'],{stdio:'inherit',env:{...process.env,SCAFFOLD_BOUNDARY_EQUIVALENCE:'1'}});process.exit(r.status??1)\"";
5612
+ if (spec.bin) scripts["test:src:bin"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin";
5613
+ if (spec.integration) scripts["test:integration"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project integration";
5614
+ if (spec.bin && spec.integration) scripts["test:equivalence"] = "node -e \"const c=require('node:child_process'),n=process.platform==='win32'?'npm.cmd':'npm',r=c.spawnSync(n,['run','test:integration'],{stdio:'inherit',env:{...process.env,SCAFFOLD_BOUNDARY_EQUIVALENCE:'1'}});process.exit(r.status??1)\"";
5615
+ if (spec.service) scripts["test:service"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project service";
5605
5616
  if (spec.app.length > 0) {
5606
5617
  scripts["test:app"] = "vitest run --config vite.config.ts --no-cache --reporter=dot " + spec.app.map((environment) => `--project ${APP_MATRIX[environment].project}`).join(" ");
5607
5618
  for (const environment of spec.app) scripts[`test:app:${environment}`] = `vitest run --config vite.config.ts --no-cache --reporter=dot --project ${APP_MATRIX[environment].project}`;
@@ -5610,12 +5621,12 @@ function packageManifest(spec) {
5610
5621
  scripts["test:guides"] = "vitest run --config vite.config.ts --reporter=dot --project guides";
5611
5622
  scripts.build = [
5612
5623
  "npm run clean",
5613
- ...hasSource || spec.engine ? ["npm run build:src"] : [],
5624
+ ...hasSource || spec.bin ? ["npm run build:src"] : [],
5614
5625
  ...spec.app.length > 0 ? ["npm run build:app"] : [],
5615
- ...spec.engine ? ["npm run build:host"] : []
5626
+ ...spec.bin ? ["npm run build:host"] : []
5616
5627
  ].join(" && ");
5617
- if (hasSource || spec.engine) {
5618
- scripts["build:src"] = spec.src.map((environment) => `npm run build:src:${environment}`).join(" && ") + (spec.engine ? `${spec.src.length > 0 ? " && " : ""}npm run build:src:bin` : "");
5628
+ if (hasSource || spec.bin) {
5629
+ scripts["build:src"] = spec.src.map((environment) => `npm run build:src:${environment}`).join(" && ") + (spec.bin ? `${spec.src.length > 0 ? " && " : ""}npm run build:src:bin` : "");
5619
5630
  for (const environment of spec.src) scripts[`build:src:${environment}`] = environment === "browser" ? `vite build --config configs/src/vite.${environment}.config.ts` : `vite build --config configs/src/vite.${environment}.config.ts && npm run copy dist/src/${environment}/index.d.ts dist/src/${environment}/index.d.cts`;
5620
5631
  }
5621
5632
  if (spec.app.length > 0) {
@@ -5628,18 +5639,12 @@ function packageManifest(spec) {
5628
5639
  scripts["serve:build"] = "npm run build:app:server && npm run serve";
5629
5640
  }
5630
5641
  }
5631
- if (spec.engine) {
5642
+ if (spec.bin) {
5632
5643
  scripts["build:src:bin"] = "vite build --config configs/src/vite.bin.config.ts";
5633
5644
  scripts["build:host"] = "node -e \"import('./dist/src/server/index.js').then((m)=>{const n=m.stageHost(process.cwd(),'dist/host').length;console.log('build-host: staged '+n+' file(s) into dist/host')})\"";
5634
5645
  }
5635
- scripts.prepublishOnly = "npm run format:check && npm run lint:check && npm run check && npm run build && npm test" + (spec.engine ? " && npm run test:integration" : "");
5636
- const devDependencies = {
5637
- ...devDependenciesFor(spec.extras),
5638
- ...peerDevDependencies,
5639
- ...spec.src.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
5640
- ...spec.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
5641
- ...spec.engine ? SOURCE_BROWSER_DEV_DEPENDENCIES : {}
5642
- };
5646
+ scripts.prepublishOnly = "npm run format:check && npm run lint:check && npm run check && npm run build && npm test" + (spec.integration ? " && npm run test:integration" : "");
5647
+ const devDependencies = devDependenciesFor(spec);
5643
5648
  const manifest = {
5644
5649
  name: hasSource ? `@orkestrel/${spec.name}` : spec.name,
5645
5650
  version: spec.version,
@@ -5653,15 +5658,15 @@ function packageManifest(spec) {
5653
5658
  type: "git",
5654
5659
  url: `git+https://github.com/orkestrel/${spec.name}.git`
5655
5660
  },
5656
- ...spec.engine ? { bin: { scaffold: "./dist/bin/scaffold.js" } } : {},
5657
- files: spec.engine ? [
5661
+ ...spec.bin ? { bin: { scaffold: "./dist/bin/scaffold.js" } } : {},
5662
+ files: spec.bin ? [
5658
5663
  "dist/src",
5659
5664
  "dist/bin",
5660
5665
  "dist/host",
5661
5666
  "README.md"
5662
5667
  ] : hasSource ? ["dist/src", "README.md"] : ["dist/app", "README.md"],
5663
5668
  type: "module",
5664
- ...hasSource ? { sideEffects: spec.engine ? ["./src/bin/scaffold.ts", "./dist/bin/scaffold.js"] : false } : {},
5669
+ ...hasSource ? { sideEffects: spec.bin ? ["./src/bin/scaffold.ts", "./dist/bin/scaffold.js"] : false } : {},
5665
5670
  ...entry === void 0 ? {} : {
5666
5671
  main: entry.main,
5667
5672
  module: entry.module,
@@ -5671,7 +5676,7 @@ function packageManifest(spec) {
5671
5676
  },
5672
5677
  scripts,
5673
5678
  dependencies,
5674
- devDependencies: Object.fromEntries(Object.entries(devDependencies).filter(([depName]) => !spec.engine || depName !== "@orkestrel/scaffold").filter(([depName]) => hasSource || depName !== "@microsoft/api-extractor" && depName !== "vite-plugin-dts").filter(([depName]) => hasSource || spec.app.includes("browser") || depName !== "@vitest/browser-playwright").sort(([a], [b]) => compareCodeUnit(a, b))),
5679
+ devDependencies: Object.fromEntries(Object.entries(devDependencies).filter(([depName]) => !spec.bin || depName !== "@orkestrel/scaffold").filter(([depName]) => hasSource || depName !== "@microsoft/api-extractor" && depName !== "vite-plugin-dts").filter(([depName]) => hasSource || spec.app.includes("browser") || depName !== "@vitest/browser-playwright").sort(([a], [b]) => compareCodeUnit(a, b))),
5675
5680
  ...Object.keys(peerDependencies).length > 0 ? { peerDependencies } : {},
5676
5681
  ...Object.keys(peerDependenciesMeta).length > 0 ? { peerDependenciesMeta } : {},
5677
5682
  engines: { node: spec.engines }
@@ -5744,7 +5749,7 @@ function rootTsconfig(src, app = []) {
5744
5749
  *
5745
5750
  * @param src - The declared published `Environment[]`.
5746
5751
  * @param app - The declared application `Environment[]`, defaulting to none.
5747
- * @param engine - Whether the workspace also builds its own executable.
5752
+ * @param bin - Whether the workspace also builds its own executable.
5748
5753
  * @returns The machinery set the generated header renders.
5749
5754
  *
5750
5755
  * @example
@@ -5753,8 +5758,8 @@ function rootTsconfig(src, app = []) {
5753
5758
  * viteMachinery([], ['core']) // { browser: false, vue: false, output: false }
5754
5759
  * ```
5755
5760
  */
5756
- function viteMachinery(src, app = [], engine = false) {
5757
- const unbuilt = src.length === 0 && app.length > 0 && !engine && app.every((environment) => environment === "core");
5761
+ function viteMachinery(src, app = [], bin = false) {
5762
+ const unbuilt = src.length === 0 && app.length > 0 && !bin && app.every((environment) => environment === "core");
5758
5763
  return {
5759
5764
  browser: src.includes("browser") || app.includes("browser"),
5760
5765
  vue: app.includes("browser"),
@@ -5762,6 +5767,65 @@ function viteMachinery(src, app = [], engine = false) {
5762
5767
  };
5763
5768
  }
5764
5769
  /**
5770
+ * Derive the one ordered Vitest project registration list shared by every
5771
+ * generated root configuration shape.
5772
+ *
5773
+ * @param src - The declared published environments.
5774
+ * @param app - The declared application environments.
5775
+ * @param axes - Optional executable, integration, and service project axes.
5776
+ * @returns Source projects, application projects, proof projects, then optional axis projects.
5777
+ *
5778
+ * @example
5779
+ * ```ts
5780
+ * viteProjectRegistrations(['core'], [], { integration: true })
5781
+ * // [{ project: 'srcCore' }, { project: 'policy' }, { project: 'guides' }, { project: 'integration' }]
5782
+ * ```
5783
+ */
5784
+ function viteProjectRegistrations(src, app = [], axes = {}) {
5785
+ const registrations = [];
5786
+ for (const environment of ENVIRONMENTS) {
5787
+ if (!src.includes(environment)) continue;
5788
+ if (environment === "core") registrations.push({ project: "srcCore" });
5789
+ if (environment === "browser") registrations.push({
5790
+ project: "srcBrowser",
5791
+ browser: SRC_MATRIX.browser.project
5792
+ });
5793
+ if (environment === "server") registrations.push({ project: "srcServer" });
5794
+ }
5795
+ for (const environment of ENVIRONMENTS) {
5796
+ if (!app.includes(environment)) continue;
5797
+ if (environment === "core") registrations.push({ project: "appCore" });
5798
+ if (environment === "browser") registrations.push({
5799
+ project: "appBrowser",
5800
+ browser: APP_MATRIX.browser.project
5801
+ });
5802
+ if (environment === "server") registrations.push({ project: "appServer" });
5803
+ }
5804
+ registrations.push({ project: "policy" }, { project: "guides" });
5805
+ if (axes.bin === true) registrations.push({ project: "srcBin" });
5806
+ if (axes.integration === true) registrations.push({ project: "integration" });
5807
+ if (axes.service === true) registrations.push({ project: "service" });
5808
+ return registrations;
5809
+ }
5810
+ /**
5811
+ * Render the one ordered proof and structural-axis project definition block.
5812
+ *
5813
+ * @param axes - Optional executable, integration, and service project axes.
5814
+ * @returns Policy, guides, then selected axis project definitions, separated by one blank line.
5815
+ *
5816
+ * @example
5817
+ * ```ts
5818
+ * viteProjectDefinitions({ bin: true }).includes('export const srcBin =') // true
5819
+ * ```
5820
+ */
5821
+ function viteProjectDefinitions(axes = {}) {
5822
+ const definitions = [policyViteProject(), guidesViteProject()];
5823
+ if (axes.bin === true) definitions.push(binViteProject());
5824
+ if (axes.integration === true) definitions.push(integrationViteProject(axes));
5825
+ if (axes.service === true) definitions.push(serviceViteProject());
5826
+ return definitions.join("\n");
5827
+ }
5828
+ /**
5765
5829
  * Render the root Vitest project registration, preserving browser ownership
5766
5830
  * supplied by the caller.
5767
5831
  *
@@ -6137,15 +6201,21 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6137
6201
  const environmentBoundary = `
6138
6202
  ${CONST_KEYWORD} WORKSPACE_ROOT = realpathSync.native(dirname(fileURLToPath(import.meta.url)))${needsVue ? `\n${EXPORT_KEYWORD} ${CONST_KEYWORD} IMPORT_META_ENV_PREFIX = 'import.meta.env.'` : ""}
6139
6203
 
6204
+ ${EXPORT_KEYWORD} function fileSystemPath(pathname: string): string {
6205
+ if (!pathname.startsWith('/@fs/')) return pathname
6206
+ const candidate = pathname.slice('/@fs/'.length)
6207
+ // Vite URL normalization can collapse the leading slash of a POSIX absolute path.
6208
+ return candidate.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(candidate)
6209
+ ? candidate
6210
+ : \`/\${candidate}\`
6211
+ }
6212
+
6140
6213
  ${EXPORT_KEYWORD} function physicalPath(path: string): string {
6141
6214
  const [pathWithoutQuery] = path.split('?')
6142
- const candidate = pathWithoutQuery?.startsWith('/@fs/')
6143
- ? pathWithoutQuery.slice('/@fs/'.length)
6144
- : pathWithoutQuery
6145
- const physicalCandidate =
6146
- candidate !== undefined && /^file:/i.test(candidate) ? fileURLToPath(candidate) : candidate
6215
+ const candidate = fileSystemPath(pathWithoutQuery ?? path)
6216
+ const physicalCandidate = /^file:/i.test(candidate) ? fileURLToPath(candidate) : candidate
6147
6217
  const absoluteCandidate =
6148
- physicalCandidate === undefined || physicalCandidate.length === 0
6218
+ physicalCandidate.length === 0
6149
6219
  ? WORKSPACE_ROOT
6150
6220
  : isAbsolute(physicalCandidate)
6151
6221
  ? physicalCandidate
@@ -6202,7 +6272,7 @@ ${EXPORT_KEYWORD} function isWorkspaceBoundaryModule(id: string): boolean {
6202
6272
  const normalizedId = id.replaceAll('\\\\', '/')
6203
6273
  const [path] = normalizedId.split(/[?#]/)
6204
6274
  if (path === undefined) return false
6205
- let candidate = path.startsWith('/@fs/') ? path.slice('/@fs/'.length) : path
6275
+ let candidate = fileSystemPath(path)
6206
6276
  try {
6207
6277
  if (/^file:/i.test(candidate)) candidate = fileURLToPath(candidate)
6208
6278
  } catch {
@@ -6226,10 +6296,7 @@ ${EXPORT_KEYWORD} function isWorkspaceBoundaryModule(id: string): boolean {
6226
6296
  ${EXPORT_KEYWORD} function isOutsideWorkspacePath(path: string): boolean {
6227
6297
  const [pathWithoutQuery] = path.split('?')
6228
6298
  if (pathWithoutQuery === undefined) return false
6229
- const candidate = pathWithoutQuery.startsWith('/@fs/')
6230
- ? pathWithoutQuery.slice('/@fs/'.length)
6231
- : pathWithoutQuery
6232
- return isAbsolute(candidate)
6299
+ return isAbsolute(fileSystemPath(pathWithoutQuery))
6233
6300
  }
6234
6301
 
6235
6302
  ${EXPORT_KEYWORD} function containedPath(root: string, target: string): boolean {
@@ -6279,7 +6346,7 @@ ${EXPORT_KEYWORD} function browserServerPath(
6279
6346
  try {
6280
6347
  const decoded = decodeURIComponent(pathname)
6281
6348
  if (decoded.startsWith('/@fs/')) {
6282
- const candidate = decoded.slice('/@fs/'.length)
6349
+ const candidate = fileSystemPath(decoded)
6283
6350
  if (candidate.length === 0) return null
6284
6351
  return physicalPath(candidate)
6285
6352
  }
@@ -6298,8 +6365,13 @@ ${EXPORT_KEYWORD} function browserServerPath(
6298
6365
  return undefined
6299
6366
  }
6300
6367
  if (/^\\/@(?:app|src)\\//.test(decoded)) return null
6368
+ // Vite owns the app root request, while Vitest owns its in-memory tester root request.
6369
+ if (decoded === '/') return undefined
6301
6370
  if (!decoded.startsWith('/')) return null
6302
- return physicalPath(resolvePath(root, decoded.slice(1)))
6371
+ const candidate = physicalPath(resolvePath(root, decoded.slice(1)))
6372
+ if (existsSync(candidate) || !existsSync(decoded)) return candidate
6373
+ // An absolute module URL denotes itself; browserServerRoots still bounds it.
6374
+ return physicalPath(decoded)
6303
6375
  } catch {
6304
6376
  return null
6305
6377
  }
@@ -6800,6 +6872,12 @@ ${EXPORT_KEYWORD} function maskIgnoredHtml(environmentKeys: ReadonlySet<string>,
6800
6872
  )
6801
6873
  }
6802
6874
 
6875
+ ${EXPORT_KEYWORD} function isBrowserHtmlEntry(filename: string): boolean {
6876
+ return (
6877
+ physicalPath(filename) === physicalPath(resolvePath(WORKSPACE_ROOT, 'app/browser/index.html'))
6878
+ )
6879
+ }
6880
+
6803
6881
  ${EXPORT_KEYWORD} function prepareHtml(): Plugin {
6804
6882
  const environmentKeys = new Set<string>()
6805
6883
  return {
@@ -6815,7 +6893,10 @@ ${EXPORT_KEYWORD} function prepareHtml(): Plugin {
6815
6893
  },
6816
6894
  transformIndexHtml: {
6817
6895
  order: 'pre',
6818
- handler: maskIgnoredHtml.bind(undefined, environmentKeys),
6896
+ handler(html, context) {
6897
+ if (!isBrowserHtmlEntry(context.filename)) return undefined
6898
+ return maskIgnoredHtml(environmentKeys, html)
6899
+ },
6819
6900
  },
6820
6901
  }
6821
6902
  }
@@ -6824,7 +6905,10 @@ ${EXPORT_KEYWORD} function restoreHtml(): Plugin {
6824
6905
  return {
6825
6906
  name: 'orkestrel-html-boundary-restore',
6826
6907
  enforce: 'pre',
6827
- transformIndexHtml: restoreIgnoredHtml,
6908
+ transformIndexHtml(html, context) {
6909
+ if (!isBrowserHtmlEntry(context.filename)) return undefined
6910
+ return restoreIgnoredHtml(html)
6911
+ },
6828
6912
  }
6829
6913
  }
6830
6914
 
@@ -6834,7 +6918,8 @@ ${EXPORT_KEYWORD} function finalizeHtml(): Plugin {
6834
6918
  enforce: 'post',
6835
6919
  transformIndexHtml: {
6836
6920
  order: 'post',
6837
- handler(html) {
6921
+ handler(html, context) {
6922
+ if (!isBrowserHtmlEntry(context.filename)) return undefined
6838
6923
  if (!html.includes(HTML_SECURITY_META)) {
6839
6924
  throw new Error(
6840
6925
  '[orkestrel-environment-boundary] Browser HTML must retain its security policy',
@@ -7251,11 +7336,28 @@ ${EXPORT_KEYWORD} ${CONST_KEYWORD} ENVIRONMENT_CSS = Object.freeze({
7251
7336
  },
7252
7337
  },
7253
7338
  } satisfies CSSOptions)
7339
+
7340
+ /** Prevent the Vitest browser mid-run "optimized dependencies changed, reloading" stall. */
7341
+ ${EXPORT_KEYWORD} ${CONST_KEYWORD} BROWSER_TEST_DEPENDENCIES = Object.freeze([
7342
+ '@vitest/browser/client',
7343
+ 'vitest/browser',
7344
+ 'vitest/internal/browser',
7345
+ 'vitest',
7346
+ ])
7254
7347
  ` : ""}${EXPORT_KEYWORD} ${CONST_KEYWORD} PACKAGE_MANIFEST_BYTES = 1_048_576
7255
7348
  ${EXPORT_KEYWORD} ${CONST_KEYWORD} ENVIRONMENT_MODULE_BYTES = 8_388_608
7256
7349
  ${environmentBoundary}`;
7257
7350
  }
7258
- /** Build the dedicated Node-only repository policy Vitest project. */
7351
+ /**
7352
+ * Build the dedicated standalone Node-only repository-policy Vitest project.
7353
+ *
7354
+ * @returns The emitted `policy` project definition.
7355
+ *
7356
+ * @example
7357
+ * ```ts
7358
+ * policyViteProject().includes("label: 'policy'") // true
7359
+ * ```
7360
+ */
7259
7361
  function policyViteProject() {
7260
7362
  return `${EXPORT_KEYWORD} const policy = (config?: UserConfig): UserConfig =>
7261
7363
  mergeConfig(
@@ -7274,12 +7376,150 @@ function policyViteProject() {
7274
7376
  `;
7275
7377
  }
7276
7378
  /**
7379
+ * Build the standalone Node-only guide-parity Vitest project.
7380
+ *
7381
+ * @returns The emitted `guides` project definition.
7382
+ *
7383
+ * @example
7384
+ * ```ts
7385
+ * guidesViteProject().includes("label: 'guides'") // true
7386
+ * ```
7387
+ */
7388
+ function guidesViteProject() {
7389
+ return `${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
7390
+ mergeConfig(
7391
+ {
7392
+ resolve,
7393
+ test: {
7394
+ name: { label: 'guides', color: 'green' },
7395
+ include: ['tests/guides/**/*.test.ts'],
7396
+ exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],
7397
+ setupFiles: ['./tests/setup.ts'],
7398
+ environment: 'node',
7399
+ browser: { enabled: false },
7400
+ },
7401
+ },
7402
+ config ?? {},
7403
+ )
7404
+ `;
7405
+ }
7406
+ /**
7407
+ * Build the executable's dedicated Node-only build and test project.
7408
+ *
7409
+ * @returns The emitted `srcBin` project definition.
7410
+ *
7411
+ * @example
7412
+ * ```ts
7413
+ * binViteProject().includes("label: 'src:bin'") // true
7414
+ * ```
7415
+ */
7416
+ function binViteProject() {
7417
+ return `${EXPORT_KEYWORD} const srcBin = (config?: UserConfig): UserConfig =>
7418
+ mergeConfig(
7419
+ {
7420
+ resolve,
7421
+ publicDir: false,
7422
+ plugins: [outputBoundary('dist/bin')],
7423
+ build: {
7424
+ emptyOutDir: true,
7425
+ sourcemap: true,
7426
+ minify: false,
7427
+ lib: {
7428
+ entry: resolveWorkspacePath('src/bin/scaffold.ts'),
7429
+ formats: ['es'],
7430
+ fileName: () => 'scaffold.js',
7431
+ },
7432
+ outDir: 'dist/bin',
7433
+ target: 'node22',
7434
+ rolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },
7435
+ },
7436
+ test: {
7437
+ name: { label: 'src:bin', color: 'yellow' },
7438
+ include: ['tests/src/bin/**/*.test.ts'],
7439
+ setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
7440
+ environment: 'node',
7441
+ browser: { enabled: false },
7442
+ },
7443
+ },
7444
+ config ?? {},
7445
+ )
7446
+ `;
7447
+ }
7448
+ /**
7449
+ * Build the standalone Node-only installed-consumer integration proof project.
7450
+ *
7451
+ * @param axes - Optional executable and integration axes controlling the shared registry setup.
7452
+ * @returns The emitted `integration` project definition.
7453
+ *
7454
+ * @example
7455
+ * ```ts
7456
+ * integrationViteProject({ bin: true, integration: true }).includes(
7457
+ * "globalSetup: ['./tests/setupIntegration.ts']",
7458
+ * ) // true
7459
+ * ```
7460
+ */
7461
+ function integrationViteProject(axes = {}) {
7462
+ return `${EXPORT_KEYWORD} const integration = (config?: UserConfig): UserConfig =>
7463
+ mergeConfig(
7464
+ {
7465
+ resolve,
7466
+ test: {
7467
+ name: { label: 'integration', color: 'blue' },
7468
+ include: ['tests/integration/**/*.test.ts'],
7469
+ setupFiles: ['./tests/setup.ts'],
7470
+ ${axes.bin === true && axes.integration === true ? ` // Wire the template registry for the generated-consumer proof.
7471
+ globalSetup: ['./tests/setupIntegration.ts'],
7472
+ ` : ""} environment: 'node',
7473
+ browser: { enabled: false },
7474
+ testTimeout: 120_000,
7475
+ hookTimeout: 120_000,
7476
+ fileParallelism: false,
7477
+ },
7478
+ },
7479
+ config ?? {},
7480
+ )
7481
+ `;
7482
+ }
7483
+ /**
7484
+ * Build the standalone Node-only live-service proof project.
7485
+ *
7486
+ * @returns The emitted `service` project definition.
7487
+ *
7488
+ * @example
7489
+ * ```ts
7490
+ * serviceViteProject().includes("label: 'service'") // true
7491
+ * ```
7492
+ */
7493
+ function serviceViteProject() {
7494
+ return `${EXPORT_KEYWORD} const service = (config?: UserConfig): UserConfig =>
7495
+ mergeConfig(
7496
+ {
7497
+ resolve,
7498
+ test: {
7499
+ name: { label: 'service', color: 'red' },
7500
+ include: ['tests/service/**/*.test.ts'],
7501
+ setupFiles: ['./tests/setup.ts', './tests/setupService.ts'],
7502
+ environment: 'node',
7503
+ browser: { enabled: false },
7504
+ testTimeout: 120_000,
7505
+ hookTimeout: 120_000,
7506
+ fileParallelism: false,
7507
+ },
7508
+ },
7509
+ config ?? {},
7510
+ )
7511
+ `;
7512
+ }
7513
+ /**
7277
7514
  * The single non-`core` environment's factory IS the base (Shape 3 of
7278
7515
  * `rootViteConfig`) — the environment's own `viteHeader` (Playwright only when
7279
7516
  * `environment === 'browser'`, per the live sqlite/indexeddb exemplars) prefixes
7280
- * the environment-specific `srcBrowser` / `srcServer` + `guides` projects export.
7517
+ * the environment-specific `srcBrowser` / `srcServer` project, followed by the
7518
+ * standalone policy and guides proof projects and any selected structural-axis
7519
+ * projects.
7281
7520
  *
7282
7521
  * @param environment - The sole declared non-`core` environment.
7522
+ * @param axes - Optional executable, integration, and service project axes.
7283
7523
  * @returns The root `vite.config.ts` file content for a single non-`core` environment, newline-terminated.
7284
7524
  *
7285
7525
  * @example
@@ -7287,9 +7527,11 @@ function policyViteProject() {
7287
7527
  * singleSrcViteConfig('server').includes('srcServer') // true
7288
7528
  * ```
7289
7529
  */
7290
- function singleSrcViteConfig(environment) {
7530
+ function singleSrcViteConfig(environment, axes = {}) {
7291
7531
  const machinery = viteMachinery([environment]);
7292
7532
  const header = viteHeader(machinery);
7533
+ const renderedTest = renderViteTest(viteProjectRegistrations([environment], [], axes), machinery.browser);
7534
+ const definitions = viteProjectDefinitions(axes);
7293
7535
  if (environment === "browser") return `${header}
7294
7536
  ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7295
7537
  mergeConfig(
@@ -7317,6 +7559,18 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7317
7559
  name: { label: 'src:browser', color: 'yellow' },
7318
7560
  include: ['tests/src/browser/**/*.test.ts'],
7319
7561
  setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
7562
+ ...(config?.test?.browser?.enabled === false
7563
+ ? {}
7564
+ : {
7565
+ deps: {
7566
+ optimizer: {
7567
+ client: {
7568
+ enabled: true,
7569
+ include: [...BROWSER_TEST_DEPENDENCIES],
7570
+ },
7571
+ },
7572
+ },
7573
+ }),
7320
7574
  browser: {
7321
7575
  enabled: true,
7322
7576
  provider: playwright(),
@@ -7328,34 +7582,10 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7328
7582
  config ?? {},
7329
7583
  )
7330
7584
 
7331
- ${policyViteProject()}
7332
- ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
7333
- srcBrowser(
7334
- mergeConfig(
7335
- {
7336
- test: {
7337
- name: { label: 'guides', color: 'green' },
7338
- include: ['tests/guides/**/*.test.ts'],
7339
- exclude: ['tests/src/**/*.test.ts', 'tests/setup.test.ts'],
7340
- environment: 'node',
7341
- browser: { enabled: false },
7342
- },
7343
- },
7344
- config ?? {},
7345
- ),
7346
- )
7347
-
7585
+ ${definitions}
7348
7586
  export default defineConfig({
7349
7587
  resolve,
7350
- test: gateBrowserProjects(
7351
- [
7352
- { project: srcBrowser, browser: 'src:browser' },
7353
- { project: policy },
7354
- { project: guides },
7355
- ],
7356
- hasChromium,
7357
- process.argv,
7358
- ),
7588
+ ${renderedTest}
7359
7589
  })
7360
7590
  `;
7361
7591
  return `${header}
@@ -7391,33 +7621,18 @@ ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7391
7621
  config ?? {},
7392
7622
  )
7393
7623
 
7394
- ${policyViteProject()}
7395
- ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
7396
- srcServer(
7397
- mergeConfig(
7398
- {
7399
- test: {
7400
- name: { label: 'guides', color: 'green' },
7401
- include: ['tests/guides/**/*.test.ts'],
7402
- exclude: ['tests/src/**/*.test.ts', 'tests/setup.test.ts'],
7403
- },
7404
- },
7405
- config ?? {},
7406
- ),
7407
- )
7408
-
7624
+ ${definitions}
7409
7625
  export default defineConfig({
7410
7626
  resolve,
7411
- test: {
7412
- projects: [srcServer, policy, guides],
7413
- },
7627
+ ${renderedTest}
7414
7628
  })
7415
7629
  `;
7416
7630
  }
7417
7631
  /**
7418
7632
  * The root `vite.config.ts` — three grounded shapes, chosen by a blueprint's
7419
7633
  * `src`:
7420
- * 1. `core`-only — `srcCore` + `guides`, no Playwright at all (the live
7634
+ * 1. `core`-only — `srcCore` + standalone policy/guides proof projects, no
7635
+ * Playwright at all (the live
7421
7636
  * timeout exemplar: no browser project exists anywhere in the file).
7422
7637
  * 2. Multi-environment (2+ src, always including `core` per the live
7423
7638
  * middleware/router exemplars) — `srcCore` is the shared base;
@@ -7432,10 +7647,9 @@ export default defineConfig({
7432
7647
  * environment is `browser` (it must run its own tests in a real browser).
7433
7648
  *
7434
7649
  * @param src - The declared `Environment[]`.
7435
- * @param engine - Structural: `true` appends the `srcBin` project (an
7436
- * executable build target, never a barrel) after the other declared
7437
- * projects the self-hosting tax, grounded against this very repo's own
7438
- * checked-in `vite.config.ts`.
7650
+ * @param axes - Optional structural project axes. `bin` appends the standalone
7651
+ * executable build-and-test project; `integration` and `service` append their
7652
+ * standalone proof projects.
7439
7653
  * @returns The root `vite.config.ts` file content, newline-terminated.
7440
7654
  *
7441
7655
  * @example
@@ -7443,14 +7657,14 @@ export default defineConfig({
7443
7657
  * rootViteConfig(['core']).includes('srcCore') // true
7444
7658
  * ```
7445
7659
  */
7446
- function rootViteConfig(src, engine = false) {
7660
+ function rootViteConfig(src, axes = {}) {
7447
7661
  const hasCore = src.includes("core");
7448
- const nonCore = src.filter((environment) => environment !== "core");
7662
+ const nonCore = ENVIRONMENTS.filter((environment) => environment !== "core" && src.includes(environment));
7449
7663
  const machinery = viteMachinery(src);
7450
7664
  const header = viteHeader(machinery);
7451
7665
  if (!hasCore) {
7452
7666
  const [onlyEnvironment] = nonCore;
7453
- if (onlyEnvironment === "browser" || onlyEnvironment === "server") return singleSrcViteConfig(onlyEnvironment);
7667
+ if (onlyEnvironment === "browser" || onlyEnvironment === "server") return singleSrcViteConfig(onlyEnvironment, axes);
7454
7668
  }
7455
7669
  const browserBlock = `
7456
7670
  ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
@@ -7478,6 +7692,18 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7478
7692
  include: ['tests/src/browser/**/*.test.ts'],
7479
7693
  exclude: ['tests/src/core/**/*.test.ts'],
7480
7694
  setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
7695
+ ...(config?.test?.browser?.enabled === false
7696
+ ? {}
7697
+ : {
7698
+ deps: {
7699
+ optimizer: {
7700
+ client: {
7701
+ enabled: true,
7702
+ include: [...BROWSER_TEST_DEPENDENCIES],
7703
+ },
7704
+ },
7705
+ },
7706
+ }),
7481
7707
  browser: {
7482
7708
  enabled: true,
7483
7709
  provider: playwright(),
@@ -7532,60 +7758,8 @@ ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7532
7758
  ),
7533
7759
  )
7534
7760
  `;
7535
- const binBlock = engine ? `
7536
- ${EXPORT_KEYWORD} const srcBin = (config?: UserConfig): UserConfig =>
7537
- srcCore(
7538
- mergeConfig(
7539
- {
7540
- publicDir: false,
7541
- plugins: [outputBoundary('dist/bin')],
7542
- build: {
7543
- lib: {
7544
- entry: resolveWorkspacePath('src/bin/scaffold.ts'),
7545
- formats: ['es'],
7546
- fileName: () => 'scaffold.js',
7547
- },
7548
- outDir: 'dist/bin',
7549
- target: 'node22',
7550
- rolldownOptions: {
7551
- external: [/^node:/, /^@orkestrel\\//, /^@src\\//],
7552
- },
7553
- },
7554
- test: {
7555
- name: { label: 'src:bin', color: 'yellow' },
7556
- include: ['tests/src/bin/**/*.test.ts'],
7557
- exclude: ['tests/src/core/**/*.test.ts', 'tests/src/server/**/*.test.ts'],
7558
- setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
7559
- },
7560
- },
7561
- config ?? {},
7562
- ),
7563
- )
7564
-
7565
- ${EXPORT_KEYWORD} const integration = (config?: UserConfig): UserConfig =>
7566
- srcBin(
7567
- mergeConfig(
7568
- {
7569
- test: {
7570
- name: { label: 'integration', color: 'blue' },
7571
- include: ['tests/integration/**/*.test.ts'],
7572
- exclude: ['tests/src/**/*.test.ts', 'tests/guides/**/*.test.ts'],
7573
- },
7574
- },
7575
- config ?? {},
7576
- ),
7577
- )
7578
- ` : "";
7579
- const blocks = nonCore.map((environment) => environment === "browser" ? browserBlock : serverBlock).join("") + binBlock;
7580
- const registrations = [];
7581
- if (hasCore) registrations.push({ project: "srcCore" });
7582
- for (const environment of nonCore) registrations.push(environment === "browser" ? {
7583
- project: "srcBrowser",
7584
- browser: SRC_MATRIX.browser.project
7585
- } : { project: "srcServer" });
7586
- registrations.push({ project: "policy" }, { project: "guides" });
7587
- if (engine) registrations.push({ project: "srcBin" }, { project: "integration" });
7588
- const renderedTest = renderViteTest(registrations, machinery.browser);
7761
+ const blocks = nonCore.map((environment) => environment === "browser" ? browserBlock : serverBlock).join("");
7762
+ const renderedTest = renderViteTest(viteProjectRegistrations(src, [], axes), machinery.browser);
7589
7763
  return `${header}
7590
7764
  ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
7591
7765
  mergeConfig(
@@ -7607,22 +7781,8 @@ ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
7607
7781
  },
7608
7782
  config ?? {},
7609
7783
  )
7610
-
7611
- ${policyViteProject()}
7612
- ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
7613
- srcCore(
7614
- mergeConfig(
7615
- {
7616
- test: {
7617
- name: { label: 'guides', color: 'green' },
7618
- include: ['tests/guides/**/*.test.ts'],
7619
- exclude: ['tests/src/**/*.test.ts', 'tests/setup.test.ts'],
7620
- },
7621
- },
7622
- config ?? {},
7623
- ),
7624
- )
7625
7784
  ${blocks}
7785
+ ${viteProjectDefinitions(axes)}
7626
7786
  export default defineConfig({
7627
7787
  resolve,
7628
7788
  ${renderedTest}
@@ -7635,7 +7795,7 @@ ${renderedTest}
7635
7795
  *
7636
7796
  * @param src - Published src environments.
7637
7797
  * @param app - Private app environments.
7638
- * @param engine - Whether the workspace also builds scaffold's executable.
7798
+ * @param axes - Optional executable, integration, and service project axes.
7639
7799
  * @returns The root `vite.config.ts` content.
7640
7800
  *
7641
7801
  * @example
@@ -7643,15 +7803,12 @@ ${renderedTest}
7643
7803
  * applicationViteConfig([], ['core', 'server']).includes('appServer') // true
7644
7804
  * ```
7645
7805
  */
7646
- function applicationViteConfig(src, app, engine = false) {
7806
+ function applicationViteConfig(src, app, axes = {}) {
7647
7807
  const hasSourceCore = src.includes("core");
7648
- const machinery = viteMachinery(src, app, engine);
7808
+ const machinery = viteMachinery(src, app, axes.bin === true);
7649
7809
  const header = viteHeader(machinery);
7650
- const registrations = [];
7651
7810
  const blocks = [];
7652
- if (src.includes("core")) {
7653
- registrations.push({ project: "srcCore" });
7654
- blocks.push(`
7811
+ if (src.includes("core")) blocks.push(`
7655
7812
  ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
7656
7813
  mergeConfig(
7657
7814
  {
@@ -7670,12 +7827,7 @@ ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
7670
7827
  config ?? {},
7671
7828
  )
7672
7829
  `);
7673
- }
7674
7830
  if (src.includes("browser")) {
7675
- registrations.push({
7676
- project: "srcBrowser",
7677
- browser: SRC_MATRIX.browser.project
7678
- });
7679
7831
  const coreOutput = hasSourceCore ? `
7680
7832
  output: { paths: { '@src/core': '../core/index.js' } },` : "";
7681
7833
  const coreExternal = hasSourceCore ? `id === '@src/core' || ` : "";
@@ -7706,6 +7858,18 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7706
7858
  name: { label: 'src:browser', color: 'yellow' },
7707
7859
  include: ['tests/src/browser/**/*.test.ts'],
7708
7860
  ${hasSourceCore ? "exclude: ['tests/src/core/**/*.test.ts'],\n " : ""}setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
7861
+ ...(config?.test?.browser?.enabled === false
7862
+ ? {}
7863
+ : {
7864
+ deps: {
7865
+ optimizer: {
7866
+ client: {
7867
+ enabled: true,
7868
+ include: [...BROWSER_TEST_DEPENDENCIES],
7869
+ },
7870
+ },
7871
+ },
7872
+ }),
7709
7873
  browser: {
7710
7874
  enabled: true,
7711
7875
  provider: playwright(),
@@ -7719,7 +7883,6 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7719
7883
  `);
7720
7884
  }
7721
7885
  if (src.includes("server")) {
7722
- registrations.push({ project: "srcServer" });
7723
7886
  const coreOutput = hasSourceCore ? `
7724
7887
  output: [
7725
7888
  {
@@ -7769,9 +7932,7 @@ ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
7769
7932
  )
7770
7933
  `);
7771
7934
  }
7772
- if (app.includes("core")) {
7773
- registrations.push({ project: "appCore" });
7774
- blocks.push(`
7935
+ if (app.includes("core")) blocks.push(`
7775
7936
  ${EXPORT_KEYWORD} const appCore = (config?: UserConfig): UserConfig =>
7776
7937
  mergeConfig(
7777
7938
  {
@@ -7789,13 +7950,7 @@ ${EXPORT_KEYWORD} const appCore = (config?: UserConfig): UserConfig =>
7789
7950
  config ?? {},
7790
7951
  )
7791
7952
  `);
7792
- }
7793
- if (app.includes("browser")) {
7794
- registrations.push({
7795
- project: "appBrowser",
7796
- browser: APP_MATRIX.browser.project
7797
- });
7798
- blocks.push(`
7953
+ if (app.includes("browser")) blocks.push(`
7799
7954
  ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
7800
7955
  if (config.length > 0) {
7801
7956
  throw new Error(
@@ -7814,7 +7969,6 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
7814
7969
  prepareHtml(),
7815
7970
  finalizeHtml(),
7816
7971
  ],
7817
- optimizeDeps: { include: ['vue'] },
7818
7972
  root: resolveWorkspacePath('app/browser'),
7819
7973
  publicDir: false,
7820
7974
  server: {
@@ -7837,6 +7991,14 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
7837
7991
  dir: resolveWorkspacePath('.'),
7838
7992
  include: ['tests/app/browser/**/*.test.ts'],
7839
7993
  setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
7994
+ deps: {
7995
+ optimizer: {
7996
+ client: {
7997
+ enabled: true,
7998
+ include: ['vue', ...BROWSER_TEST_DEPENDENCIES],
7999
+ },
8000
+ },
8001
+ },
7840
8002
  browser: {
7841
8003
  enabled: true,
7842
8004
  provider: playwright(),
@@ -7847,10 +8009,7 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
7847
8009
  }
7848
8010
  }
7849
8011
  `);
7850
- }
7851
- if (app.includes("server")) {
7852
- registrations.push({ project: "appServer" });
7853
- blocks.push(`
8012
+ if (app.includes("server")) blocks.push(`
7854
8013
  ${EXPORT_KEYWORD} const appServer = (config?: UserConfig): UserConfig =>
7855
8014
  mergeConfig(
7856
8015
  {
@@ -7881,72 +8040,10 @@ ${EXPORT_KEYWORD} const appServer = (config?: UserConfig): UserConfig =>
7881
8040
  config ?? {},
7882
8041
  )
7883
8042
  `);
7884
- }
7885
- if (engine) {
7886
- registrations.push({ project: "srcBin" }, { project: "integration" });
7887
- blocks.push(`
7888
- ${EXPORT_KEYWORD} const srcBin = (config?: UserConfig): UserConfig =>
7889
- mergeConfig(
7890
- {
7891
- resolve,
7892
- publicDir: false,
7893
- plugins: [outputBoundary('dist/bin')],
7894
- build: {
7895
- lib: {
7896
- entry: resolveWorkspacePath('src/bin/scaffold.ts'),
7897
- formats: ['es'],
7898
- fileName: () => 'scaffold.js',
7899
- },
7900
- outDir: 'dist/bin',
7901
- target: 'node22',
7902
- rolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },
7903
- },
7904
- test: {
7905
- name: { label: 'src:bin', color: 'yellow' },
7906
- include: ['tests/src/bin/**/*.test.ts'],
7907
- setupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],
7908
- environment: 'node',
7909
- browser: { enabled: false },
7910
- },
7911
- },
7912
- config ?? {},
7913
- )
7914
-
7915
- ${EXPORT_KEYWORD} const integration = (config?: UserConfig): UserConfig =>
7916
- srcBin(
7917
- mergeConfig(
7918
- {
7919
- test: {
7920
- name: { label: 'integration', color: 'blue' },
7921
- include: ['tests/integration/**/*.test.ts'],
7922
- exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/guides/**/*.test.ts'],
7923
- },
7924
- },
7925
- config ?? {},
7926
- ),
7927
- )
7928
- `);
7929
- }
7930
- registrations.push({ project: "policy" }, { project: "guides" });
7931
- const renderedTest = renderViteTest(registrations, machinery.browser);
7932
- return `${header}
7933
- ${policyViteProject()}
7934
- ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
7935
- mergeConfig(
7936
- {
7937
- resolve,
7938
- test: {
7939
- name: { label: 'guides', color: 'green' },
7940
- include: ['tests/guides/**/*.test.ts'],
7941
- exclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],
7942
- setupFiles: ['./tests/setup.ts'],
7943
- environment: 'node',
7944
- browser: { enabled: false },
7945
- },
7946
- },
7947
- config ?? {},
7948
- )
7949
- ${blocks.join("")}
8043
+ const renderedTest = renderViteTest(viteProjectRegistrations(src, app, axes), machinery.browser);
8044
+ const definitions = viteProjectDefinitions(axes);
8045
+ return `${header}${blocks.join("")}
8046
+ ${definitions}
7950
8047
  export default defineConfig({
7951
8048
  resolve,
7952
8049
  ${renderedTest}
@@ -8100,6 +8197,67 @@ export default defineConfig(
8100
8197
  `;
8101
8198
  }
8102
8199
  /**
8200
+ * Build the executable's declaration-only `configs/src/tsconfig.bin.json`.
8201
+ *
8202
+ * @returns The executable `tsconfig` file content, newline-terminated.
8203
+ *
8204
+ * @example
8205
+ * ```ts
8206
+ * binTsconfig().includes('"outDir": "../../dist/bin"') // true
8207
+ * ```
8208
+ */
8209
+ function binTsconfig() {
8210
+ return formatJson({
8211
+ extends: "../../tsconfig.json",
8212
+ compilerOptions: {
8213
+ lib: ["ESNext"],
8214
+ types: ["node"],
8215
+ noEmit: false,
8216
+ declaration: true,
8217
+ emitDeclarationOnly: true,
8218
+ rootDir: "../../src",
8219
+ outDir: "../../dist/bin"
8220
+ },
8221
+ include: TYPESCRIPT_EXTENSIONS.map((extension) => `../../src/bin/**/*.${extension}`)
8222
+ });
8223
+ }
8224
+ /**
8225
+ * Build the executable's `configs/src/vite.bin.config.ts` wrapper.
8226
+ *
8227
+ * @returns The executable Vite configuration content, newline-terminated.
8228
+ *
8229
+ * @example
8230
+ * ```ts
8231
+ * binViteConfig().includes("banner: '#!/usr/bin/env node'") // true
8232
+ * ```
8233
+ */
8234
+ function binViteConfig() {
8235
+ return `import { defineConfig } from 'vite'
8236
+ import { srcBin } from '../../vite.config'
8237
+
8238
+ // The \`scaffold\` executable build — a single ESM lib file, no declarations (an
8239
+ // executable ships no types), with the \`#!/usr/bin/env node\` shebang re-emitted via
8240
+ // \`output.banner\` (rolldown strips shebangs from source during bundling), and
8241
+ // \`output.paths\` rewriting the externalized \`@src/*\` specifiers to the built sibling
8242
+ // src environments (relative to \`dist/bin/\`), so the emitted bin resolves at runtime.
8243
+ export default defineConfig(
8244
+ srcBin({
8245
+ build: {
8246
+ rolldownOptions: {
8247
+ output: {
8248
+ banner: '#!/usr/bin/env node',
8249
+ paths: {
8250
+ '@src/core': '../src/core/index.js',
8251
+ '@src/server': '../src/server/index.js',
8252
+ },
8253
+ },
8254
+ },
8255
+ },
8256
+ }),
8257
+ )
8258
+ `;
8259
+ }
8260
+ /**
8103
8261
  * Build one `configs/app/tsconfig.<environment>.json` check-only configuration.
8104
8262
  *
8105
8263
  * @param environment - The application environment.
@@ -8148,12 +8306,25 @@ export default defineConfig(${anchor}())
8148
8306
  `;
8149
8307
  }
8150
8308
  /**
8151
- * Build selection-aware GitHub CI without external service dependencies.
8309
+ * Build selection-aware GitHub CI, provisioning the declared foreign service before its proof.
8152
8310
  *
8153
8311
  * @param spec - The workspace blueprint.
8154
8312
  * @returns The complete `.github/workflows/ci.yml` content.
8155
8313
  */
8156
8314
  function ciWorkflow(spec) {
8315
+ const browser = spec.bin || spec.src.includes("browser") || spec.app.includes("browser") ? `
8316
+ - name: Install Playwright browsers
8317
+ run: npx --no-install playwright install --with-deps chromium
8318
+ ` : "";
8319
+ const tail = [];
8320
+ if (spec.integration) tail.push(` - name: Run live consumer integration
8321
+ run: npm run test:integration`);
8322
+ if (spec.service) {
8323
+ tail.push(` - name: Provision live service
8324
+ run: bash ${SERVICE_SCRIPT_PATH}`);
8325
+ tail.push(` - name: Run live service tests
8326
+ run: npm run test:service`);
8327
+ }
8157
8328
  return `name: ci.yml
8158
8329
 
8159
8330
  on:
@@ -8185,10 +8356,7 @@ jobs:
8185
8356
 
8186
8357
  - name: Install dependencies
8187
8358
  run: npm ci --ignore-scripts
8188
- ${spec.engine || spec.src.includes("browser") || spec.app.includes("browser") ? `
8189
- - name: Install Playwright browsers
8190
- run: npx --no-install playwright install --with-deps chromium
8191
- ` : ""}
8359
+ ${browser}
8192
8360
  - name: Check formatting
8193
8361
  run: npm run format:check
8194
8362
 
@@ -8202,11 +8370,7 @@ ${spec.engine || spec.src.includes("browser") || spec.app.includes("browser") ?
8202
8370
  run: npm run build
8203
8371
 
8204
8372
  - name: Run tests
8205
- run: npm test${spec.engine ? `
8206
-
8207
- - name: Run live consumer integration
8208
- run: npm run test:integration
8209
- ` : ""}
8373
+ run: npm test${tail.length === 0 ? "" : `\n\n${tail.join("\n\n")}`}
8210
8374
  `;
8211
8375
  }
8212
8376
  /**
@@ -8224,7 +8388,7 @@ ${spec.engine || spec.src.includes("browser") || spec.app.includes("browser") ?
8224
8388
  * ```
8225
8389
  */
8226
8390
  function configArtifacts(spec) {
8227
- const machinery = viteMachinery(spec.src, spec.app, spec.engine);
8391
+ const machinery = viteMachinery(spec.src, spec.app, spec.bin);
8228
8392
  const artifacts = [{
8229
8393
  path: "tsconfig.json",
8230
8394
  group: "configs",
@@ -8234,7 +8398,7 @@ function configArtifacts(spec) {
8234
8398
  path: "vite.config.ts",
8235
8399
  group: "configs",
8236
8400
  origin: "computed",
8237
- content: spec.app.length > 0 ? applicationViteConfig(spec.src, spec.app, spec.engine) : rootViteConfig(spec.src, spec.engine)
8401
+ content: spec.app.length > 0 ? applicationViteConfig(spec.src, spec.app, spec) : rootViteConfig(spec.src, spec)
8238
8402
  }];
8239
8403
  for (const environment of spec.src) {
8240
8404
  const row = SRC_MATRIX[environment];
@@ -8250,6 +8414,12 @@ function configArtifacts(spec) {
8250
8414
  });
8251
8415
  }
8252
8416
  }
8417
+ if (spec.bin) for (const path of BIN_CONFIGS) artifacts.push({
8418
+ path,
8419
+ group: "configs",
8420
+ origin: "computed",
8421
+ content: path.endsWith(".json") ? binTsconfig() : binViteConfig()
8422
+ });
8253
8423
  for (const environment of spec.app) {
8254
8424
  const row = APP_MATRIX[environment];
8255
8425
  for (const path of row.configs) {
@@ -9395,6 +9565,6 @@ function createBlueprint(data) {
9395
9565
  return candidate;
9396
9566
  }
9397
9567
  //#endregion
9398
- export { APP_BROWSER_DEV_DEPENDENCIES, APP_MATRIX, BASE_DEV_DEPENDENCIES, CATEGORIES, CHECKOUT_ACTION_SHA, COMPILER_ID, COMPILE_STAGES, CONST_KEYWORD, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXPORT_KEYWORD, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, FRESHNESS, FUNCTION_KEYWORD, GROUPS, HEX_PATTERN, HOST_PATHS, IMPORT_KEYWORD, INVALID_PATH_CHARACTER_PATTERN, JSON_PRINT_WIDTH, JSON_TAB_WIDTH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_COLLECTION_ITEMS, MAX_DATA_GRAPH_KEYS, MAX_DATA_GRAPH_NODES, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_SERIALIZED_INPUT_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORIGINS, ORKESTREL_RANGE_PATTERN, PlanManager, SCAFFOLD_RANGE, SETUP_NODE_ACTION_SHA, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, SYNC_BASELINE_PATTERN, ScaffoldError, TEMPLATES, TYPESCRIPT_EXTENSIONS, VERSION_PATTERN, alignTable, appTsconfig, appViteConfig, applicationArtifacts, applicationViteConfig, applyOverrides, artifactShape, auditToReview, blueprint, blueprintShape, blueprintToMembers, blueprintToPlan, bytesToHex, catalogNames, catalogToBlock, ciWorkflow, compareCodeUnit, computeColumnWidth, computeHash, configArtifacts, contentByteLength, contentCodePoint, contentToBytes, contentToHex, coreTsconfig, coreViteConfig, createBlueprint, createCompiler, createPlanManager, delimiterCell, dependency, dependencyShape, devDependenciesFor, diffPlan, dualCondition, entryFields, escapeHtmlText, exportsMap, fillArtifact, findFileConflict, findPathConflict, formatJson, guideArtifacts, guideMemberTable, guideMethods, guideTests, guideUsage, hasBlueprintEnvironment, hasOnlyDataProperties, hasValidArtifactBytes, hasValidArtifactHex, hasValidAuditBytes, hasValidBlueprintBytes, hasValidOverrideBytes, hasValidPlanBytes, hasValidPlanHex, hasValidSnapshotBytes, hasValidSyncReportBytes, hostGroup, inferGroup, isArtifact, isBehind, isBlueprint, isCompilerEventHooks, isDenseDataArray, isDependency, isEmitterErrorHandler, isMember, isOverride, isPlan, isPlanManagerEventHooks, isScaffoldError, isSyncReport, isWorkspaceName, manifestToDependencies, manifestToName, member, memberShape, override, overrideShape, ownDataValue, packageManifest, padCell, paritySpecifiers, parseBlueprint, parseBoundedJSON, parseCompilerOptions, parsePlan, parsePlanIds, parsePlanManagerOptions, parseSyncReport, pascalCase, pinPlan, planPayload, planShape, planToReview, planToSummary, policyViteProject, rangeToFreshness, renderArray, renderObject, renderValue, renderViteTest, rootTsconfig, rootViteConfig, selectHostPaths, serializeTypeScriptString, singleSrcViteConfig, snapshotOf, snapshotPlan, sourceArtifacts, splitTableRow, srcTsconfig, srcVariant, srcViteConfig, stableStringify, syncReportShape, syncToReview, testArtifacts, validateBlueprint, validateDependencyArray, validatePlan, viteHeader, viteMachinery };
9568
+ export { APP_BROWSER_DEV_DEPENDENCIES, APP_MATRIX, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, CATEGORIES, CHECKOUT_ACTION_SHA, COMPILER_ID, COMPILE_STAGES, CONST_KEYWORD, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXPORT_KEYWORD, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, FRESHNESS, FUNCTION_KEYWORD, GROUPS, HEX_PATTERN, HOST_PATHS, IMPORT_KEYWORD, INVALID_PATH_CHARACTER_PATTERN, JSON_PRINT_WIDTH, JSON_TAB_WIDTH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_COLLECTION_ITEMS, MAX_DATA_GRAPH_KEYS, MAX_DATA_GRAPH_NODES, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_SERIALIZED_INPUT_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORIGINS, ORKESTREL_RANGE_PATTERN, PlanManager, SCAFFOLD_RANGE, SERVICE_SCRIPT_PATH, SETUP_NODE_ACTION_SHA, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, SYNC_BASELINE_PATTERN, ScaffoldError, TEMPLATES, TYPESCRIPT_EXTENSIONS, VERSION_PATTERN, alignTable, appTsconfig, appViteConfig, applicationArtifacts, applicationViteConfig, applyOverrides, artifactShape, auditToReview, binTsconfig, binViteConfig, binViteProject, blueprint, blueprintShape, blueprintToMembers, blueprintToPlan, bytesToHex, catalogNames, catalogToBlock, ciWorkflow, compareCodeUnit, computeColumnWidth, computeHash, configArtifacts, contentByteLength, contentCodePoint, contentToBytes, contentToHex, coreTsconfig, coreViteConfig, createBlueprint, createCompiler, createPlanManager, delimiterCell, dependency, dependencyShape, devDependenciesFor, diffPlan, dualCondition, entryFields, escapeHtmlText, exportsMap, fillArtifact, findFileConflict, findPathConflict, formatJson, guideArtifacts, guideMemberTable, guideMethods, guideTests, guideUsage, guidesViteProject, hasBlueprintEnvironment, hasOnlyDataProperties, hasValidArtifactBytes, hasValidArtifactHex, hasValidAuditBytes, hasValidBlueprintBytes, hasValidOverrideBytes, hasValidPlanBytes, hasValidPlanHex, hasValidSnapshotBytes, hasValidSyncReportBytes, hostGroup, inferGroup, integrationViteProject, isArtifact, isBehind, isBlueprint, isCompilerEventHooks, isDenseDataArray, isDependency, isEmitterErrorHandler, isMember, isOverride, isPlan, isPlanManagerEventHooks, isScaffoldError, isSyncReport, isWorkspaceName, manifestToDependencies, manifestToName, member, memberShape, override, overrideShape, ownDataValue, packageManifest, padCell, paritySpecifiers, parseBlueprint, parseBoundedJSON, parseCompilerOptions, parsePlan, parsePlanIds, parsePlanManagerOptions, parseSyncReport, pascalCase, pinPlan, planPayload, planShape, planToReview, planToSummary, policyViteProject, rangeToFreshness, renderArray, renderObject, renderValue, renderViteTest, rootTsconfig, rootViteConfig, selectHostPaths, serializeTypeScriptString, serviceViteProject, singleSrcViteConfig, snapshotOf, snapshotPlan, sourceArtifacts, splitTableRow, srcTsconfig, srcVariant, srcViteConfig, stableStringify, syncReportShape, syncToReview, testArtifacts, validateBlueprint, validateDependencyArray, validatePlan, viteHeader, viteMachinery, viteProjectDefinitions, viteProjectRegistrations };
9399
9569
 
9400
9570
  //# sourceMappingURL=index.js.map