@orkestrel/scaffold 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/scaffold.js +57 -22
- package/dist/bin/scaffold.js.map +1 -1
- package/dist/host/CLAUDE.md +64 -24
- package/dist/host/claude/rules/workspace.md +8 -8
- package/dist/host/guides/src/scaffold.md +178 -94
- package/dist/host/scripts/codex.sh +5 -0
- package/dist/host/tests/setupPolicy.ts +179 -4
- package/dist/src/core/index.cjs +289 -69
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +74 -13
- package/dist/src/core/index.d.ts +74 -13
- package/dist/src/core/index.js +287 -70
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +11 -5
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +4 -2
- package/dist/src/server/index.d.ts +4 -2
- package/dist/src/server/index.js +12 -6
- package/dist/src/server/index.js.map +1 -1
- package/package.json +12 -11
package/dist/src/core/index.cjs
CHANGED
|
@@ -104,9 +104,12 @@ var APP_MATRIX = Object.freeze({
|
|
|
104
104
|
* The root docs (`AGENTS.md` / `CLAUDE.md`), `LICENSE`, `.agents`, `.claude`, `.codex`,
|
|
105
105
|
* the four SessionStart hook scripts (`scripts/deps.sh` / `scripts/cursor.sh` /
|
|
106
106
|
* `scripts/codex.sh` / `scripts/ollama.sh`), the repository coding-law policy module,
|
|
107
|
-
* the line's seven byte-identical root dotfiles, and the two guides-grouped
|
|
108
|
-
* dev-tooling guide
|
|
109
|
-
* scaffold engine's own self-guide
|
|
107
|
+
* the line's seven byte-identical root dotfiles, and the two guides-grouped
|
|
108
|
+
* mirror candidates: the line-wide dev-tooling guide
|
|
109
|
+
* (`guides/src/guide.md`) and the scaffold engine's own self-guide
|
|
110
|
+
* (`guides/src/scaffold.md`). `stageHost` vendors both; each plan carries the
|
|
111
|
+
* subset selected by `selectHostPaths`, omitting the target blueprint's own
|
|
112
|
+
* guide.
|
|
110
113
|
*/
|
|
111
114
|
var HOST_PATHS = Object.freeze([
|
|
112
115
|
"AGENTS.md",
|
|
@@ -218,15 +221,15 @@ var DEFAULT_VERSION = "0.0.1";
|
|
|
218
221
|
/** The `engines.node` range the `blueprint` builder fills. */
|
|
219
222
|
var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
|
|
220
223
|
/** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
|
|
221
|
-
var SCAFFOLD_RANGE = "^0.0.
|
|
224
|
+
var SCAFFOLD_RANGE = "^0.0.7";
|
|
222
225
|
/** Tooling versions shared by scaffold and every generated workspace. */
|
|
223
226
|
var BASE_DEV_DEPENDENCIES = Object.freeze({
|
|
224
227
|
"@microsoft/api-extractor": "^7.58.12",
|
|
225
228
|
"@orkestrel/guide": "^0.0.5",
|
|
226
229
|
"@orkestrel/scaffold": SCAFFOLD_RANGE,
|
|
227
|
-
"@types/node": "^26.1.
|
|
228
|
-
oxfmt: "^0.
|
|
229
|
-
oxlint: "^1.
|
|
230
|
+
"@types/node": "^26.1.2",
|
|
231
|
+
oxfmt: "^0.61.0",
|
|
232
|
+
oxlint: "^1.76.0",
|
|
230
233
|
typescript: "^6.0.3",
|
|
231
234
|
vite: "^8.1.5",
|
|
232
235
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -1140,6 +1143,22 @@ function snapshotOf(current) {
|
|
|
1140
1143
|
return Object.fromEntries(entries);
|
|
1141
1144
|
}
|
|
1142
1145
|
/**
|
|
1146
|
+
* Select host paths without the guide owned by the target blueprint.
|
|
1147
|
+
*
|
|
1148
|
+
* @param paths - Host artifact paths in deterministic input order.
|
|
1149
|
+
* @param name - The target blueprint's unscoped package name.
|
|
1150
|
+
* @returns Every host path except `guides/src/<name>.md`, in input order.
|
|
1151
|
+
*
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```ts
|
|
1154
|
+
* selectHostPaths(['guides/src/guide.md', 'LICENSE'], 'guide') // ['LICENSE']
|
|
1155
|
+
* ```
|
|
1156
|
+
*/
|
|
1157
|
+
function selectHostPaths(paths, name) {
|
|
1158
|
+
const guide = `guides/src/${name}.md`;
|
|
1159
|
+
return paths.filter((path) => path !== guide);
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1143
1162
|
* Find the first exact or portable case-insensitive path collision.
|
|
1144
1163
|
*
|
|
1145
1164
|
* @param paths - Portable paths in deterministic input order.
|
|
@@ -1442,6 +1461,29 @@ function manifestToDependencies(manifestText) {
|
|
|
1442
1461
|
return dependencies;
|
|
1443
1462
|
}
|
|
1444
1463
|
/**
|
|
1464
|
+
* Project a `package.json` text to its own string `name`.
|
|
1465
|
+
*
|
|
1466
|
+
* @param manifest - The `package.json` file content.
|
|
1467
|
+
* @returns The own string `name`, or `undefined` when the manifest exceeds its
|
|
1468
|
+
* byte ceiling, is malformed, has a non-object root, or has no own string
|
|
1469
|
+
* `name`.
|
|
1470
|
+
*
|
|
1471
|
+
* @example
|
|
1472
|
+
* ```ts
|
|
1473
|
+
* import { manifestToName } from '@orkestrel/scaffold'
|
|
1474
|
+
*
|
|
1475
|
+
* manifestToName('{"name":"@orkestrel/router"}') // '@orkestrel/router'
|
|
1476
|
+
* manifestToName('{}') // undefined
|
|
1477
|
+
* ```
|
|
1478
|
+
*/
|
|
1479
|
+
function manifestToName(manifest) {
|
|
1480
|
+
if (manifest.length > 1048576 || contentByteLength(manifest) > 1048576) return;
|
|
1481
|
+
const parsed = (0, _orkestrel_contract.parseJSON)(manifest);
|
|
1482
|
+
if (!(0, _orkestrel_contract.isRecord)(parsed)) return void 0;
|
|
1483
|
+
const name = ownDataValue(parsed, "name");
|
|
1484
|
+
return typeof name === "string" ? name : void 0;
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1445
1487
|
* Compare a declared range to the registry latest.
|
|
1446
1488
|
*
|
|
1447
1489
|
* @param range - The declared semver range.
|
|
@@ -2146,6 +2188,7 @@ var isPlan = (0, _orkestrel_contract.andOf)((0, _orkestrel_contract.andOf)((0, _
|
|
|
2146
2188
|
function validatePlan(plan) {
|
|
2147
2189
|
const blueprintValidation = validateBlueprint(plan.blueprint);
|
|
2148
2190
|
const questions = [...blueprintValidation.questions];
|
|
2191
|
+
const warnings = [...blueprintValidation.warnings];
|
|
2149
2192
|
if (!hasValidPlanBytes(plan)) questions.push({
|
|
2150
2193
|
field: "artifacts",
|
|
2151
2194
|
text: "Plan artifact content exceeds the retained byte limits",
|
|
@@ -2170,16 +2213,20 @@ function validatePlan(plan) {
|
|
|
2170
2213
|
});
|
|
2171
2214
|
continue;
|
|
2172
2215
|
}
|
|
2173
|
-
if (artifact.path === "package.json")
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2216
|
+
if (artifact.path === "package.json") {
|
|
2217
|
+
questions.push({
|
|
2218
|
+
field: "overrides",
|
|
2219
|
+
text: "Override path \"package.json\" targets the blueprint-owned publication boundary",
|
|
2220
|
+
blocking: true
|
|
2221
|
+
});
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
warnings.push(`Override path "${item.path}" replaces its planned artifact content`);
|
|
2178
2225
|
}
|
|
2179
2226
|
return {
|
|
2180
2227
|
valid: questions.length === 0,
|
|
2181
2228
|
questions,
|
|
2182
|
-
warnings
|
|
2229
|
+
warnings
|
|
2183
2230
|
};
|
|
2184
2231
|
}
|
|
2185
2232
|
/** Determine whether every guide body fits the public UTF-8 artifact byte limit. */
|
|
@@ -5555,6 +5602,7 @@ function packageManifest(spec) {
|
|
|
5555
5602
|
}
|
|
5556
5603
|
if (spec.engine) scripts["test:src:bin"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin";
|
|
5557
5604
|
if (spec.engine) scripts["test:integration"] = "vitest run --config vite.config.ts --no-cache --reporter=dot --project integration";
|
|
5605
|
+
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)\"";
|
|
5558
5606
|
if (spec.app.length > 0) {
|
|
5559
5607
|
scripts["test:app"] = "vitest run --config vite.config.ts --no-cache --reporter=dot " + spec.app.map((environment) => `--project ${APP_MATRIX[environment].project}`).join(" ");
|
|
5560
5608
|
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}`;
|
|
@@ -5715,6 +5763,37 @@ function viteMachinery(src, app = [], engine = false) {
|
|
|
5715
5763
|
};
|
|
5716
5764
|
}
|
|
5717
5765
|
/**
|
|
5766
|
+
* Render the root Vitest project registration, preserving browser ownership
|
|
5767
|
+
* supplied by the caller.
|
|
5768
|
+
*
|
|
5769
|
+
* @param registrations - Ordered project factory identifiers with optional browser labels.
|
|
5770
|
+
* @param browser - Whether the generated configuration carries browser machinery.
|
|
5771
|
+
* @returns The rendered root `test` property.
|
|
5772
|
+
*
|
|
5773
|
+
* @example
|
|
5774
|
+
* ```ts
|
|
5775
|
+
* renderViteTest([{ project: 'srcCore' }], false)
|
|
5776
|
+
* // '\ttest: {\n\t\tprojects: [srcCore],\n\t},'
|
|
5777
|
+
* ```
|
|
5778
|
+
*/
|
|
5779
|
+
function renderViteTest(registrations, browser) {
|
|
5780
|
+
const projects = registrations.map((registration) => registration.project);
|
|
5781
|
+
const inlineProjects = ` projects: [${projects.join(", ")}],`;
|
|
5782
|
+
const renderedProjects = computeColumnWidth(inlineProjects) <= 100 ? inlineProjects : ` projects: [
|
|
5783
|
+
${projects.map((project) => ` ${project},`).join("\n")}
|
|
5784
|
+
],`;
|
|
5785
|
+
if (!browser) return ` test: {
|
|
5786
|
+
${renderedProjects}
|
|
5787
|
+
},`;
|
|
5788
|
+
return ` test: gateBrowserProjects(
|
|
5789
|
+
[
|
|
5790
|
+
${registrations.map((registration) => registration.browser === void 0 ? `{ project: ${registration.project} }` : `{ project: ${registration.project}, browser: ${serializeTypeScriptString(registration.browser)} }`).map((registration) => ` ${registration},`).join("\n")}
|
|
5791
|
+
],
|
|
5792
|
+
hasChromium,
|
|
5793
|
+
process.argv,
|
|
5794
|
+
),`;
|
|
5795
|
+
}
|
|
5796
|
+
/**
|
|
5718
5797
|
* The rendered import / `resolve` header block every `rootViteConfig` shape
|
|
5719
5798
|
* prefixes — the environment boundary and every guarantee it enforces ship
|
|
5720
5799
|
* unconditionally; `machinery` selects only the host-specific pipelines layered
|
|
@@ -5752,6 +5831,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
|
|
|
5752
5831
|
transform: {
|
|
5753
5832
|
order: 'pre',
|
|
5754
5833
|
async handler(code, id) {
|
|
5834
|
+
if (!isWorkspaceBoundaryModule(id)) return null
|
|
5755
5835
|
const restored = /[?&]html-proxy(?:[=&]|$)/.test(id) ? restoreIgnoredHtml(code) : code
|
|
5756
5836
|
const target = workspacePath(id)
|
|
5757
5837
|
const physicalImporter = physicalPath(id)
|
|
@@ -5911,6 +5991,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
|
|
|
5911
5991
|
transform: {
|
|
5912
5992
|
order: 'pre',
|
|
5913
5993
|
async handler(code, id) {
|
|
5994
|
+
if (!isWorkspaceBoundaryModule(id)) return null
|
|
5914
5995
|
const target = workspacePath(id)
|
|
5915
5996
|
const physicalImporter = physicalPath(id)
|
|
5916
5997
|
const importerPackageRoot = trustedPackageRootFor(physicalImporter, trustedPackageRoots)
|
|
@@ -5993,6 +6074,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
|
|
|
5993
6074
|
transform: {
|
|
5994
6075
|
order: 'pre',
|
|
5995
6076
|
async handler(code, id) {
|
|
6077
|
+
if (!isWorkspaceBoundaryModule(id)) return null
|
|
5996
6078
|
const target = workspacePath(id)
|
|
5997
6079
|
const physicalImporter = physicalPath(id)
|
|
5998
6080
|
const importerPackageRoot = trustedPackageRootFor(physicalImporter, trustedPackageRoots)
|
|
@@ -6084,6 +6166,64 @@ ${EXPORT_KEYWORD} function workspacePath(path: string): string | undefined {
|
|
|
6084
6166
|
return relativePath
|
|
6085
6167
|
}
|
|
6086
6168
|
|
|
6169
|
+
${EXPORT_KEYWORD} function isBoundaryExemptModule(id: string): boolean {
|
|
6170
|
+
const normalizedId = id.replaceAll('\\\\', '/')
|
|
6171
|
+
const [path] = normalizedId.split(/[?#]/)
|
|
6172
|
+
if (
|
|
6173
|
+
path === undefined ||
|
|
6174
|
+
normalizedId.startsWith('\\0') ||
|
|
6175
|
+
normalizedId.includes('virtual:') ||
|
|
6176
|
+
normalizedId === '@vite/client' ||
|
|
6177
|
+
normalizedId === '@vite/env' ||
|
|
6178
|
+
normalizedId.startsWith('/@id/') ||
|
|
6179
|
+
normalizedId.startsWith('/@vite/') ||
|
|
6180
|
+
normalizedId.startsWith('/__vite') ||
|
|
6181
|
+
normalizedId.startsWith('/__vitest') ||
|
|
6182
|
+
normalizedId.startsWith('@vitest/browser') ||
|
|
6183
|
+
normalizedId.includes('/@vitest/browser/')
|
|
6184
|
+
) {
|
|
6185
|
+
return true
|
|
6186
|
+
}
|
|
6187
|
+
let physicalId: string | undefined
|
|
6188
|
+
try {
|
|
6189
|
+
physicalId = physicalPath(id).replaceAll('\\\\', '/')
|
|
6190
|
+
} catch {
|
|
6191
|
+
physicalId = undefined
|
|
6192
|
+
}
|
|
6193
|
+
for (const candidate of physicalId === undefined ? [path] : [path, physicalId]) {
|
|
6194
|
+
if (candidate.split('/').some((segment) => segment.toLowerCase() === 'node_modules')) {
|
|
6195
|
+
return true
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
return false
|
|
6199
|
+
}
|
|
6200
|
+
|
|
6201
|
+
${EXPORT_KEYWORD} function isWorkspaceBoundaryModule(id: string): boolean {
|
|
6202
|
+
if (isBoundaryExemptModule(id)) return false
|
|
6203
|
+
const normalizedId = id.replaceAll('\\\\', '/')
|
|
6204
|
+
const [path] = normalizedId.split(/[?#]/)
|
|
6205
|
+
if (path === undefined) return false
|
|
6206
|
+
let candidate = path.startsWith('/@fs/') ? path.slice('/@fs/'.length) : path
|
|
6207
|
+
try {
|
|
6208
|
+
if (/^file:/i.test(candidate)) candidate = fileURLToPath(candidate)
|
|
6209
|
+
} catch {
|
|
6210
|
+
return false
|
|
6211
|
+
}
|
|
6212
|
+
const rootRelative = /^\\/(?:app|src)\\/(?:core|browser|server)\\//.test(candidate)
|
|
6213
|
+
const absoluteCandidate = rootRelative
|
|
6214
|
+
? resolvePath(WORKSPACE_ROOT, candidate.slice(1))
|
|
6215
|
+
: isAbsolute(candidate)
|
|
6216
|
+
? candidate
|
|
6217
|
+
: resolvePath(WORKSPACE_ROOT, candidate)
|
|
6218
|
+
const relativeId = relative(WORKSPACE_ROOT, absoluteCandidate).replaceAll('\\\\', '/')
|
|
6219
|
+
return (
|
|
6220
|
+
relativeId !== '..' &&
|
|
6221
|
+
!relativeId.startsWith('../') &&
|
|
6222
|
+
!isAbsolute(relativeId) &&
|
|
6223
|
+
/^(?:app|src)\\/(?:core|browser|server)\\//.test(relativeId)
|
|
6224
|
+
)
|
|
6225
|
+
}
|
|
6226
|
+
|
|
6087
6227
|
${EXPORT_KEYWORD} function isOutsideWorkspacePath(path: string): boolean {
|
|
6088
6228
|
const [pathWithoutQuery] = path.split('?')
|
|
6089
6229
|
if (pathWithoutQuery === undefined) return false
|
|
@@ -6722,6 +6862,7 @@ ${EXPORT_KEYWORD} function finalizeHtml(): Plugin {
|
|
|
6722
6862
|
const transformed = await transformWithOxc(code, path)
|
|
6723
6863
|
const visitor = new Visitor({
|
|
6724
6864
|
ImportExpression(node) {
|
|
6865
|
+
if (emitted) return
|
|
6725
6866
|
let value: string | undefined
|
|
6726
6867
|
if (node.source.type === 'Literal' && typeof node.source.value === 'string') {
|
|
6727
6868
|
value = node.source.value
|
|
@@ -6820,8 +6961,8 @@ ${needsVue ? ` configureServer(server) {
|
|
|
6820
6961
|
})
|
|
6821
6962
|
},
|
|
6822
6963
|
` : ""} async resolveId(source, importer) {
|
|
6823
|
-
if (importer === undefined) return null
|
|
6824
|
-
if (source
|
|
6964
|
+
if (importer === undefined || !isWorkspaceBoundaryModule(importer)) return null
|
|
6965
|
+
if (isBoundaryExemptModule(source)) return null
|
|
6825
6966
|
const normalizedSource = source.replaceAll('\\\\', '/')
|
|
6826
6967
|
const sourceError = environmentSourceError(owner, normalizedSource)
|
|
6827
6968
|
if (sourceError !== undefined) this.error(sourceError)
|
|
@@ -6898,6 +7039,7 @@ ${needsVue ? ` configureServer(server) {
|
|
|
6898
7039
|
return null
|
|
6899
7040
|
},
|
|
6900
7041
|
async load(id) {
|
|
7042
|
+
if (!isWorkspaceBoundaryModule(id)) return null
|
|
6901
7043
|
const physicalImporter = physicalPath(id)
|
|
6902
7044
|
const trustedPackageRoot = trustedPackageRootFor(physicalImporter, trustedPackageRoots)
|
|
6903
7045
|
const inferredPackageRoot =
|
|
@@ -6955,6 +7097,7 @@ ${needsVue ? ` configureServer(server) {
|
|
|
6955
7097
|
const physical = physicalPath(
|
|
6956
7098
|
isAbsolute(original) ? original : resolvePath(environmentRoot, original),
|
|
6957
7099
|
)
|
|
7100
|
+
if (isBoundaryExemptModule(original) || isBoundaryExemptModule(physical)) continue
|
|
6958
7101
|
const target = workspacePath(physical)
|
|
6959
7102
|
if (target === undefined) {
|
|
6960
7103
|
if (trustedPackageRootFor(physical, trustedPackageRoots) === undefined) {
|
|
@@ -6970,6 +7113,7 @@ ${needsVue ? ` configureServer(server) {
|
|
|
6970
7113
|
buildEnd(error) {
|
|
6971
7114
|
if (error !== undefined) return
|
|
6972
7115
|
for (const id of this.getModuleIds()) {
|
|
7116
|
+
if (!isWorkspaceBoundaryModule(id)) continue
|
|
6973
7117
|
const target = workspacePath(id)
|
|
6974
7118
|
if (target === undefined) {
|
|
6975
7119
|
if (
|
|
@@ -7026,7 +7170,58 @@ ${CONST_KEYWORD} resolve = {
|
|
|
7026
7170
|
}, {}),
|
|
7027
7171
|
}
|
|
7028
7172
|
|
|
7029
|
-
${needsBrowser ? `${EXPORT_KEYWORD}
|
|
7173
|
+
${needsBrowser ? `${EXPORT_KEYWORD} function gateBrowserProjects(
|
|
7174
|
+
registrations: readonly {
|
|
7175
|
+
readonly project: () => UserConfig
|
|
7176
|
+
readonly browser?: string
|
|
7177
|
+
}[],
|
|
7178
|
+
available: boolean,
|
|
7179
|
+
argv: readonly string[],
|
|
7180
|
+
): NonNullable<UserConfig['test']> {
|
|
7181
|
+
const projects: UserConfig[] = []
|
|
7182
|
+
const gated: string[] = []
|
|
7183
|
+
for (const registration of registrations) {
|
|
7184
|
+
if (registration.browser !== undefined && !available) {
|
|
7185
|
+
gated.push(registration.browser)
|
|
7186
|
+
projects.push({
|
|
7187
|
+
resolve,
|
|
7188
|
+
test: {
|
|
7189
|
+
name: { label: registration.browser, color: 'yellow' },
|
|
7190
|
+
include: [],
|
|
7191
|
+
environment: 'node',
|
|
7192
|
+
browser: { enabled: false },
|
|
7193
|
+
},
|
|
7194
|
+
})
|
|
7195
|
+
continue
|
|
7196
|
+
}
|
|
7197
|
+
projects.push(registration.project())
|
|
7198
|
+
}
|
|
7199
|
+
if (gated.length === 0) return { projects }
|
|
7200
|
+
console.warn(\`browser projects skipped: Chromium absent (\${gated.join(', ')})\`)
|
|
7201
|
+
const filters: string[] = []
|
|
7202
|
+
let readable = true
|
|
7203
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
7204
|
+
const argument = argv[index]
|
|
7205
|
+
if (argument === '--project') {
|
|
7206
|
+
const filter = argv[index + 1]
|
|
7207
|
+
if (filter === undefined) {
|
|
7208
|
+
readable = false
|
|
7209
|
+
continue
|
|
7210
|
+
}
|
|
7211
|
+
filters.push(filter)
|
|
7212
|
+
index += 1
|
|
7213
|
+
continue
|
|
7214
|
+
}
|
|
7215
|
+
if (argument?.startsWith('--project=') === true) {
|
|
7216
|
+
filters.push(argument.slice('--project='.length))
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
return readable && filters.length > 0 && filters.every((filter) => gated.includes(filter))
|
|
7220
|
+
? { passWithNoTests: true, projects }
|
|
7221
|
+
: { projects }
|
|
7222
|
+
}
|
|
7223
|
+
|
|
7224
|
+
${EXPORT_KEYWORD} ${CONST_KEYWORD} ENVIRONMENT_CSS = Object.freeze({
|
|
7030
7225
|
transformer: 'lightningcss',
|
|
7031
7226
|
lightningcss: {
|
|
7032
7227
|
visitor: () => {
|
|
@@ -7121,11 +7316,10 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
|
|
|
7121
7316
|
},
|
|
7122
7317
|
test: {
|
|
7123
7318
|
name: { label: 'src:browser', color: 'yellow' },
|
|
7124
|
-
include:
|
|
7125
|
-
passWithNoTests: !hasChromium,
|
|
7319
|
+
include: ['tests/src/browser/**/*.test.ts'],
|
|
7126
7320
|
setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
|
|
7127
7321
|
browser: {
|
|
7128
|
-
enabled:
|
|
7322
|
+
enabled: true,
|
|
7129
7323
|
provider: playwright(),
|
|
7130
7324
|
instances: [{ browser: 'chromium', headless: true }],
|
|
7131
7325
|
},
|
|
@@ -7154,9 +7348,15 @@ ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
|
|
|
7154
7348
|
|
|
7155
7349
|
export default defineConfig({
|
|
7156
7350
|
resolve,
|
|
7157
|
-
test:
|
|
7158
|
-
|
|
7159
|
-
|
|
7351
|
+
test: gateBrowserProjects(
|
|
7352
|
+
[
|
|
7353
|
+
{ project: srcBrowser, browser: 'src:browser' },
|
|
7354
|
+
{ project: policy },
|
|
7355
|
+
{ project: guides },
|
|
7356
|
+
],
|
|
7357
|
+
hasChromium,
|
|
7358
|
+
process.argv,
|
|
7359
|
+
),
|
|
7160
7360
|
})
|
|
7161
7361
|
`;
|
|
7162
7362
|
return `${header}
|
|
@@ -7276,12 +7476,11 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
|
|
|
7276
7476
|
},
|
|
7277
7477
|
test: {
|
|
7278
7478
|
name: { label: 'src:browser', color: 'yellow' },
|
|
7279
|
-
include:
|
|
7280
|
-
passWithNoTests: !hasChromium,
|
|
7479
|
+
include: ['tests/src/browser/**/*.test.ts'],
|
|
7281
7480
|
exclude: ['tests/src/core/**/*.test.ts'],
|
|
7282
7481
|
setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
|
|
7283
7482
|
browser: {
|
|
7284
|
-
enabled:
|
|
7483
|
+
enabled: true,
|
|
7285
7484
|
provider: playwright(),
|
|
7286
7485
|
instances: [{ browser: 'chromium', headless: true }],
|
|
7287
7486
|
},
|
|
@@ -7379,14 +7578,15 @@ ${EXPORT_KEYWORD} const integration = (config?: UserConfig): UserConfig =>
|
|
|
7379
7578
|
)
|
|
7380
7579
|
` : "";
|
|
7381
7580
|
const blocks = nonCore.map((environment) => environment === "browser" ? browserBlock : serverBlock).join("") + binBlock;
|
|
7382
|
-
const
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
"
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7581
|
+
const registrations = [];
|
|
7582
|
+
if (hasCore) registrations.push({ project: "srcCore" });
|
|
7583
|
+
for (const environment of nonCore) registrations.push(environment === "browser" ? {
|
|
7584
|
+
project: "srcBrowser",
|
|
7585
|
+
browser: SRC_MATRIX.browser.project
|
|
7586
|
+
} : { project: "srcServer" });
|
|
7587
|
+
registrations.push({ project: "policy" }, { project: "guides" });
|
|
7588
|
+
if (engine) registrations.push({ project: "srcBin" }, { project: "integration" });
|
|
7589
|
+
const renderedTest = renderViteTest(registrations, machinery.browser);
|
|
7390
7590
|
return `${header}
|
|
7391
7591
|
${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
|
|
7392
7592
|
mergeConfig(
|
|
@@ -7426,9 +7626,7 @@ ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
|
|
|
7426
7626
|
${blocks}
|
|
7427
7627
|
export default defineConfig({
|
|
7428
7628
|
resolve,
|
|
7429
|
-
|
|
7430
|
-
projects: [${projectNames.join(", ")}],
|
|
7431
|
-
},
|
|
7629
|
+
${renderedTest}
|
|
7432
7630
|
})
|
|
7433
7631
|
`;
|
|
7434
7632
|
}
|
|
@@ -7450,10 +7648,10 @@ function applicationViteConfig(src, app, engine = false) {
|
|
|
7450
7648
|
const hasSourceCore = src.includes("core");
|
|
7451
7649
|
const machinery = viteMachinery(src, app, engine);
|
|
7452
7650
|
const header = viteHeader(machinery);
|
|
7453
|
-
const
|
|
7651
|
+
const registrations = [];
|
|
7454
7652
|
const blocks = [];
|
|
7455
7653
|
if (src.includes("core")) {
|
|
7456
|
-
|
|
7654
|
+
registrations.push({ project: "srcCore" });
|
|
7457
7655
|
blocks.push(`
|
|
7458
7656
|
${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
|
|
7459
7657
|
mergeConfig(
|
|
@@ -7475,7 +7673,10 @@ ${EXPORT_KEYWORD} const srcCore = (config?: UserConfig): UserConfig =>
|
|
|
7475
7673
|
`);
|
|
7476
7674
|
}
|
|
7477
7675
|
if (src.includes("browser")) {
|
|
7478
|
-
|
|
7676
|
+
registrations.push({
|
|
7677
|
+
project: "srcBrowser",
|
|
7678
|
+
browser: SRC_MATRIX.browser.project
|
|
7679
|
+
});
|
|
7479
7680
|
const coreOutput = hasSourceCore ? `
|
|
7480
7681
|
output: { paths: { '@src/core': '../core/index.js' } },` : "";
|
|
7481
7682
|
const coreExternal = hasSourceCore ? `id === '@src/core' || ` : "";
|
|
@@ -7504,11 +7705,10 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
|
|
|
7504
7705
|
},
|
|
7505
7706
|
test: {
|
|
7506
7707
|
name: { label: 'src:browser', color: 'yellow' },
|
|
7507
|
-
include:
|
|
7508
|
-
passWithNoTests: !hasChromium,
|
|
7708
|
+
include: ['tests/src/browser/**/*.test.ts'],
|
|
7509
7709
|
${hasSourceCore ? "exclude: ['tests/src/core/**/*.test.ts'],\n " : ""}setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
|
|
7510
7710
|
browser: {
|
|
7511
|
-
enabled:
|
|
7711
|
+
enabled: true,
|
|
7512
7712
|
provider: playwright(),
|
|
7513
7713
|
instances: [{ browser: 'chromium', headless: true }],
|
|
7514
7714
|
},
|
|
@@ -7520,7 +7720,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
|
|
|
7520
7720
|
`);
|
|
7521
7721
|
}
|
|
7522
7722
|
if (src.includes("server")) {
|
|
7523
|
-
|
|
7723
|
+
registrations.push({ project: "srcServer" });
|
|
7524
7724
|
const coreOutput = hasSourceCore ? `
|
|
7525
7725
|
output: [
|
|
7526
7726
|
{
|
|
@@ -7571,7 +7771,7 @@ ${EXPORT_KEYWORD} const srcServer = (config?: UserConfig): UserConfig =>
|
|
|
7571
7771
|
`);
|
|
7572
7772
|
}
|
|
7573
7773
|
if (app.includes("core")) {
|
|
7574
|
-
|
|
7774
|
+
registrations.push({ project: "appCore" });
|
|
7575
7775
|
blocks.push(`
|
|
7576
7776
|
${EXPORT_KEYWORD} const appCore = (config?: UserConfig): UserConfig =>
|
|
7577
7777
|
mergeConfig(
|
|
@@ -7592,7 +7792,10 @@ ${EXPORT_KEYWORD} const appCore = (config?: UserConfig): UserConfig =>
|
|
|
7592
7792
|
`);
|
|
7593
7793
|
}
|
|
7594
7794
|
if (app.includes("browser")) {
|
|
7595
|
-
|
|
7795
|
+
registrations.push({
|
|
7796
|
+
project: "appBrowser",
|
|
7797
|
+
browser: APP_MATRIX.browser.project
|
|
7798
|
+
});
|
|
7596
7799
|
blocks.push(`
|
|
7597
7800
|
${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
|
|
7598
7801
|
if (config.length > 0) {
|
|
@@ -7633,11 +7836,10 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
|
|
|
7633
7836
|
name: { label: '${APP_MATRIX.browser.project}', color: 'blue' },
|
|
7634
7837
|
root: resolveWorkspacePath('.'),
|
|
7635
7838
|
dir: resolveWorkspacePath('.'),
|
|
7636
|
-
include:
|
|
7637
|
-
passWithNoTests: !hasChromium,
|
|
7839
|
+
include: ['tests/app/browser/**/*.test.ts'],
|
|
7638
7840
|
setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
|
|
7639
7841
|
browser: {
|
|
7640
|
-
enabled:
|
|
7842
|
+
enabled: true,
|
|
7641
7843
|
provider: playwright(),
|
|
7642
7844
|
instances: [{ browser: 'chromium', headless: true }],
|
|
7643
7845
|
},
|
|
@@ -7648,7 +7850,7 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
|
|
|
7648
7850
|
`);
|
|
7649
7851
|
}
|
|
7650
7852
|
if (app.includes("server")) {
|
|
7651
|
-
|
|
7853
|
+
registrations.push({ project: "appServer" });
|
|
7652
7854
|
blocks.push(`
|
|
7653
7855
|
${EXPORT_KEYWORD} const appServer = (config?: UserConfig): UserConfig =>
|
|
7654
7856
|
mergeConfig(
|
|
@@ -7682,7 +7884,7 @@ ${EXPORT_KEYWORD} const appServer = (config?: UserConfig): UserConfig =>
|
|
|
7682
7884
|
`);
|
|
7683
7885
|
}
|
|
7684
7886
|
if (engine) {
|
|
7685
|
-
|
|
7887
|
+
registrations.push({ project: "srcBin" }, { project: "integration" });
|
|
7686
7888
|
blocks.push(`
|
|
7687
7889
|
${EXPORT_KEYWORD} const srcBin = (config?: UserConfig): UserConfig =>
|
|
7688
7890
|
mergeConfig(
|
|
@@ -7726,6 +7928,8 @@ ${EXPORT_KEYWORD} const integration = (config?: UserConfig): UserConfig =>
|
|
|
7726
7928
|
)
|
|
7727
7929
|
`);
|
|
7728
7930
|
}
|
|
7931
|
+
registrations.push({ project: "policy" }, { project: "guides" });
|
|
7932
|
+
const renderedTest = renderViteTest(registrations, machinery.browser);
|
|
7729
7933
|
return `${header}
|
|
7730
7934
|
${policyViteProject()}
|
|
7731
7935
|
${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
|
|
@@ -7746,18 +7950,12 @@ ${EXPORT_KEYWORD} const guides = (config?: UserConfig): UserConfig =>
|
|
|
7746
7950
|
${blocks.join("")}
|
|
7747
7951
|
export default defineConfig({
|
|
7748
7952
|
resolve,
|
|
7749
|
-
|
|
7750
|
-
projects: [${[
|
|
7751
|
-
...projects,
|
|
7752
|
-
"policy",
|
|
7753
|
-
"guides"
|
|
7754
|
-
].join(", ")}],
|
|
7755
|
-
},
|
|
7953
|
+
${renderedTest}
|
|
7756
7954
|
})
|
|
7757
7955
|
`;
|
|
7758
7956
|
}
|
|
7759
7957
|
/**
|
|
7760
|
-
* `configs/src/tsconfig.core.json` —
|
|
7958
|
+
* `configs/src/tsconfig.core.json` — host-neutral core with web interop declarations.
|
|
7761
7959
|
*
|
|
7762
7960
|
* @returns The core environment `tsconfig` file content, newline-terminated.
|
|
7763
7961
|
*
|
|
@@ -7770,7 +7968,7 @@ function coreTsconfig() {
|
|
|
7770
7968
|
return formatJson({
|
|
7771
7969
|
extends: "../../tsconfig.json",
|
|
7772
7970
|
compilerOptions: {
|
|
7773
|
-
lib: ["ESNext"],
|
|
7971
|
+
lib: ["ESNext", "WebWorker"],
|
|
7774
7972
|
types: [],
|
|
7775
7973
|
noEmit: false,
|
|
7776
7974
|
declaration: true,
|
|
@@ -7925,7 +8123,7 @@ function appTsconfig(environment, hasCore) {
|
|
|
7925
8123
|
"ESNext",
|
|
7926
8124
|
"DOM",
|
|
7927
8125
|
"DOM.Iterable"
|
|
7928
|
-
] : ["ESNext"],
|
|
8126
|
+
] : environment === "core" ? ["ESNext", "WebWorker"] : ["ESNext"],
|
|
7929
8127
|
types: environment === "browser" ? ["vite/client", "vue"] : environment === "server" ? ["node"] : []
|
|
7930
8128
|
},
|
|
7931
8129
|
include
|
|
@@ -8527,12 +8725,15 @@ function guideTests(spec, pascal) {
|
|
|
8527
8725
|
}
|
|
8528
8726
|
/**
|
|
8529
8727
|
* Draft the `guides` group's artifacts — the package's own filled guide stub,
|
|
8530
|
-
* the guides index, and
|
|
8728
|
+
* the guides index, and vendored dependency guide mirrors whose paths are
|
|
8729
|
+
* neither the package's own guide nor already carried by the selected host
|
|
8730
|
+
* set.
|
|
8531
8731
|
*
|
|
8532
8732
|
* @param spec - The `Blueprint` to derive guide artifacts from.
|
|
8533
8733
|
* @param pascal - The package's PascalCase entity name.
|
|
8534
8734
|
* @param members - The blueprint's derived `Member[]`.
|
|
8535
|
-
* @returns The `guides` group's `Artifact[]
|
|
8735
|
+
* @returns The `guides` group's `Artifact[]`, with one contributor per guide
|
|
8736
|
+
* path.
|
|
8536
8737
|
*
|
|
8537
8738
|
* @example
|
|
8538
8739
|
* ```ts
|
|
@@ -8585,14 +8786,16 @@ function guideArtifacts(spec, pascal, members) {
|
|
|
8585
8786
|
]]),
|
|
8586
8787
|
directory: alignTable(["Directory", "Guide"], sourceDirectories.map((directory) => [directory, `[\`${spec.name}.md\`](src/${spec.name}.md)`]))
|
|
8587
8788
|
})];
|
|
8789
|
+
const guidePath = `guides/src/${spec.name}.md`;
|
|
8588
8790
|
for (const dep of spec.dependencies) {
|
|
8589
8791
|
if (!vendoredGuides.includes(dep.name)) continue;
|
|
8590
|
-
const
|
|
8792
|
+
const path = `guides/src/${dep.name.replace("@orkestrel/", "")}.md`;
|
|
8793
|
+
if (HOST_PATHS.includes(path) || path === guidePath) continue;
|
|
8591
8794
|
artifacts.push({
|
|
8592
|
-
path
|
|
8795
|
+
path,
|
|
8593
8796
|
group: "guides",
|
|
8594
8797
|
origin: "host",
|
|
8595
|
-
source:
|
|
8798
|
+
source: path
|
|
8596
8799
|
});
|
|
8597
8800
|
}
|
|
8598
8801
|
return artifacts;
|
|
@@ -8628,7 +8831,7 @@ function applyOverrides(artifacts, overrides) {
|
|
|
8628
8831
|
/**
|
|
8629
8832
|
* The full pure compilation: draft a blueprint's artifacts — the manifest and
|
|
8630
8833
|
* exports combination rules over the per-environment `SRC_MATRIX` rows, plus
|
|
8631
|
-
* `HOST_PATHS` and `overrides` — then pin.
|
|
8834
|
+
* the `selectHostPaths` selection of `HOST_PATHS` and `overrides` — then pin.
|
|
8632
8835
|
*
|
|
8633
8836
|
* @param blueprint - The `Blueprint` to compile.
|
|
8634
8837
|
* @param groups - An optional `Group[]` selection (default: all groups).
|
|
@@ -8672,7 +8875,7 @@ npm install @orkestrel/${blueprint.name}
|
|
|
8672
8875
|
origin: "computed",
|
|
8673
8876
|
content: ciWorkflow(blueprint)
|
|
8674
8877
|
});
|
|
8675
|
-
for (const path of HOST_PATHS) {
|
|
8878
|
+
for (const path of selectHostPaths(HOST_PATHS, blueprint.name)) {
|
|
8676
8879
|
const group = hostGroup(path);
|
|
8677
8880
|
if (!selected.includes(group)) continue;
|
|
8678
8881
|
artifacts.push({
|
|
@@ -8795,7 +8998,10 @@ var Compiler = class Compiler {
|
|
|
8795
8998
|
this.#emitter.emit("audit", result);
|
|
8796
8999
|
return result;
|
|
8797
9000
|
}
|
|
8798
|
-
const result =
|
|
9001
|
+
const result = {
|
|
9002
|
+
...diffPlan(scaffolding.plan, current),
|
|
9003
|
+
questions: scaffolding.questions
|
|
9004
|
+
};
|
|
8799
9005
|
this.#emitter.emit("audit", result);
|
|
8800
9006
|
return result;
|
|
8801
9007
|
}
|
|
@@ -8859,7 +9065,16 @@ var Compiler = class Compiler {
|
|
|
8859
9065
|
const validation = validatePlan(draft);
|
|
8860
9066
|
const dependencyQuestions = this.#dependencyQuestions(blueprint);
|
|
8861
9067
|
const blocking = [...validation.questions];
|
|
8862
|
-
const
|
|
9068
|
+
const warningQuestions = validation.warnings.map((text) => ({
|
|
9069
|
+
field: "overrides",
|
|
9070
|
+
text,
|
|
9071
|
+
blocking: false
|
|
9072
|
+
}));
|
|
9073
|
+
const questions = [
|
|
9074
|
+
...blocking,
|
|
9075
|
+
...warningQuestions,
|
|
9076
|
+
...dependencyQuestions
|
|
9077
|
+
];
|
|
8863
9078
|
stages.push({
|
|
8864
9079
|
stage: "gate",
|
|
8865
9080
|
input: draft,
|
|
@@ -8952,9 +9167,11 @@ var Compiler = class Compiler {
|
|
|
8952
9167
|
}
|
|
8953
9168
|
#pointerArtifacts(blueprint) {
|
|
8954
9169
|
const artifacts = [];
|
|
9170
|
+
const guidePath = `guides/src/${blueprint.name}.md`;
|
|
8955
9171
|
for (const item of blueprint.dependencies) {
|
|
8956
9172
|
if (Compiler.#vendored.includes(item.name)) continue;
|
|
8957
9173
|
const path = `guides/src/${item.name.replace("@orkestrel/", "")}.md`;
|
|
9174
|
+
if (path === guidePath || HOST_PATHS.includes(path)) continue;
|
|
8958
9175
|
artifacts.push({
|
|
8959
9176
|
path,
|
|
8960
9177
|
group: "guides",
|
|
@@ -9307,6 +9524,7 @@ exports.isScaffoldError = isScaffoldError;
|
|
|
9307
9524
|
exports.isSyncReport = isSyncReport;
|
|
9308
9525
|
exports.isWorkspaceName = isWorkspaceName;
|
|
9309
9526
|
exports.manifestToDependencies = manifestToDependencies;
|
|
9527
|
+
exports.manifestToName = manifestToName;
|
|
9310
9528
|
exports.member = member;
|
|
9311
9529
|
exports.memberShape = memberShape;
|
|
9312
9530
|
exports.override = override;
|
|
@@ -9333,8 +9551,10 @@ exports.rangeToFreshness = rangeToFreshness;
|
|
|
9333
9551
|
exports.renderArray = renderArray;
|
|
9334
9552
|
exports.renderObject = renderObject;
|
|
9335
9553
|
exports.renderValue = renderValue;
|
|
9554
|
+
exports.renderViteTest = renderViteTest;
|
|
9336
9555
|
exports.rootTsconfig = rootTsconfig;
|
|
9337
9556
|
exports.rootViteConfig = rootViteConfig;
|
|
9557
|
+
exports.selectHostPaths = selectHostPaths;
|
|
9338
9558
|
exports.serializeTypeScriptString = serializeTypeScriptString;
|
|
9339
9559
|
exports.singleSrcViteConfig = singleSrcViteConfig;
|
|
9340
9560
|
exports.snapshotOf = snapshotOf;
|