@orkestrel/scaffold 0.0.101 → 0.0.102
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/agents/skills/orkestrel-dispatch/scripts/brief.js +6 -14
- package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +41 -28
- package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +5 -12
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +25 -13
- package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +18 -25
- package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +11 -9
- package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +233 -232
- package/dist/agents/skills/orkestrel-publish/scripts/compare.js +95 -89
- package/dist/agents/skills/orkestrel-publish/scripts/pins.js +5 -7
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +1273 -0
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +99 -89
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +54 -52
- package/dist/agents/skills/orkestrel-scout/scripts/map.js +160 -161
- package/dist/bin/main.js +483 -444
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +1 -0
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +8 -11
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +58 -28
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +5 -10
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +31 -12
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +28 -23
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +12 -10
- package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +318 -237
- package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +2 -5
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +7 -6
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +12 -10
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +12 -5
- package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +124 -82
- package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +5 -7
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1655 -0
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +128 -97
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +70 -55
- package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +215 -155
- package/dist/host/claude/rules/architecture.md +2 -2
- package/dist/host/claude/rules/tests.md +8 -2
- package/dist/host/claude/rules/typescript.md +130 -0
- package/dist/host/claude/rules/workspace.md +30 -12
- package/dist/host/configs/helpers.ts +206 -133
- package/dist/host/configs/policy.ts +110 -105
- package/dist/host/guides/scaffold.md +244 -170
- package/dist/host/manifest.json +35 -29
- package/dist/host/tests/config.test.ts +1220 -633
- package/dist/host/tests/policy.test.ts +19 -0
- package/dist/host/tests/setupPolicy.ts +1669 -985
- package/dist/src/core/index.cjs +1595 -1686
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +202 -18
- package/dist/src/core/index.d.ts +202 -18
- package/dist/src/core/index.js +1590 -1687
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +448 -392
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +1182 -1052
- package/dist/src/server/index.d.ts +1182 -1052
- package/dist/src/server/index.js +447 -395
- package/dist/src/server/index.js.map +1 -1
- package/package.json +2 -2
package/dist/src/core/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { fillTemplate } from "@orkestrel/template";
|
|
|
3
3
|
import { Emitter } from "@orkestrel/emitter";
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@orkestrel/scaffold",
|
|
6
|
-
version: "0.0.
|
|
6
|
+
version: "0.0.102",
|
|
7
7
|
description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
|
|
8
8
|
keywords: [
|
|
9
9
|
"audit",
|
|
@@ -107,7 +107,7 @@ var package_default = {
|
|
|
107
107
|
"@orkestrel/guide": "^0.0.24",
|
|
108
108
|
"@orkestrel/html": "^0.0.12",
|
|
109
109
|
"@orkestrel/probe": "^0.0.23",
|
|
110
|
-
"@orkestrel/test": "^0.0.
|
|
110
|
+
"@orkestrel/test": "^0.0.26",
|
|
111
111
|
"@types/node": "^26.6.4",
|
|
112
112
|
"@vitest/browser-playwright": "^4.1.11",
|
|
113
113
|
"oxfmt": "^0.72.0",
|
|
@@ -502,6 +502,16 @@ var SERVICE_SETUP_PATH = "tests/setupService.ts";
|
|
|
502
502
|
* one proof.
|
|
503
503
|
*/
|
|
504
504
|
var SERVICE_TEST_INCLUDE = "tests/service/**/*.test.ts";
|
|
505
|
+
/**
|
|
506
|
+
* Names the include the study project covers, where an exact-case `*.test.ts` file beneath
|
|
507
|
+
* `tests/studies`, outside any `node_modules` or `.git` directory, makes a workspace `studies`.
|
|
508
|
+
*
|
|
509
|
+
* @remarks
|
|
510
|
+
* The selector reads the include's population less Vitest's default exclude: an exact-case file
|
|
511
|
+
* beneath `tests/studies`, nested or direct, whose name ends in `.test.ts`, outside any
|
|
512
|
+
* `node_modules` or `.git` directory, which Vitest's default exclude never collects.
|
|
513
|
+
*/
|
|
514
|
+
var STUDIES_TEST_INCLUDE = "tests/studies/**/*.test.ts";
|
|
505
515
|
/** Names the Vite wrapper whose presence makes a workspace `showcase`. */
|
|
506
516
|
var SHOWCASE_CONFIG_PATH = "configs/app/vite.showcase.config.ts";
|
|
507
517
|
/** Names the Vite wrapper whose presence makes a workspace `journey`. */
|
|
@@ -804,11 +814,13 @@ export const peers: readonly string[] =
|
|
|
804
814
|
peerDependencies === undefined ? [] : Object.keys(peerDependencies)
|
|
805
815
|
|
|
806
816
|
const resolve = {
|
|
807
|
-
alias: Object.
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
817
|
+
alias: Object.fromEntries(
|
|
818
|
+
Object.entries(tsconfig.compilerOptions.paths).map(([key, values]) => {
|
|
819
|
+
const [path] = values
|
|
820
|
+
if (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')
|
|
821
|
+
return [key, resolveWorkspacePath(path)]
|
|
822
|
+
}),
|
|
823
|
+
),
|
|
812
824
|
}
|
|
813
825
|
|
|
814
826
|
// Merges a caller's override onto the configuration a factory declares, so a
|
|
@@ -837,53 +849,67 @@ const resolve = {
|
|
|
837
849
|
// merges it, so an override's arrays elsewhere concatenate with the base's rather than
|
|
838
850
|
// replacing them.
|
|
839
851
|
export function mergeOverride(base: UserConfig, override?: UserConfig): UserConfig {
|
|
840
|
-
if (
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
852
|
+
if (
|
|
853
|
+
override !== undefined &&
|
|
854
|
+
'command' in override &&
|
|
855
|
+
'mode' in override &&
|
|
856
|
+
typeof override.mode !== 'string'
|
|
857
|
+
) {
|
|
858
|
+
throw new Error('The project invocation carries no string mode')
|
|
859
|
+
}
|
|
860
|
+
const effective: UserConfig | undefined =
|
|
861
|
+
override !== undefined && 'command' in override && typeof override.mode === 'string'
|
|
862
|
+
? { mode: override.mode }
|
|
863
|
+
: override
|
|
864
|
+
const merged: UserConfig = effective === undefined ? { ...base } : mergeConfig(base, effective)
|
|
847
865
|
const name = merged.test?.name
|
|
848
866
|
const label = typeof name === 'string' ? name : name?.label
|
|
849
867
|
const browser = merged.test?.browser
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
868
|
+
const named: UserConfig =
|
|
869
|
+
label !== undefined && browser?.instances !== undefined
|
|
870
|
+
? {
|
|
871
|
+
...merged,
|
|
872
|
+
test: {
|
|
873
|
+
...merged.test,
|
|
874
|
+
browser: {
|
|
875
|
+
...browser,
|
|
876
|
+
instances: browser.instances.map((instance) => ({
|
|
877
|
+
...instance,
|
|
878
|
+
name: instance.name ?? \`\${label} (\${instance.browser})\`,
|
|
879
|
+
})),
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
}
|
|
883
|
+
: merged
|
|
884
|
+
if (named.plugins === undefined || effective === undefined) return named
|
|
885
|
+
const candidates = [...(effective.plugins ?? [])]
|
|
886
|
+
const bases = [...(base.plugins ?? [])]
|
|
887
|
+
// A base plugin takes the first candidate of its own name that no earlier base plugin took, and
|
|
888
|
+
// candidates of other names never compete for it, so its pick is the candidate whose rank among
|
|
889
|
+
// its name equals the number of earlier base plugins sharing that name.
|
|
890
|
+
const chosen = bases.map((plugin, position) =>
|
|
891
|
+
isNamedPlugin(plugin)
|
|
892
|
+
? candidates
|
|
893
|
+
.flatMap((candidate, index) =>
|
|
894
|
+
isNamedPlugin(candidate) && candidate.name === plugin.name ? [index] : [],
|
|
895
|
+
)
|
|
896
|
+
.at(
|
|
897
|
+
bases
|
|
898
|
+
.slice(0, position)
|
|
899
|
+
.filter((earlier) => isNamedPlugin(earlier) && earlier.name === plugin.name).length,
|
|
900
|
+
)
|
|
901
|
+
: undefined,
|
|
902
|
+
)
|
|
903
|
+
return {
|
|
904
|
+
...named,
|
|
905
|
+
plugins: [
|
|
906
|
+
...bases.map((plugin, position) => {
|
|
907
|
+
const index = chosen[position]
|
|
908
|
+
return index === undefined ? plugin : (candidates[index] ?? plugin)
|
|
909
|
+
}),
|
|
910
|
+
...candidates.filter((_, index) => !chosen.includes(index)),
|
|
911
|
+
],
|
|
885
912
|
}
|
|
886
|
-
return { ...merged, plugins: selected }
|
|
887
913
|
}
|
|
888
914
|
|
|
889
915
|
function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
|
|
@@ -919,6 +945,7 @@ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
|
|
|
919
945
|
browser: {
|
|
920
946
|
enabled: true,
|
|
921
947
|
provider: playwright(browserOptions),
|
|
948
|
+
commands,
|
|
922
949
|
instances: [{ browser: 'chromium', headless: true }],
|
|
923
950
|
},
|
|
924
951
|
fileParallelism: false,
|
|
@@ -979,6 +1006,7 @@ export function srcVue(override?: UserConfig): UserConfig {
|
|
|
979
1006
|
browser: {
|
|
980
1007
|
enabled: true,
|
|
981
1008
|
provider: playwright(browserOptions),
|
|
1009
|
+
commands,
|
|
982
1010
|
instances: [{ browser: 'chromium', headless: true }],
|
|
983
1011
|
},
|
|
984
1012
|
fileParallelism: false,
|
|
@@ -1022,6 +1050,7 @@ export function srcBrowser(override?: UserConfig): UserConfig {
|
|
|
1022
1050
|
browser: {
|
|
1023
1051
|
enabled: true,
|
|
1024
1052
|
provider: playwright(browserOptions),
|
|
1053
|
+
commands,
|
|
1025
1054
|
instances: [{ browser: 'chromium', headless: true }],
|
|
1026
1055
|
},
|
|
1027
1056
|
fileParallelism: false,
|
|
@@ -1157,6 +1186,7 @@ export function srcBin(override?: UserConfig): UserConfig {
|
|
|
1157
1186
|
browser: {
|
|
1158
1187
|
enabled: true,
|
|
1159
1188
|
provider: playwright(browserOptions),
|
|
1189
|
+
commands,
|
|
1160
1190
|
instances: [{ browser: 'chromium', headless: true }],
|
|
1161
1191
|
},
|
|
1162
1192
|
fileParallelism: false,
|
|
@@ -1390,6 +1420,7 @@ export function appServer(override?: UserConfig): UserConfig {
|
|
|
1390
1420
|
{{global}} browser: {
|
|
1391
1421
|
enabled: true,
|
|
1392
1422
|
provider: playwright(browserOptions),
|
|
1423
|
+
commands,
|
|
1393
1424
|
instances: [{ browser: 'chromium', headless: true }],
|
|
1394
1425
|
},
|
|
1395
1426
|
},
|
|
@@ -1469,6 +1500,26 @@ export function service(override?: UserConfig): UserConfig {
|
|
|
1469
1500
|
}
|
|
1470
1501
|
return mergeOverride(project, override)
|
|
1471
1502
|
}
|
|
1503
|
+
`,
|
|
1504
|
+
studies: `// Authored study proofs run installed packages through bounded subprocesses and protocol fixtures,
|
|
1505
|
+
// so this project is isolated in its own gate script, test:studies.
|
|
1506
|
+
export function studies(override?: UserConfig): UserConfig {
|
|
1507
|
+
const project: UserConfig = {
|
|
1508
|
+
resolve,
|
|
1509
|
+
test: {
|
|
1510
|
+
name: { label: 'studies', color: 'red' },
|
|
1511
|
+
include: ['${STUDIES_TEST_INCLUDE}'],
|
|
1512
|
+
setupFiles: ['./tests/setup.ts'],
|
|
1513
|
+
environment: 'node',
|
|
1514
|
+
browser: { enabled: false },
|
|
1515
|
+
testTimeout: 120_000,
|
|
1516
|
+
hookTimeout: 120_000,
|
|
1517
|
+
fileParallelism: false,
|
|
1518
|
+
sequence: { groupOrder: 1 },
|
|
1519
|
+
},
|
|
1520
|
+
}
|
|
1521
|
+
return mergeOverride(project, override)
|
|
1522
|
+
}
|
|
1472
1523
|
`,
|
|
1473
1524
|
distribution: `export function distribution(override?: UserConfig): UserConfig {
|
|
1474
1525
|
const project: UserConfig = {
|
|
@@ -2058,34 +2109,33 @@ export function resolvePinnedBrowser(): string | undefined {
|
|
|
2058
2109
|
*/
|
|
2059
2110
|
export function resolveManagedBrowser(pinned: string): string | undefined {
|
|
2060
2111
|
if (isBrowserExecutable(pinned)) return pinned
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2112
|
+
// One \`dirname\` per path segment reaches the root from any path, and the nearest
|
|
2113
|
+
// ancestor named \`chromium-<revision>\` is the revision directory this build sits in.
|
|
2114
|
+
const directory = dirname(pinned)
|
|
2115
|
+
const ancestors = directory
|
|
2116
|
+
.split(/[\\\\/]/u)
|
|
2117
|
+
.reduce<string[]>((chain) => [...chain, dirname(chain.at(-1) ?? directory)], [directory])
|
|
2118
|
+
const revisionRoot = ancestors.find((ancestor) => CHROMIUM_ENTRY_PATTERN.test(basename(ancestor)))
|
|
2119
|
+
if (revisionRoot === undefined) return undefined
|
|
2068
2120
|
const browsersRoot = dirname(revisionRoot)
|
|
2069
2121
|
for (const alias of ['chromium', 'chromium.exe']) {
|
|
2070
2122
|
const candidate = resolvePath(browsersRoot, alias)
|
|
2071
2123
|
if (isBrowserExecutable(candidate)) return candidate
|
|
2072
2124
|
}
|
|
2073
|
-
let entries: readonly string[]
|
|
2074
2125
|
try {
|
|
2075
|
-
|
|
2126
|
+
const revisions = readdirSync(browsersRoot)
|
|
2127
|
+
.filter((entry) => CHROMIUM_ENTRY_PATTERN.test(entry))
|
|
2128
|
+
.sort(compareRevisions)
|
|
2129
|
+
for (const revision of revisions) {
|
|
2130
|
+
for (const layout of CHROMIUM_LAYOUTS) {
|
|
2131
|
+
const candidate = resolvePath(browsersRoot, revision, layout)
|
|
2132
|
+
if (isBrowserExecutable(candidate)) return candidate
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
return undefined
|
|
2076
2136
|
} catch {
|
|
2077
2137
|
return undefined
|
|
2078
2138
|
}
|
|
2079
|
-
const revisions = entries
|
|
2080
|
-
.filter((entry) => CHROMIUM_ENTRY_PATTERN.test(entry))
|
|
2081
|
-
.sort(compareRevisions)
|
|
2082
|
-
for (const revision of revisions) {
|
|
2083
|
-
for (const layout of CHROMIUM_LAYOUTS) {
|
|
2084
|
-
const candidate = resolvePath(browsersRoot, revision, layout)
|
|
2085
|
-
if (isBrowserExecutable(candidate)) return candidate
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
return undefined
|
|
2089
2139
|
}
|
|
2090
2140
|
|
|
2091
2141
|
/**
|
|
@@ -2103,16 +2153,14 @@ export function resolveManagedBrowser(pinned: string): string | undefined {
|
|
|
2103
2153
|
export function resolveBundledBrowser(platform: NodeJS.Platform, root: string): string | undefined {
|
|
2104
2154
|
if (platform !== 'linux') return undefined
|
|
2105
2155
|
for (const layout of BUNDLED_CHROMIUM_LAYOUTS) {
|
|
2106
|
-
let matches: readonly string[]
|
|
2107
2156
|
try {
|
|
2108
|
-
|
|
2157
|
+
for (const match of globSync(layout, { cwd: root }).sort(compareRevisions)) {
|
|
2158
|
+
const candidate = resolvePath(root, match)
|
|
2159
|
+
if (isBrowserExecutable(candidate)) return candidate
|
|
2160
|
+
}
|
|
2109
2161
|
} catch {
|
|
2110
2162
|
return undefined
|
|
2111
2163
|
}
|
|
2112
|
-
for (const match of [...matches].sort(compareRevisions)) {
|
|
2113
|
-
const candidate = resolvePath(root, match)
|
|
2114
|
-
if (isBrowserExecutable(candidate)) return candidate
|
|
2115
|
-
}
|
|
2116
2164
|
}
|
|
2117
2165
|
return undefined
|
|
2118
2166
|
}
|
|
@@ -2134,21 +2182,22 @@ export function resolveSystemBrowser(
|
|
|
2134
2182
|
environment: NodeJS.ProcessEnv,
|
|
2135
2183
|
): string | undefined {
|
|
2136
2184
|
if (platform !== 'linux' && platform !== 'darwin' && platform !== 'win32') return undefined
|
|
2137
|
-
const roots = new Set
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2185
|
+
const roots = new Set(
|
|
2186
|
+
platform === 'win32'
|
|
2187
|
+
? [
|
|
2188
|
+
...[
|
|
2189
|
+
environment.LOCALAPPDATA,
|
|
2190
|
+
environment.PROGRAMFILES,
|
|
2191
|
+
environment['PROGRAMFILES(X86)'],
|
|
2192
|
+
].flatMap((root) => (root !== undefined && root.length > 0 ? [root] : [])),
|
|
2193
|
+
...[environment.HOMEDRIVE].flatMap((homeDrive) =>
|
|
2194
|
+
homeDrive !== undefined && homeDrive.length > 0
|
|
2195
|
+
? [join(homeDrive, 'Program Files'), join(homeDrive, 'Program Files (x86)')]
|
|
2196
|
+
: [],
|
|
2197
|
+
),
|
|
2198
|
+
]
|
|
2199
|
+
: [],
|
|
2200
|
+
)
|
|
2152
2201
|
for (const browser of SYSTEM_BROWSER_CHANNELS) {
|
|
2153
2202
|
if (platform === 'win32') {
|
|
2154
2203
|
for (const root of roots) {
|
|
@@ -2237,6 +2286,10 @@ export function resolveBrowser(
|
|
|
2237
2286
|
launchOptions: { channel: resolveSystemBrowser(platform, environment) ?? fallback, ...launch },
|
|
2238
2287
|
}
|
|
2239
2288
|
}
|
|
2289
|
+
`,
|
|
2290
|
+
commands: `import type { BrowserConfigOptions } from 'vitest/node'
|
|
2291
|
+
|
|
2292
|
+
export const commands: Readonly<NonNullable<BrowserConfigOptions['commands']>> = Object.freeze({})
|
|
2240
2293
|
`
|
|
2241
2294
|
});
|
|
2242
2295
|
/**
|
|
@@ -2324,10 +2377,10 @@ const CAPTURE = inject('capture')
|
|
|
2324
2377
|
|
|
2325
2378
|
describe('{{application}} arrival journey', () => {
|
|
2326
2379
|
it('proves the declared arrival families', async () => {
|
|
2327
|
-
const families =
|
|
2328
|
-
const proven =
|
|
2380
|
+
const families = ['Journey', 'Refusal', 'Matrix', ...(CAPTURE ? ['Capture'] : [])]
|
|
2381
|
+
const proven: string[] = []
|
|
2329
2382
|
const states = ['{{application}}-arrival']
|
|
2330
|
-
const placed =
|
|
2383
|
+
const placed: string[] = []
|
|
2331
2384
|
const portfolio = createPortfolio({
|
|
2332
2385
|
states,
|
|
2333
2386
|
variants: VARIANTS,
|
|
@@ -2344,30 +2397,30 @@ describe('{{application}} arrival journey', () => {
|
|
|
2344
2397
|
})
|
|
2345
2398
|
.element()
|
|
2346
2399
|
expect(isRendered(heading)).toBe(true)
|
|
2347
|
-
proven.
|
|
2400
|
+
proven.push('Journey')
|
|
2348
2401
|
await portfolio.place('{{application}}-arrival')
|
|
2349
|
-
placed.
|
|
2402
|
+
placed.push('{{application}}-arrival')
|
|
2350
2403
|
|
|
2351
2404
|
for (const role of ACCESSIBLE_ROLES) expect(page.getByRole(role).elements()).toEqual([])
|
|
2352
2405
|
expect(readRefusal('Continue')).toBe(
|
|
2353
2406
|
'No interactive element has the accessible name "Continue"',
|
|
2354
2407
|
)
|
|
2355
|
-
proven.
|
|
2408
|
+
proven.push('Refusal')
|
|
2356
2409
|
|
|
2357
|
-
const measured =
|
|
2410
|
+
const measured: string[] = []
|
|
2358
2411
|
for (const variant of VARIANTS) {
|
|
2359
2412
|
await page.viewport(variant.width, variant.height)
|
|
2360
2413
|
expect(readStyle(heading, 'display')).toBe('block')
|
|
2361
2414
|
expect(window.innerWidth).toBe(variant.width)
|
|
2362
|
-
measured.
|
|
2415
|
+
measured.push(variant.name)
|
|
2363
2416
|
}
|
|
2364
|
-
expect(measured).toEqual(
|
|
2365
|
-
proven.
|
|
2417
|
+
expect(measured).toEqual(VARIANTS.map(({ name }) => name))
|
|
2418
|
+
proven.push('Matrix')
|
|
2366
2419
|
|
|
2367
2420
|
const files = expandCaptures(states, VARIANTS)
|
|
2368
2421
|
expect(portfolio.files).toEqual(files)
|
|
2369
2422
|
expect(new Set(files).size).toBe(states.length * VARIANTS.length)
|
|
2370
|
-
expect(placed).toEqual(
|
|
2423
|
+
expect(placed).toEqual(states)
|
|
2371
2424
|
const expected = CAPTURE
|
|
2372
2425
|
? expandCaptures(
|
|
2373
2426
|
states,
|
|
@@ -2377,7 +2430,7 @@ describe('{{application}} arrival journey', () => {
|
|
|
2377
2430
|
expect(portfolio.paths.map((path) => path.replaceAll('\\\\', '/').split('/').at(-1))).toEqual(
|
|
2378
2431
|
expected,
|
|
2379
2432
|
)
|
|
2380
|
-
if (CAPTURE) proven.
|
|
2433
|
+
if (CAPTURE) proven.push('Capture')
|
|
2381
2434
|
expect(proven).toEqual(families)
|
|
2382
2435
|
} finally {
|
|
2383
2436
|
{{cleanup}} const variant = VARIANTS.find(({ name }) => name === VARIANT)
|
|
@@ -2422,13 +2475,7 @@ describe('{{name}} entry', () => {
|
|
|
2422
2475
|
})
|
|
2423
2476
|
`,
|
|
2424
2477
|
styles: Object.freeze({
|
|
2425
|
-
module: `/**
|
|
2426
|
-
export interface SheetEntry {
|
|
2427
|
-
readonly rule: CSSRule
|
|
2428
|
-
readonly layer: string | undefined
|
|
2429
|
-
}
|
|
2430
|
-
|
|
2431
|
-
/** Describes an adopted stylesheet and its idempotent release operation. */
|
|
2478
|
+
module: `/** Describes an adopted stylesheet and its idempotent release operation. */
|
|
2432
2479
|
export interface SheetAdoption {
|
|
2433
2480
|
readonly sheet: CSSStyleSheet
|
|
2434
2481
|
release(): void
|
|
@@ -2460,42 +2507,36 @@ export function adoptSheet(text: string): SheetAdoption {
|
|
|
2460
2507
|
|
|
2461
2508
|
/**
|
|
2462
2509
|
* Reads layer statements and blocks in declaration order, including repeated names.
|
|
2463
|
-
* @param
|
|
2510
|
+
* @param source - The parsed sheet, or a grouping rule inside it.
|
|
2511
|
+
* @param layer - The qualified name of the layer that encloses \`source\`, when one does.
|
|
2464
2512
|
* @returns Qualified layer names, with an empty name for an anonymous layer.
|
|
2465
2513
|
* @example
|
|
2466
2514
|
* \`\`\`ts
|
|
2467
2515
|
* readLayerNames(new CSSStyleSheet()) // []
|
|
2468
2516
|
* \`\`\`
|
|
2469
2517
|
*/
|
|
2470
|
-
export function readLayerNames(
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
: layer + '.' + rule.name
|
|
2493
|
-
: layer
|
|
2494
|
-
for (const child of Array.from(rule.cssRules).reverse()) {
|
|
2495
|
-
pending.push({ rule: child, layer: parent })
|
|
2496
|
-
}
|
|
2497
|
-
}
|
|
2498
|
-
return names
|
|
2518
|
+
export function readLayerNames(
|
|
2519
|
+
source: CSSStyleSheet | CSSGroupingRule,
|
|
2520
|
+
layer?: string,
|
|
2521
|
+
): readonly string[] {
|
|
2522
|
+
return Array.from(source.cssRules).flatMap((rule) => [
|
|
2523
|
+
...(rule instanceof CSSLayerStatementRule
|
|
2524
|
+
? rule.nameList
|
|
2525
|
+
: rule instanceof CSSLayerBlockRule
|
|
2526
|
+
? [rule.name]
|
|
2527
|
+
: []
|
|
2528
|
+
).map((name) => (layer === undefined ? name : layer + '.' + name)),
|
|
2529
|
+
...(rule instanceof CSSGroupingRule
|
|
2530
|
+
? readLayerNames(
|
|
2531
|
+
rule,
|
|
2532
|
+
rule instanceof CSSLayerBlockRule
|
|
2533
|
+
? layer === undefined
|
|
2534
|
+
? rule.name
|
|
2535
|
+
: layer + '.' + rule.name
|
|
2536
|
+
: layer,
|
|
2537
|
+
)
|
|
2538
|
+
: []),
|
|
2539
|
+
])
|
|
2499
2540
|
}
|
|
2500
2541
|
`,
|
|
2501
2542
|
proof: `import type { SheetAdoption } from './setupStyles.js'
|
|
@@ -2785,15 +2826,17 @@ function isList(value: unknown): value is readonly unknown[] {
|
|
|
2785
2826
|
// thing: an array falls through the former and keeps the latter.
|
|
2786
2827
|
function isPackageTarget(target: string): boolean {
|
|
2787
2828
|
if (!target.startsWith('./')) return false
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2829
|
+
const refused = ['.', '..', 'node_modules']
|
|
2830
|
+
return target
|
|
2831
|
+
.slice(2)
|
|
2832
|
+
.split(/[\\\\/]/u)
|
|
2833
|
+
.every((segment) => {
|
|
2834
|
+
try {
|
|
2835
|
+
return !refused.includes(decodeURIComponent(segment).toLowerCase())
|
|
2836
|
+
} catch {
|
|
2837
|
+
return !refused.includes(segment.toLowerCase())
|
|
2838
|
+
}
|
|
2839
|
+
})
|
|
2797
2840
|
}
|
|
2798
2841
|
|
|
2799
2842
|
function readJson(path: string): unknown {
|
|
@@ -2818,11 +2861,11 @@ function readOutput(result: SpawnSyncReturns<string>): string {
|
|
|
2818
2861
|
return \`\${result.stdout ?? ''}\${result.stderr ?? ''}\`.trim()
|
|
2819
2862
|
}
|
|
2820
2863
|
|
|
2821
|
-
function runNpm(args: readonly string[], cwd: string): SpawnSyncReturns<string> {
|
|
2864
|
+
function runNpm(args: readonly string[], cwd: string, scratch: string): SpawnSyncReturns<string> {
|
|
2822
2865
|
return spawnSync(NPM, [...args], {
|
|
2823
2866
|
cwd,
|
|
2824
2867
|
encoding: 'utf8',
|
|
2825
|
-
env: { ...process.env, npm_config_cache: join(
|
|
2868
|
+
env: { ...process.env, npm_config_cache: join(scratch, 'cache') },
|
|
2826
2869
|
shell: SHELL,
|
|
2827
2870
|
windowsHide: true,
|
|
2828
2871
|
})
|
|
@@ -2877,11 +2920,14 @@ function matchesFile(path: string): boolean {
|
|
|
2877
2920
|
// the containing condition or fallback list unresolved, so the walk continues.
|
|
2878
2921
|
function targetToDeclaration(target: string, installed: string): string | undefined {
|
|
2879
2922
|
if (!isPackageTarget(target)) return undefined
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2923
|
+
const declaration = target.endsWith('.cjs')
|
|
2924
|
+
? \`\${target.slice(0, -4)}.d.cts\`
|
|
2925
|
+
: target.endsWith('.mjs')
|
|
2926
|
+
? \`\${target.slice(0, -4)}.d.mts\`
|
|
2927
|
+
: target.endsWith('.js')
|
|
2928
|
+
? \`\${target.slice(0, -3)}.d.ts\`
|
|
2929
|
+
: target
|
|
2930
|
+
if (declaration === target && !isDeclaration(target)) return undefined
|
|
2885
2931
|
return matchesFile(join(installed, declaration)) ? declaration : undefined
|
|
2886
2932
|
}
|
|
2887
2933
|
|
|
@@ -2913,21 +2959,22 @@ function resolveDeclaration(
|
|
|
2913
2959
|
// physical nested manifest starts a scope even when it omits \`type\` or cannot be
|
|
2914
2960
|
// parsed. A directory at that spelling is not a manifest, so the walk continues.
|
|
2915
2961
|
function readPackageType(installed: string, target: string): unknown {
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
const
|
|
2929
|
-
|
|
2930
|
-
|
|
2962
|
+
// One \`dirname\` per path segment reaches the root from any path. The walk ends at the
|
|
2963
|
+
// installed package, so no scope above it is consulted.
|
|
2964
|
+
const start = dirname(join(installed, target))
|
|
2965
|
+
const chain = start
|
|
2966
|
+
.split(/[\\\\/]/u)
|
|
2967
|
+
.reduce<string[]>((climbed) => [...climbed, dirname(climbed.at(-1) ?? start)], [start])
|
|
2968
|
+
const end = chain.indexOf(installed)
|
|
2969
|
+
const scope = chain
|
|
2970
|
+
.slice(0, end === -1 ? chain.length : end + 1)
|
|
2971
|
+
.find((directory) => matchesFile(join(directory, 'package.json')))
|
|
2972
|
+
if (scope === undefined) return undefined
|
|
2973
|
+
try {
|
|
2974
|
+
const manifest = readJson(join(scope, 'package.json'))
|
|
2975
|
+
return isRecord(manifest) ? manifest.type : undefined
|
|
2976
|
+
} catch {
|
|
2977
|
+
return undefined
|
|
2931
2978
|
}
|
|
2932
2979
|
}
|
|
2933
2980
|
|
|
@@ -3096,16 +3143,13 @@ function checkProject(stage: Stage, project: string): readonly string[] {
|
|
|
3096
3143
|
if (refused.length > 0) {
|
|
3097
3144
|
throw new Error(\`The consumer compiler wrote \${refused} to its error stream\`)
|
|
3098
3145
|
}
|
|
3099
|
-
const
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
reported[reported.length - 1] = \`\${last} \${line.trim()}\`
|
|
3107
|
-
continue
|
|
3108
|
-
}
|
|
3146
|
+
const lines = \`\${result.stdout ?? ''}\`.split(/\\r\\n|\\n/u).filter((line) => line.trim().length > 0)
|
|
3147
|
+
// An elaborated diagnostic prints its detail on indented lines under its own
|
|
3148
|
+
// first line, so each of those joins the diagnostic it elaborates. The first line
|
|
3149
|
+
// has no diagnostic above it to join, so it opens one whatever its indentation.
|
|
3150
|
+
const heads = lines.flatMap((line, index) => (index === 0 || !/^\\s/u.test(line) ? [index] : []))
|
|
3151
|
+
const reported = heads.map((head, position) => {
|
|
3152
|
+
const line = lines[head] ?? ''
|
|
3109
3153
|
const located = DIAGNOSTIC_PATTERN.exec(line)?.[1]
|
|
3110
3154
|
if (located === undefined) {
|
|
3111
3155
|
throw new Error(\`The consumer compiler reported \${line}, which names no location\`)
|
|
@@ -3113,8 +3157,11 @@ function checkProject(stage: Stage, project: string): readonly string[] {
|
|
|
3113
3157
|
if (resolve(stage.consumer, located) === project) {
|
|
3114
3158
|
throw new Error(\`The scratch project is itself at fault: \${line}\`)
|
|
3115
3159
|
}
|
|
3116
|
-
|
|
3117
|
-
|
|
3160
|
+
return [
|
|
3161
|
+
line,
|
|
3162
|
+
...lines.slice(head + 1, heads[position + 1] ?? lines.length).map((detail) => detail.trim()),
|
|
3163
|
+
].join(' ')
|
|
3164
|
+
})
|
|
3118
3165
|
if (reported.length === 0 && result.status !== 0) {
|
|
3119
3166
|
throw new Error(\`The consumer compiler refused the project: \${readOutput(result)}\`)
|
|
3120
3167
|
}
|
|
@@ -3151,13 +3198,14 @@ const surfaced: Record<keyof typeof published, true> = declared
|
|
|
3151
3198
|
// One consumer module importing every installed entry, written where its own
|
|
3152
3199
|
// resolution finds the installed package.
|
|
3153
3200
|
function writeConsumerProbe(stage: Stage, path: string, specifiers: readonly string[]): void {
|
|
3154
|
-
const
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3201
|
+
const modules = specifiers.map((specifier, index) => ({
|
|
3202
|
+
binding: \`entry\${String(index)}\`,
|
|
3203
|
+
specifier,
|
|
3204
|
+
}))
|
|
3205
|
+
const bindings = modules.map(
|
|
3206
|
+
({ binding, specifier }) => \`import * as \${binding} from \${JSON.stringify(specifier)}\`,
|
|
3207
|
+
)
|
|
3208
|
+
const names = modules.map(({ binding }) => binding)
|
|
3161
3209
|
const source = \`\${bindings.join('\\n')}\\nexport const surface = [\${names.join(', ')}]\\n\`
|
|
3162
3210
|
writeFile(join(stage.consumer, path), source)
|
|
3163
3211
|
}
|
|
@@ -3178,11 +3226,11 @@ function driveRuntime(stage: Stage, specifier: string, driver: string): readonly
|
|
|
3178
3226
|
// Pack this workspace, install the archive into an isolated consumer, and read the
|
|
3179
3227
|
// published surface back off the installed tree. Every later claim reads this
|
|
3180
3228
|
// result, so a failure here is raised where it happens rather than once per entry.
|
|
3181
|
-
function buildStage(): Stage {
|
|
3182
|
-
const packed = join(
|
|
3183
|
-
const consumer = join(
|
|
3229
|
+
function buildStage(scratch: string): Stage {
|
|
3230
|
+
const packed = join(scratch, 'packed')
|
|
3231
|
+
const consumer = join(scratch, 'consumer')
|
|
3184
3232
|
mkdirSync(packed, { recursive: true })
|
|
3185
|
-
const pack = runNpm(['pack', '--ignore-scripts', '--pack-destination', packed], ROOT)
|
|
3233
|
+
const pack = runNpm(['pack', '--ignore-scripts', '--pack-destination', packed], ROOT, scratch)
|
|
3186
3234
|
if (pack.status !== 0) throw new Error(\`npm pack refused this workspace: \${readOutput(pack)}\`)
|
|
3187
3235
|
const archives = readdirSync(packed).filter((name) => name.endsWith('.tgz'))
|
|
3188
3236
|
const archive = archives[0]
|
|
@@ -3195,6 +3243,7 @@ function buildStage(): Stage {
|
|
|
3195
3243
|
const install = runNpm(
|
|
3196
3244
|
['install', '--ignore-scripts', '--no-audit', '--no-fund', join(packed, archive)],
|
|
3197
3245
|
consumer,
|
|
3246
|
+
scratch,
|
|
3198
3247
|
)
|
|
3199
3248
|
if (install.status !== 0) {
|
|
3200
3249
|
throw new Error(\`Installing the packed archive failed: \${readOutput(install)}\`)
|
|
@@ -3205,16 +3254,9 @@ function buildStage(): Stage {
|
|
|
3205
3254
|
if (!isRecord(manifest) || !isRecord(manifest.exports)) {
|
|
3206
3255
|
throw new Error('The installed manifest publishes no exports map')
|
|
3207
3256
|
}
|
|
3208
|
-
const entries
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
const undeclared: string[] = []
|
|
3212
|
-
const excluded: string[] = []
|
|
3213
|
-
for (const [subpath, entry] of Object.entries(manifest.exports)) {
|
|
3214
|
-
const files = collectTargets(entry)
|
|
3215
|
-
targets.push(...files)
|
|
3216
|
-
subpaths.push(subpath)
|
|
3217
|
-
const declaration = readDeclaration(entry, installed)
|
|
3257
|
+
const readings = Object.entries(manifest.exports).map(([subpath, mapping]) => {
|
|
3258
|
+
const files = collectTargets(mapping)
|
|
3259
|
+
const declaration = readDeclaration(mapping, installed)
|
|
3218
3260
|
// A subpath resolving no declaration is partitioned rather than dropped. It is a
|
|
3219
3261
|
// defect when a runtime loads one of its targets for names, because a consumer
|
|
3220
3262
|
// importing it compiles against nothing under \`node16\`. It is an excluded
|
|
@@ -3225,21 +3267,19 @@ function buildStage(): Stage {
|
|
|
3225
3267
|
declaration.commonjs === undefined &&
|
|
3226
3268
|
declaration.browser === undefined
|
|
3227
3269
|
) {
|
|
3228
|
-
|
|
3229
|
-
else excluded.push(subpath)
|
|
3230
|
-
continue
|
|
3270
|
+
return { subpath, files, entry: undefined }
|
|
3231
3271
|
}
|
|
3232
|
-
const importTarget = resolveTarget(
|
|
3233
|
-
const requireTarget = resolveTarget(
|
|
3234
|
-
const browserTarget = resolveTarget(
|
|
3235
|
-
const browsable = resolvesBrowser(
|
|
3272
|
+
const importTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.module)
|
|
3273
|
+
const requireTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.commonjs)
|
|
3274
|
+
const browserTarget = resolveTarget(mapping, RUNTIME_CONDITIONS.browser)
|
|
3275
|
+
const browsable = resolvesBrowser(mapping)
|
|
3236
3276
|
const shadowed = browsable && requireTarget === browserTarget
|
|
3237
3277
|
const requirable = requireTarget !== undefined && !shadowed
|
|
3238
|
-
const loadable = requirable && resolvesCommonJS(
|
|
3239
|
-
|
|
3278
|
+
const loadable = requirable && resolvesCommonJS(mapping, installed)
|
|
3279
|
+
const entry: Entry = {
|
|
3240
3280
|
subpath,
|
|
3241
3281
|
specifier: subpath === '.' ? name : \`\${name}\${subpath.slice(1)}\`,
|
|
3242
|
-
mapping
|
|
3282
|
+
mapping,
|
|
3243
3283
|
declaration: {
|
|
3244
3284
|
importable: declaration.module !== undefined,
|
|
3245
3285
|
requirable: declaration.commonjs !== undefined,
|
|
@@ -3249,54 +3289,92 @@ function buildStage(): Stage {
|
|
|
3249
3289
|
importable: importTarget !== undefined && !(browsable && importTarget === browserTarget),
|
|
3250
3290
|
requirable,
|
|
3251
3291
|
loadable,
|
|
3252
|
-
}
|
|
3253
|
-
|
|
3292
|
+
}
|
|
3293
|
+
return { subpath, files, entry }
|
|
3294
|
+
})
|
|
3295
|
+
const entries = readings.flatMap(({ entry }) => (entry === undefined ? [] : [entry]))
|
|
3296
|
+
const targets = readings.flatMap(({ files }) => files)
|
|
3297
|
+
const subpaths = readings.map(({ subpath }) => subpath)
|
|
3298
|
+
const undeclared = readings
|
|
3299
|
+
.filter(({ entry, files }) => entry === undefined && files.some(isModule))
|
|
3300
|
+
.map(({ subpath }) => subpath)
|
|
3301
|
+
const excluded = readings
|
|
3302
|
+
.filter(({ entry, files }) => entry === undefined && !files.some(isModule))
|
|
3303
|
+
.map(({ subpath }) => subpath)
|
|
3254
3304
|
return { consumer, installed, archives, entries, subpaths, undeclared, excluded, targets }
|
|
3255
3305
|
}
|
|
3256
3306
|
|
|
3257
|
-
|
|
3258
|
-
|
|
3307
|
+
// One file's run: the scratch directory and the staged consumer, which is absent when the
|
|
3308
|
+
// registry could not be reached.
|
|
3309
|
+
interface DistributionRun {
|
|
3310
|
+
readonly scratch: string
|
|
3311
|
+
readonly stage: Stage | undefined
|
|
3312
|
+
}
|
|
3313
|
+
|
|
3314
|
+
// The run the start hook binds once for this file and the stop hook releases.
|
|
3315
|
+
class DistributionSuite {
|
|
3316
|
+
#run: DistributionRun | undefined
|
|
3317
|
+
|
|
3318
|
+
get scratch(): string {
|
|
3319
|
+
if (this.#run === undefined) {
|
|
3320
|
+
throw new Error('The distribution setup has not allocated its scratch directory')
|
|
3321
|
+
}
|
|
3322
|
+
return this.#run.scratch
|
|
3323
|
+
}
|
|
3259
3324
|
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
throw new Error('The distribution setup has not allocated its scratch directory')
|
|
3325
|
+
get stage(): Stage | undefined {
|
|
3326
|
+
return this.#run?.stage
|
|
3263
3327
|
}
|
|
3264
|
-
return scratch
|
|
3265
|
-
}
|
|
3266
3328
|
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3329
|
+
start(): void {
|
|
3330
|
+
if (this.#run !== undefined) {
|
|
3331
|
+
throw new Error('The distribution setup has already allocated its scratch directory')
|
|
3332
|
+
}
|
|
3333
|
+
const scratch = mkdtempSync(join(tmpdir(), 'distribution-'))
|
|
3334
|
+
this.#run = { scratch, stage: openStage(scratch) }
|
|
3335
|
+
}
|
|
3272
3336
|
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3337
|
+
destroy(): void {
|
|
3338
|
+
if (this.#run !== undefined) {
|
|
3339
|
+
rmSync(this.#run.scratch, { force: true, recursive: true, maxRetries: 3, retryDelay: 100 })
|
|
3340
|
+
}
|
|
3341
|
+
this.#run = undefined
|
|
3276
3342
|
}
|
|
3277
|
-
}
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3345
|
+
const DISTRIBUTION_SUITE = new DistributionSuite()
|
|
3346
|
+
|
|
3347
|
+
beforeAll(() => DISTRIBUTION_SUITE.start())
|
|
3348
|
+
|
|
3349
|
+
afterAll(() => DISTRIBUTION_SUITE.destroy())
|
|
3278
3350
|
|
|
3279
3351
|
// Installing the packed archive resolves its own runtime dependencies, so an
|
|
3280
3352
|
// unreachable registry leaves nothing to measure. Under release that is the gate
|
|
3281
3353
|
// failing; anywhere else the suite skips and names the mechanism it wanted.
|
|
3282
|
-
function openStage(): Stage | undefined {
|
|
3354
|
+
function openStage(scratch: string): Stage | undefined {
|
|
3283
3355
|
try {
|
|
3284
|
-
|
|
3356
|
+
mkdirSync(join(scratch, 'cache'), { recursive: true })
|
|
3357
|
+
if (runNpm(PING, ROOT, scratch).status !== 0) {
|
|
3285
3358
|
if (!RELEASE) return undefined
|
|
3286
3359
|
throw new Error(
|
|
3287
3360
|
'The release gate requires a reachable npm registry, and npm ping did not answer',
|
|
3288
3361
|
)
|
|
3289
3362
|
}
|
|
3290
|
-
return buildStage()
|
|
3363
|
+
return buildStage(scratch)
|
|
3291
3364
|
} catch (error) {
|
|
3292
|
-
rmSync(
|
|
3365
|
+
rmSync(scratch, {
|
|
3366
|
+
force: true,
|
|
3367
|
+
recursive: true,
|
|
3368
|
+
maxRetries: 3,
|
|
3369
|
+
retryDelay: 100,
|
|
3370
|
+
})
|
|
3293
3371
|
throw error
|
|
3294
3372
|
}
|
|
3295
3373
|
}
|
|
3296
3374
|
|
|
3297
3375
|
describe('distribution classifiers', () => {
|
|
3298
3376
|
it('classifies synthetic export mappings without a registry stage', () => {
|
|
3299
|
-
const root = join(
|
|
3377
|
+
const root = join(DISTRIBUTION_SUITE.scratch, 'classifiers')
|
|
3300
3378
|
writeFile(
|
|
3301
3379
|
join(root, 'package.json'),
|
|
3302
3380
|
JSON.stringify({
|
|
@@ -3365,6 +3443,7 @@ describe('distribution classifiers', () => {
|
|
|
3365
3443
|
// The staged consumer, or a skip naming what the run could not reach. \`it.skipIf\`
|
|
3366
3444
|
// carries no reason, so the gate sits here where the test context can state one.
|
|
3367
3445
|
function requireStage(context: TestContext): Stage {
|
|
3446
|
+
const staged = DISTRIBUTION_SUITE.stage
|
|
3368
3447
|
if (staged === undefined) {
|
|
3369
3448
|
return context.skip('\`npm ping\` did not answer, so nothing was packed or installed')
|
|
3370
3449
|
}
|
|
@@ -3429,28 +3508,24 @@ describe('installed package consumer', () => {
|
|
|
3429
3508
|
it('compiles a consumer under every module resolution [requires the registry]', (context) => {
|
|
3430
3509
|
const stage = requireStage(context)
|
|
3431
3510
|
const name = readManifestName(join(stage.installed, 'package.json'))
|
|
3432
|
-
const
|
|
3433
|
-
|
|
3434
|
-
for (const driver of RESOLUTIONS) {
|
|
3435
|
-
for (const [extension, format] of FORMATS) {
|
|
3511
|
+
const readings = RESOLUTIONS.flatMap((driver) =>
|
|
3512
|
+
FORMATS.flatMap(([extension, format]) => {
|
|
3436
3513
|
const written = selectEntries(stage.entries, driver.conditions[format])
|
|
3437
|
-
if (written.length === 0)
|
|
3514
|
+
if (written.length === 0) return []
|
|
3438
3515
|
const label = \`\${driver.label}.\${extension}\`
|
|
3439
3516
|
const probe = \`probe.\${label}\`
|
|
3440
3517
|
const specifiers = written.map((entry) => entry.specifier)
|
|
3441
3518
|
writeConsumerProbe(stage, probe, specifiers)
|
|
3442
3519
|
const project = writeProject(stage, probe, driver, [\`./\${probe}\`])
|
|
3443
|
-
|
|
3444
|
-
reported.push(\`\${label}: \${message}\`)
|
|
3445
|
-
}
|
|
3520
|
+
const messages = checkProject(stage, project).map((message) => \`\${label}: \${message}\`)
|
|
3446
3521
|
const control = \`control.\${label}\`
|
|
3447
3522
|
writeConsumerProbe(stage, control, [\`\${name}\${ABSENT_SUBPATH}\`])
|
|
3448
3523
|
const refused = writeProject(stage, control, driver, [\`./\${control}\`])
|
|
3449
|
-
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
expect(
|
|
3453
|
-
expect(silent).toStrictEqual([])
|
|
3524
|
+
return [{ messages, silent: checkProject(stage, refused).length === 0 ? [label] : [] }]
|
|
3525
|
+
}),
|
|
3526
|
+
)
|
|
3527
|
+
expect(readings.flatMap(({ messages }) => messages)).toStrictEqual([])
|
|
3528
|
+
expect(readings.flatMap(({ silent }) => silent)).toStrictEqual([])
|
|
3454
3529
|
})
|
|
3455
3530
|
{{guard}}})
|
|
3456
3531
|
|
|
@@ -4150,6 +4225,7 @@ var isBlueprint = recordOf({
|
|
|
4150
4225
|
conformance: isBoolean,
|
|
4151
4226
|
service: isBoolean,
|
|
4152
4227
|
vendors: andOf(isCollection, arrayOf(isString)),
|
|
4228
|
+
studies: isBoolean,
|
|
4153
4229
|
global: isBoolean,
|
|
4154
4230
|
showcase: isBoolean,
|
|
4155
4231
|
journey: isBoolean,
|
|
@@ -4566,9 +4642,8 @@ function parseCompilerOptions(value) {
|
|
|
4566
4642
|
* ```
|
|
4567
4643
|
*/
|
|
4568
4644
|
function bytesToHex(bytes) {
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
return hex;
|
|
4645
|
+
const digits = Array.from({ length: 256 }, (_, value) => value.toString(16).padStart(2, "0"));
|
|
4646
|
+
return Iterator.from(bytes).map((byte) => digits[byte] ?? "").toArray().join("");
|
|
4572
4647
|
}
|
|
4573
4648
|
/**
|
|
4574
4649
|
* Encodes text as the exact lowercase hexadecimal form of its UTF-8 bytes.
|
|
@@ -4613,12 +4688,68 @@ function contentToHex(content) {
|
|
|
4613
4688
|
* ```
|
|
4614
4689
|
*/
|
|
4615
4690
|
function computeBytes(content) {
|
|
4616
|
-
|
|
4617
|
-
for (const character of content) {
|
|
4691
|
+
return content[Symbol.iterator]().reduce((bytes, character) => {
|
|
4618
4692
|
const code = character.codePointAt(0) ?? 0;
|
|
4619
|
-
bytes
|
|
4693
|
+
return bytes + (code <= 127 ? 1 : code <= 2047 ? 2 : code <= 65535 ? 3 : 4);
|
|
4694
|
+
}, 0);
|
|
4695
|
+
}
|
|
4696
|
+
/**
|
|
4697
|
+
* Computes the sum of a list of numbers.
|
|
4698
|
+
*
|
|
4699
|
+
* @param values - The numbers to add.
|
|
4700
|
+
* @returns The sum, and `0` for no numbers.
|
|
4701
|
+
*
|
|
4702
|
+
* @remarks
|
|
4703
|
+
* The one place a running tally is derived from the amounts that make it up, so a
|
|
4704
|
+
* byte budget is the allowance less what was spent rather than a counter that is
|
|
4705
|
+
* reassigned as reads land.
|
|
4706
|
+
*
|
|
4707
|
+
* @example
|
|
4708
|
+
* ```ts
|
|
4709
|
+
* import { computeTotal } from '@orkestrel/scaffold'
|
|
4710
|
+
*
|
|
4711
|
+
* computeTotal([65536, 65536, 12]) // 131084
|
|
4712
|
+
* computeTotal([]) // 0
|
|
4713
|
+
* ```
|
|
4714
|
+
*/
|
|
4715
|
+
function computeTotal(values) {
|
|
4716
|
+
return values.reduce((total, value) => total + value, 0);
|
|
4717
|
+
}
|
|
4718
|
+
/**
|
|
4719
|
+
* Yields the answer to each value of a source and ends after the first refused answer.
|
|
4720
|
+
*
|
|
4721
|
+
* @param source - The values to answer, requested one at a time as the answers are read.
|
|
4722
|
+
* @param answer - Answers one value, or returns `undefined` to refuse it.
|
|
4723
|
+
* @returns A generator of the answers in source order, whose last answer is the first refusal when
|
|
4724
|
+
* the source holds one.
|
|
4725
|
+
* @throws Thrown when `answer` throws for a value, with that error, or when closing `source` after
|
|
4726
|
+
* a refusal throws, with the close's error.
|
|
4727
|
+
*
|
|
4728
|
+
* @remarks
|
|
4729
|
+
* The body is a `for…of` loop, so the source's iterator is requested once, when the first answer
|
|
4730
|
+
* is read, and stepped only as the answers are read: a length the source reports never bounds the
|
|
4731
|
+
* read, a hole reads as an `undefined` value, and an infinite source is read as far as the first
|
|
4732
|
+
* refusal. The iterator is closed after a refusal with a normal completion, so a raising close
|
|
4733
|
+
* surfaces, and is closed when `answer` throws with a throw completion, so the error from `answer`
|
|
4734
|
+
* wins. An iterator that ends is left alone. A caller that stops at a refusal and keeps what came
|
|
4735
|
+
* before it reads the answers into a list and checks that none is `undefined`.
|
|
4736
|
+
*
|
|
4737
|
+
* @example
|
|
4738
|
+
* ```ts
|
|
4739
|
+
* import { iterateAnswers } from '@orkestrel/scaffold'
|
|
4740
|
+
*
|
|
4741
|
+
* const halve = (value: number): number | undefined => (value % 2 === 0 ? value / 2 : undefined)
|
|
4742
|
+
*
|
|
4743
|
+
* Array.from(iterateAnswers([2, 4, 5, 6], halve)).length // 3
|
|
4744
|
+
* Array.from(iterateAnswers([2, 4], halve)) // [1, 2]
|
|
4745
|
+
* ```
|
|
4746
|
+
*/
|
|
4747
|
+
function* iterateAnswers(source, answer) {
|
|
4748
|
+
for (const value of source) {
|
|
4749
|
+
const answered = answer(value);
|
|
4750
|
+
yield answered;
|
|
4751
|
+
if (answered === void 0) return;
|
|
4620
4752
|
}
|
|
4621
|
-
return bytes;
|
|
4622
4753
|
}
|
|
4623
4754
|
/**
|
|
4624
4755
|
* Computes the deterministic content identity of text.
|
|
@@ -4645,9 +4776,10 @@ function computeBytes(content) {
|
|
|
4645
4776
|
* ```
|
|
4646
4777
|
*/
|
|
4647
4778
|
function computeHash(text) {
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4779
|
+
return text[Symbol.iterator]().reduce((digest, character) => {
|
|
4780
|
+
const first = BigInt.asUintN(64, (digest ^ BigInt(character.charCodeAt(0))) * 1099511628211n);
|
|
4781
|
+
return character.length === 1 ? first : BigInt.asUintN(64, (first ^ BigInt(character.charCodeAt(1))) * 1099511628211n);
|
|
4782
|
+
}, 14695981039346656037n).toString(16).padStart(16, "0");
|
|
4651
4783
|
}
|
|
4652
4784
|
/**
|
|
4653
4785
|
* Tests whether a path instructs or wires an agent rather than the toolchain.
|
|
@@ -4833,28 +4965,23 @@ function inferGroup(path) {
|
|
|
4833
4965
|
* ```
|
|
4834
4966
|
*/
|
|
4835
4967
|
function serializeTypeScriptString(value) {
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
index += 1;
|
|
4854
|
-
} else serialized += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
4855
|
-
} else serialized += character;
|
|
4856
|
-
}
|
|
4857
|
-
return `${serialized}'`;
|
|
4968
|
+
const escapes = {
|
|
4969
|
+
"'": "\\'",
|
|
4970
|
+
"\\": "\\\\",
|
|
4971
|
+
"\b": "\\b",
|
|
4972
|
+
"\f": "\\f",
|
|
4973
|
+
"\n": "\\n",
|
|
4974
|
+
"\r": "\\r",
|
|
4975
|
+
" ": "\\t",
|
|
4976
|
+
"\u2028": "\\u2028",
|
|
4977
|
+
"\u2029": "\\u2029"
|
|
4978
|
+
};
|
|
4979
|
+
return `'${Array.from(value, (character) => {
|
|
4980
|
+
const escape = escapes[character];
|
|
4981
|
+
if (escape !== void 0) return escape;
|
|
4982
|
+
const code = character.charCodeAt(0);
|
|
4983
|
+
return character.length === 1 && (code < 32 || code >= 55296 && code <= 57343) ? `\\u${code.toString(16).padStart(4, "0")}` : character;
|
|
4984
|
+
}).join("")}'`;
|
|
4858
4985
|
}
|
|
4859
4986
|
/**
|
|
4860
4987
|
* Derives the guide mirror path a package name answers for.
|
|
@@ -5186,21 +5313,18 @@ function matchesDriftReachability(ownership, finding) {
|
|
|
5186
5313
|
*/
|
|
5187
5314
|
function catalogToLayers(entries) {
|
|
5188
5315
|
const published = new Set(entries.filter((entry) => entry.lookup === "found").map((entry) => entry.name));
|
|
5189
|
-
const
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
const
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
layers.push(ready.sort());
|
|
5202
|
-
}
|
|
5203
|
-
return layers;
|
|
5316
|
+
const found = Iterator.from(entries).flatMap((entry) => entry.lookup === "found" ? [[entry.name, [...entry.dependencies, ...entry.peers].map((dependency) => dependency.name).filter((name) => published.has(name))]] : []).toArray();
|
|
5317
|
+
const dependencies = new Map(found);
|
|
5318
|
+
return found.reduce((state) => {
|
|
5319
|
+
const ready = [...dependencies].filter(([name, edges]) => !state.placed.has(name) && edges.every((edge) => state.placed.has(edge))).map(([name]) => name).sort();
|
|
5320
|
+
return ready.length === 0 ? state : {
|
|
5321
|
+
layers: [...state.layers, ready],
|
|
5322
|
+
placed: /* @__PURE__ */ new Set([...state.placed, ...ready])
|
|
5323
|
+
};
|
|
5324
|
+
}, {
|
|
5325
|
+
layers: [],
|
|
5326
|
+
placed: /* @__PURE__ */ new Set()
|
|
5327
|
+
}).layers;
|
|
5204
5328
|
}
|
|
5205
5329
|
/**
|
|
5206
5330
|
* Projects a plan into its tally by artifact origin.
|
|
@@ -5223,12 +5347,9 @@ function catalogToLayers(entries) {
|
|
|
5223
5347
|
* ```
|
|
5224
5348
|
*/
|
|
5225
5349
|
function planToSummary(plan) {
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
for (const artifact of plan.artifacts) if (artifact.origin === "host") host += 1;
|
|
5230
|
-
else if (artifact.origin === "template") template += 1;
|
|
5231
|
-
else computed += 1;
|
|
5350
|
+
const origins = Iterator.from(plan.artifacts).map((artifact) => artifact.origin).toArray();
|
|
5351
|
+
const host = origins.filter((origin) => origin === "host").length;
|
|
5352
|
+
const template = origins.filter((origin) => origin === "template").length;
|
|
5232
5353
|
return {
|
|
5233
5354
|
name: plan.blueprint.name,
|
|
5234
5355
|
src: plan.blueprint.src,
|
|
@@ -5236,7 +5357,7 @@ function planToSummary(plan) {
|
|
|
5236
5357
|
groups: plan.groups,
|
|
5237
5358
|
host,
|
|
5238
5359
|
template,
|
|
5239
|
-
computed
|
|
5360
|
+
computed: origins.length - host - template
|
|
5240
5361
|
};
|
|
5241
5362
|
}
|
|
5242
5363
|
/**
|
|
@@ -5324,8 +5445,8 @@ function compareVersions(left, right) {
|
|
|
5324
5445
|
if (second !== void 0) return -1;
|
|
5325
5446
|
return compareValues(left, right);
|
|
5326
5447
|
}
|
|
5327
|
-
for (
|
|
5328
|
-
const order = compareValues(
|
|
5448
|
+
for (const [index, component] of first.entries()) {
|
|
5449
|
+
const order = compareValues(component, second[index] ?? 0);
|
|
5329
5450
|
if (order !== 0) return order;
|
|
5330
5451
|
}
|
|
5331
5452
|
return 0;
|
|
@@ -5476,35 +5597,17 @@ function manifestToDependencies(manifest) {
|
|
|
5476
5597
|
development: [],
|
|
5477
5598
|
peer: []
|
|
5478
5599
|
};
|
|
5479
|
-
const runtime = []
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
},
|
|
5491
|
-
{
|
|
5492
|
-
name: "peerDependencies",
|
|
5493
|
-
dependencies: peer
|
|
5494
|
-
}
|
|
5495
|
-
];
|
|
5496
|
-
for (const section of sections) {
|
|
5497
|
-
const entries = parsed[section.name];
|
|
5498
|
-
if (!isRecord(entries)) continue;
|
|
5499
|
-
for (const [name, range] of Object.entries(entries)) {
|
|
5500
|
-
if (!DEPENDENCY_NAME_PATTERN.test(name) || name.length > 214) continue;
|
|
5501
|
-
if (!isString(range) || range.length === 0 || range.length > 2048) continue;
|
|
5502
|
-
section.dependencies.push({
|
|
5503
|
-
name,
|
|
5504
|
-
range
|
|
5505
|
-
});
|
|
5506
|
-
}
|
|
5507
|
-
}
|
|
5600
|
+
const [runtime = [], development = [], peer = []] = [
|
|
5601
|
+
"dependencies",
|
|
5602
|
+
"devDependencies",
|
|
5603
|
+
"peerDependencies"
|
|
5604
|
+
].map((section) => {
|
|
5605
|
+
const entries = parsed[section];
|
|
5606
|
+
return isRecord(entries) ? Object.entries(entries).flatMap(([name, range]) => !DEPENDENCY_NAME_PATTERN.test(name) || name.length > 214 || !isString(range) || range.length === 0 || range.length > 2048 ? [] : [{
|
|
5607
|
+
name,
|
|
5608
|
+
range
|
|
5609
|
+
}]) : [];
|
|
5610
|
+
});
|
|
5508
5611
|
return {
|
|
5509
5612
|
runtime: limitEntries(runtime, MAX_COLLECTION_ITEMS),
|
|
5510
5613
|
development: limitEntries(development, MAX_COLLECTION_ITEMS),
|
|
@@ -5541,6 +5644,50 @@ function renderSkillPointer(canonical, name) {
|
|
|
5541
5644
|
if (closing === -1) return void 0;
|
|
5542
5645
|
return `${lines.slice(0, closing + 1).join("\n")}\n${fillTemplate(ARTIFACT_TEMPLATES.orchestration.skill, { name })}`;
|
|
5543
5646
|
}
|
|
5647
|
+
/**
|
|
5648
|
+
* Scans manifest text for its strings and object braces, in order.
|
|
5649
|
+
*
|
|
5650
|
+
* @param text - The manifest text to scan.
|
|
5651
|
+
* @returns One token per quoted string and per `{` or `}` outside a string, or
|
|
5652
|
+
* `undefined` when a string is never closed.
|
|
5653
|
+
*
|
|
5654
|
+
* @remarks
|
|
5655
|
+
* Native JSON validation owns syntax; this scan only locates the byte ranges an
|
|
5656
|
+
* in-place writer edits. A string is opaque, so a brace inside one is never read,
|
|
5657
|
+
* and a backslash escapes the character after it. Depth counts objects alone and
|
|
5658
|
+
* ignores arrays, exactly as the range writers count them, so a key nested inside
|
|
5659
|
+
* another object never reads as a top-level one. A string that a colon follows
|
|
5660
|
+
* carries `value`, the offset of the character after that colon and the
|
|
5661
|
+
* whitespace beside it.
|
|
5662
|
+
*
|
|
5663
|
+
* @example
|
|
5664
|
+
* ```ts
|
|
5665
|
+
* import { scanManifestTokens } from '@orkestrel/scaffold'
|
|
5666
|
+
*
|
|
5667
|
+
* scanManifestTokens('{"a": "b"}')?.length // 4
|
|
5668
|
+
* scanManifestTokens('{"a') // undefined
|
|
5669
|
+
* ```
|
|
5670
|
+
*/
|
|
5671
|
+
function scanManifestTokens(text) {
|
|
5672
|
+
const tokens = [];
|
|
5673
|
+
for (const match of text.matchAll(/(?<string>"(?:\\[\s\S]|[^"\\])*")(?<colon>\s*:\s*)?|[{}]|"/gu)) {
|
|
5674
|
+
if (match[0] === "\"") return void 0;
|
|
5675
|
+
const literal = match.groups?.string;
|
|
5676
|
+
const depth = (tokens.at(-1)?.depth ?? 0) + (match[0] === "{" ? 1 : match[0] === "}" ? -1 : 0);
|
|
5677
|
+
tokens.push(literal === void 0 ? {
|
|
5678
|
+
text: match[0],
|
|
5679
|
+
index: match.index,
|
|
5680
|
+
depth,
|
|
5681
|
+
value: void 0
|
|
5682
|
+
} : {
|
|
5683
|
+
text: literal,
|
|
5684
|
+
index: match.index,
|
|
5685
|
+
depth,
|
|
5686
|
+
value: match.groups?.colon === void 0 ? void 0 : match.index + match[0].length
|
|
5687
|
+
});
|
|
5688
|
+
}
|
|
5689
|
+
return tokens;
|
|
5690
|
+
}
|
|
5544
5691
|
//#endregion
|
|
5545
5692
|
//#region src/core/compilers.ts
|
|
5546
5693
|
/**
|
|
@@ -5591,18 +5738,18 @@ function blueprintToSheets(blueprint) {
|
|
|
5591
5738
|
* ```
|
|
5592
5739
|
*/
|
|
5593
5740
|
function blueprintToExports(blueprint) {
|
|
5594
|
-
const
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5741
|
+
const exported = {
|
|
5742
|
+
...srcToExports(blueprint.src),
|
|
5743
|
+
...Object.fromEntries(blueprintToFaces(blueprint).filter((extension) => extension.axes.includes("src")).flatMap((extension) => {
|
|
5744
|
+
const face = [`./${extension.name}`, pathToCondition(`./dist/src/${extension.name}/index`, ["es"])];
|
|
5745
|
+
return blueprint.src.includes("browser") ? [face, ["./browser", pathToCondition("./dist/src/browser/index", ["es"])]] : [face];
|
|
5746
|
+
})),
|
|
5747
|
+
...Object.fromEntries([...blueprintToSheets(blueprint), ...blueprint.themes ? ["styles/themes"] : []].flatMap((name) => [[`./${name}`, `./dist/src/${name}/index.css`], [`./${name}/scss`, `./src/${name}/index.scss`]]))
|
|
5748
|
+
};
|
|
5749
|
+
return Object.keys(exported).length > 0 ? {
|
|
5750
|
+
...exported,
|
|
5751
|
+
"./package.json": "./package.json"
|
|
5752
|
+
} : exported;
|
|
5606
5753
|
}
|
|
5607
5754
|
/**
|
|
5608
5755
|
* Builds one `exports` condition block for a built environment.
|
|
@@ -5702,17 +5849,14 @@ function srcToEntry(src) {
|
|
|
5702
5849
|
*/
|
|
5703
5850
|
function srcToExports(src) {
|
|
5704
5851
|
if (src.length === 0) return {};
|
|
5705
|
-
const map = {};
|
|
5706
5852
|
const root = srcToRoot(src);
|
|
5707
5853
|
const environment = root ?? "core";
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
map["./package.json"] = "./package.json";
|
|
5715
|
-
return map;
|
|
5854
|
+
const entries = [
|
|
5855
|
+
[".", pathToCondition(`./dist/src/${environment}/index`, SRC_MATRIX[environment].formats)],
|
|
5856
|
+
...root === void 0 ? ENVIRONMENTS.filter((declared) => declared !== "core" && src.includes(declared)).map((declared) => [SRC_MATRIX[declared].path, pathToCondition(`./dist/src/${declared}/index`, SRC_MATRIX[declared].formats)]) : [],
|
|
5857
|
+
["./package.json", "./package.json"]
|
|
5858
|
+
];
|
|
5859
|
+
return Object.fromEntries(entries);
|
|
5716
5860
|
}
|
|
5717
5861
|
/**
|
|
5718
5862
|
* Projects a blueprint into the development dependencies its manifest declares.
|
|
@@ -5761,7 +5905,7 @@ function blueprintToDevDependencies(blueprint) {
|
|
|
5761
5905
|
const sheets = blueprintToSheets(blueprint).length > 0 || blueprint.themes;
|
|
5762
5906
|
const rendered = blueprint.src.includes("browser") || blueprint.app.includes("browser") || sheets;
|
|
5763
5907
|
const own = blueprint.src.length > 0 || sheets ? `@orkestrel/${blueprint.name}` : blueprint.name;
|
|
5764
|
-
const
|
|
5908
|
+
const prior = {
|
|
5765
5909
|
...BASE_DEV_DEPENDENCIES,
|
|
5766
5910
|
...rendered && !BROWSE_UPSTREAM.includes(own) ? BROWSE_DEV_DEPENDENCIES : {},
|
|
5767
5911
|
...sheets ? STYLES_DEV_DEPENDENCIES : {},
|
|
@@ -5769,12 +5913,16 @@ function blueprintToDevDependencies(blueprint) {
|
|
|
5769
5913
|
...blueprint.src.includes("browser") || blueprint.setup.includes("browser") || sheets ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
|
|
5770
5914
|
...blueprint.app.length > 0 ? APP_DEV_DEPENDENCIES : {},
|
|
5771
5915
|
...blueprint.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
|
|
5772
|
-
...blueprint.app.includes("server") ? APP_SERVER_DEV_DEPENDENCIES : {}
|
|
5916
|
+
...blueprint.app.includes("server") ? APP_SERVER_DEV_DEPENDENCIES : {},
|
|
5917
|
+
...Object.fromEntries(blueprintToMachinery(blueprint).frameworks.flatMap((framework) => Object.entries(FRAMEWORK_MATRIX[framework].dependencies))),
|
|
5918
|
+
...Object.fromEntries(Iterator.from(blueprint.extras).map((extra) => [extra.name, extra.range]).toArray()),
|
|
5919
|
+
...blueprint.showcase && blueprint.app.includes("browser") ? SHOWCASE_DEV_DEPENDENCIES : {}
|
|
5920
|
+
};
|
|
5921
|
+
const peers = Iterator.from(blueprint.peers).flatMap((peer) => Object.hasOwn(prior, peer.name) ? [] : [[peer.name, peer.range]]).toArray();
|
|
5922
|
+
const merged = {
|
|
5923
|
+
...prior,
|
|
5924
|
+
...Object.fromEntries(peers.filter(([name], index) => peers.findIndex(([other]) => other === name) === index))
|
|
5773
5925
|
};
|
|
5774
|
-
for (const framework of blueprintToMachinery(blueprint).frameworks) Object.assign(merged, FRAMEWORK_MATRIX[framework].dependencies);
|
|
5775
|
-
for (const extra of blueprint.extras) merged[extra.name] = extra.range;
|
|
5776
|
-
if (blueprint.showcase && blueprint.app.includes("browser")) Object.assign(merged, SHOWCASE_DEV_DEPENDENCIES);
|
|
5777
|
-
for (const peer of blueprint.peers) if (!Object.hasOwn(merged, peer.name)) merged[peer.name] = peer.range;
|
|
5778
5926
|
const runtime = new Set(blueprint.dependencies.map((dependency) => dependency.name));
|
|
5779
5927
|
return Object.fromEntries(Object.entries(merged).filter(([name]) => name !== own && !runtime.has(name)).sort(([left], [right]) => compareValues(left, right)));
|
|
5780
5928
|
}
|
|
@@ -5811,62 +5959,82 @@ function blueprintToManifestOverrides(blueprint) {
|
|
|
5811
5959
|
*/
|
|
5812
5960
|
function replaceManifestOverrides(manifest, overrides) {
|
|
5813
5961
|
if (!isRecord(parseJSON(manifest))) return void 0;
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
const path = [
|
|
5962
|
+
return Object.entries(overrides).flatMap(([selector, children]) => Object.entries(children).map(([child, range]) => ({
|
|
5963
|
+
path: [
|
|
5817
5964
|
"overrides",
|
|
5818
5965
|
selector,
|
|
5819
5966
|
child
|
|
5820
|
-
]
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5967
|
+
],
|
|
5968
|
+
range
|
|
5969
|
+
}))).reduce((compiled, leaf) => compiled === void 0 ? void 0 : replaceManifestOverride(compiled, leaf.path, leaf.range), manifest);
|
|
5970
|
+
}
|
|
5971
|
+
/**
|
|
5972
|
+
* Replaces one npm override leaf in manifest text, inserting its absent ancestors.
|
|
5973
|
+
*
|
|
5974
|
+
* @param manifest - The JSON package manifest text, already known to be an object.
|
|
5975
|
+
* @param path - The object keys from the manifest root to the leaf, ending at the leaf's key.
|
|
5976
|
+
* @param range - The string the leaf must hold.
|
|
5977
|
+
* @returns The text carrying the leaf, or `undefined` for a duplicate selected key, a malformed
|
|
5978
|
+
* ancestor, or a non-string leaf.
|
|
5979
|
+
*
|
|
5980
|
+
* @remarks
|
|
5981
|
+
* The one step {@link replaceManifestOverrides} repeats per leaf. Absent ancestors and the leaf are
|
|
5982
|
+
* inserted after the last member of the deepest ancestor the text declares, and a leaf already
|
|
5983
|
+
* holding `range` keeps its original spelling. Every byte outside the edited path survives.
|
|
5984
|
+
*
|
|
5985
|
+
* @example
|
|
5986
|
+
* ```ts
|
|
5987
|
+
* import { replaceManifestOverride } from '@orkestrel/scaffold'
|
|
5988
|
+
*
|
|
5989
|
+
* replaceManifestOverride('{}', ['overrides', 'plugin@1.0.0', 'child'], '2.0.0')
|
|
5990
|
+
* // '{"overrides":{"plugin@1.0.0":{"child":"2.0.0"}}}'
|
|
5991
|
+
* ```
|
|
5992
|
+
*/
|
|
5993
|
+
function replaceManifestOverride(manifest, path, range) {
|
|
5994
|
+
const tokens = scanManifestTokens(manifest);
|
|
5995
|
+
if (tokens === void 0) return void 0;
|
|
5996
|
+
return path.reduce((state, key, level) => {
|
|
5997
|
+
if (state.done) return state;
|
|
5998
|
+
const refused = {
|
|
5999
|
+
...state,
|
|
6000
|
+
done: true,
|
|
6001
|
+
text: void 0
|
|
6002
|
+
};
|
|
6003
|
+
const brace = tokens.find((token) => token.index === state.open && token.text === "{");
|
|
6004
|
+
if (brace === void 0) return refused;
|
|
6005
|
+
const close = tokens.find((token) => token.text === "}" && token.index > state.open && token.depth === brace.depth - 1);
|
|
6006
|
+
if (close === void 0) return refused;
|
|
6007
|
+
const matches = tokens.flatMap((token, at) => token.index > state.open && token.index < close.index && token.depth === brace.depth && token.value !== void 0 && parseJSON(token.text) === key ? [at] : []);
|
|
6008
|
+
if (matches.length > 1) return refused;
|
|
6009
|
+
const at = matches[0];
|
|
6010
|
+
const entry = at === void 0 ? void 0 : tokens[at];
|
|
6011
|
+
if (at === void 0 || entry === void 0) {
|
|
6012
|
+
const insertion = path.slice(level).reduceRight((inner, name) => `{${JSON.stringify(name)}:${inner}}`, JSON.stringify(range));
|
|
6013
|
+
const tail = state.open + manifest.slice(state.open + 1, close.index).trimEnd().length;
|
|
6014
|
+
return {
|
|
6015
|
+
...state,
|
|
6016
|
+
done: true,
|
|
6017
|
+
text: manifest.slice(0, tail + 1) + (tail === state.open ? "" : ",") + insertion.slice(1, -1) + manifest.slice(tail + 1)
|
|
6018
|
+
};
|
|
5867
6019
|
}
|
|
5868
|
-
|
|
5869
|
-
|
|
6020
|
+
const start = entry.value;
|
|
6021
|
+
if (start === void 0) return refused;
|
|
6022
|
+
if (level < path.length - 1) return manifest.charAt(start) === "{" ? {
|
|
6023
|
+
...state,
|
|
6024
|
+
open: start
|
|
6025
|
+
} : refused;
|
|
6026
|
+
const literal = tokens[at + 1];
|
|
6027
|
+
if (manifest.charAt(start) !== "\"" || literal === void 0) return refused;
|
|
6028
|
+
return {
|
|
6029
|
+
...state,
|
|
6030
|
+
done: true,
|
|
6031
|
+
text: parseJSON(literal.text) === range ? manifest : manifest.slice(0, start) + JSON.stringify(range) + manifest.slice(literal.index + literal.text.length)
|
|
6032
|
+
};
|
|
6033
|
+
}, {
|
|
6034
|
+
done: false,
|
|
6035
|
+
open: manifest.indexOf("{"),
|
|
6036
|
+
text: manifest
|
|
6037
|
+
}).text;
|
|
5870
6038
|
}
|
|
5871
6039
|
/**
|
|
5872
6040
|
* Projects a blueprint into the scripts its manifest declares.
|
|
@@ -5881,11 +6049,12 @@ function replaceManifestOverrides(manifest, overrides) {
|
|
|
5881
6049
|
* proofs every workspace can pass before it has a public API, and one build per
|
|
5882
6050
|
* target that actually builds.
|
|
5883
6051
|
*
|
|
5884
|
-
* A publishing workspace isolates its distribution and live-service proofs
|
|
5885
|
-
* `test` and runs them from `prepublishOnly` instead. Publishing is what
|
|
5886
|
-
* the distribution proof: what that proof measures is the packed tarball,
|
|
5887
|
-
* workspace that packs no published source has nothing for it to read. A
|
|
5888
|
-
* workspace therefore omits it and runs a
|
|
6052
|
+
* A publishing workspace isolates its distribution, study, and live-service proofs
|
|
6053
|
+
* from `test` and runs them from `prepublishOnly` instead. Publishing is what
|
|
6054
|
+
* selects the distribution proof: what that proof measures is the packed tarball,
|
|
6055
|
+
* so a workspace that packs no published source has nothing for it to read. A
|
|
6056
|
+
* private workspace therefore omits it and runs a study proof and a live-service
|
|
6057
|
+
* proof from `test`, the study proof first.
|
|
5889
6058
|
* Integration and conformance stay in `test` because they neither pack nor
|
|
5890
6059
|
* install the workspace and drive no external service. A conformance run may
|
|
5891
6060
|
* start a server, but it starts its own and reaches it over loopback, so the run
|
|
@@ -5921,7 +6090,10 @@ function blueprintToScripts(blueprint) {
|
|
|
5921
6090
|
...sheets,
|
|
5922
6091
|
...blueprint.bin ? ["bin"] : []
|
|
5923
6092
|
].map((name) => `npm run check:src:${name}`);
|
|
5924
|
-
const
|
|
6093
|
+
const journey = `vitest run --config ${JOURNEY_CONFIG_PATH} --no-cache --reporter=dot`;
|
|
6094
|
+
const showcase = `vite --config ${SHOWCASE_CONFIG_PATH}`;
|
|
6095
|
+
const buildShowcase = `vite build --config ${SHOWCASE_CONFIG_PATH}`;
|
|
6096
|
+
return {
|
|
5925
6097
|
clean: "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
5926
6098
|
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)\"",
|
|
5927
6099
|
format: "oxfmt --config .oxfmtrc.json --write .",
|
|
@@ -5933,123 +6105,118 @@ function blueprintToScripts(blueprint) {
|
|
|
5933
6105
|
...checks.length > 0 ? ["npm run check:src"] : [],
|
|
5934
6106
|
...blueprint.app.length > 0 ? ["npm run check:app"] : [],
|
|
5935
6107
|
...blueprint.skills ? ["npm run check:skills"] : []
|
|
5936
|
-
].join(" && ")
|
|
6108
|
+
].join(" && "),
|
|
6109
|
+
...checks.length > 0 ? {
|
|
6110
|
+
"check:src": checks.join(" && "),
|
|
6111
|
+
...Object.fromEntries(Iterator.from(blueprint.src).map((environment) => [`check:src:${environment}`, `tsc --noEmit -p configs/src/tsconfig.${environment}.json`]).toArray()),
|
|
6112
|
+
...blueprint.bin ? { "check:src:bin": "tsc --noEmit -p configs/src/tsconfig.bin.json" } : {},
|
|
6113
|
+
...Object.fromEntries([...sheets, ...source].map((name) => [`check:src:${name}`, `tsc --noEmit -p configs/src/tsconfig.${name}.json`]))
|
|
6114
|
+
} : {},
|
|
6115
|
+
...blueprint.app.length > 0 ? {
|
|
6116
|
+
"check:app": [...blueprint.app, ...application].map((environment) => `npm run check:app:${environment}`).join(" && "),
|
|
6117
|
+
...Object.fromEntries(Iterator.from(blueprint.app).map((environment) => [`check:app:${environment}`, `tsc --noEmit -p configs/app/tsconfig.${environment}.json`]).toArray()),
|
|
6118
|
+
...Object.fromEntries(application.map((name) => [`check:app:${name}`, `${FRAMEWORK_MATRIX[name].checker} --noEmit -p configs/app/tsconfig.${name}.json`]))
|
|
6119
|
+
} : {},
|
|
6120
|
+
...blueprint.skills ? { "check:skills": `tsc --noEmit -p ${SKILLS_CONFIG_PATH}` } : {},
|
|
6121
|
+
test: [
|
|
6122
|
+
...compiles ? ["npm run test:src"] : [],
|
|
6123
|
+
...blueprint.app.length > 0 ? ["npm run test:app"] : [],
|
|
6124
|
+
...blueprint.journey && blueprint.app.includes("browser") ? ["npm run test:journey", ...application.map((name) => `npm run test:journey:${name}`)] : [],
|
|
6125
|
+
"npm run test:policy",
|
|
6126
|
+
"npm run test:config",
|
|
6127
|
+
...blueprint.setup.includes("node") || blueprint.global ? ["npm run test:setup"] : [],
|
|
6128
|
+
...blueprint.setup.includes("browser") || targets.length > 0 ? ["npm run test:setup:browser"] : [],
|
|
6129
|
+
...blueprint.skills ? ["npm run test:skills"] : [],
|
|
6130
|
+
...blueprint.guides ? ["npm run test:guides"] : [],
|
|
6131
|
+
...blueprint.conformance ? ["npm run test:conformance"] : [],
|
|
6132
|
+
...integrates ? ["npm run test:integration"] : [],
|
|
6133
|
+
...!publishes && blueprint.studies ? ["npm run test:studies"] : [],
|
|
6134
|
+
...!publishes && blueprint.service ? ["npm run test:service"] : []
|
|
6135
|
+
].join(" && "),
|
|
6136
|
+
...compiles ? {
|
|
6137
|
+
"test:src": [...blueprint.src.length > 0 || blueprint.bin ? [[
|
|
6138
|
+
vitest,
|
|
6139
|
+
...blueprint.src.map((environment) => `--project ${SRC_MATRIX[environment].project}`),
|
|
6140
|
+
...source.map((name) => `--project src:${name}`),
|
|
6141
|
+
...blueprint.bin ? ["--project src:bin"] : []
|
|
6142
|
+
].join(" ")] : [], ...targets.map((name) => `npm run test:src:${name}`)].join(" && "),
|
|
6143
|
+
...Object.fromEntries(Iterator.from(blueprint.src).map((environment) => [`test:src:${environment}`, `${vitest} --project ${SRC_MATRIX[environment].project}`]).toArray()),
|
|
6144
|
+
...blueprint.bin ? { "test:src:bin": `${vitest} --project src:bin` } : {},
|
|
6145
|
+
...Object.fromEntries(source.map((name) => [`test:src:${name}`, `${vitest} --project src:${name}`])),
|
|
6146
|
+
...Object.fromEntries(targets.map((name) => [`test:src:${name}`, `npm run build:src:${name} && ${vitest} --project src:${name}`]))
|
|
6147
|
+
} : {},
|
|
6148
|
+
...blueprint.app.length > 0 ? {
|
|
6149
|
+
"test:app": [
|
|
6150
|
+
vitest,
|
|
6151
|
+
...blueprint.app.map((environment) => `--project ${APP_MATRIX[environment].project}`),
|
|
6152
|
+
...application.map((name) => `--project app:${name}`)
|
|
6153
|
+
].join(" "),
|
|
6154
|
+
...Object.fromEntries(Iterator.from(blueprint.app).map((environment) => [`test:app:${environment}`, `${vitest} --project ${APP_MATRIX[environment].project}`]).toArray()),
|
|
6155
|
+
...Object.fromEntries(application.map((name) => [`test:app:${name}`, `${vitest} --project app:${name}`]))
|
|
6156
|
+
} : {},
|
|
6157
|
+
"test:policy": `${vitest} --project policy`,
|
|
6158
|
+
"test:config": `${vitest} --project config`,
|
|
6159
|
+
...blueprint.setup.includes("node") || blueprint.global ? { "test:setup": `${vitest} --project setup` } : {},
|
|
6160
|
+
...blueprint.setup.includes("browser") || targets.length > 0 ? { "test:setup:browser": `${vitest} --project setup:browser` } : {},
|
|
6161
|
+
...blueprint.journey && blueprint.app.includes("browser") ? {
|
|
6162
|
+
"test:journey": journey,
|
|
6163
|
+
...Object.fromEntries(application.map((name) => [`test:journey:${name}`, `${journey} --mode ${name}`]))
|
|
6164
|
+
} : {},
|
|
6165
|
+
...blueprint.skills ? { "test:skills": `${vitest} --project skills` } : {},
|
|
6166
|
+
...blueprint.guides ? { "test:guides": `node --experimental-strip-types ${GUIDES_TEST_PATH}` } : {},
|
|
6167
|
+
...blueprint.conformance ? { "test:conformance": `${vitest} --project conformance` } : {},
|
|
6168
|
+
"test:probe": "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe",
|
|
6169
|
+
"test:bench": "vitest bench --config vite.config.ts --no-cache --project probe",
|
|
6170
|
+
...publishes ? { "test:distribution": `${vitest} --project distribution` } : {},
|
|
6171
|
+
...integrates ? { "test:integration": `${vitest} --project integration` } : {},
|
|
6172
|
+
...blueprint.service ? { "test:service": `${vitest} --project service` } : {},
|
|
6173
|
+
...blueprint.studies ? { "test:studies": `${vitest} --project studies` } : {},
|
|
6174
|
+
build: [
|
|
6175
|
+
"npm run clean",
|
|
6176
|
+
...compiles ? ["npm run build:src"] : [],
|
|
6177
|
+
...blueprint.app.length > 0 ? ["npm run build:app"] : []
|
|
6178
|
+
].join(" && "),
|
|
6179
|
+
...compiles ? {
|
|
6180
|
+
"build:src": [
|
|
6181
|
+
...blueprint.src.map((environment) => `npm run build:src:${environment}`),
|
|
6182
|
+
...source.map((name) => `npm run build:src:${name}`),
|
|
6183
|
+
...targets.map((name) => `npm run build:src:${name}`),
|
|
6184
|
+
...blueprint.bin ? ["npm run build:src:bin"] : []
|
|
6185
|
+
].join(" && "),
|
|
6186
|
+
...Object.fromEntries(Iterator.from(blueprint.src).map((environment) => [`build:src:${environment}`, SRC_MATRIX[environment].formats.includes("cjs") ? `vite build --config configs/src/vite.${environment}.config.ts && npm run copy dist/src/${environment}/index.d.ts dist/src/${environment}/index.d.cts` : `vite build --config configs/src/vite.${environment}.config.ts`]).toArray()),
|
|
6187
|
+
...blueprint.bin ? { "build:src:bin": "vite build --config configs/src/vite.bin.config.ts" } : {},
|
|
6188
|
+
...Object.fromEntries(source.map((name) => [`build:src:${name}`, `vite build --config configs/src/vite.${name}.config.ts`])),
|
|
6189
|
+
...Object.fromEntries(targets.map((name) => [`build:src:${name}`, [`vite build --config configs/src/vite.${name}.config.ts`, ...name === "styles" && blueprint.themes ? ["vite build --config configs/src/vite.themes.config.ts"] : []].join(" && ")]))
|
|
6190
|
+
} : {},
|
|
6191
|
+
...blueprint.app.length > 0 ? {
|
|
6192
|
+
"build:app": runtime.length > 0 ? [...runtime, ...application].map((environment) => `npm run build:app:${environment}`).join(" && ") : "npm run check:app:core",
|
|
6193
|
+
...Object.fromEntries([...runtime, ...application].map((environment) => [`build:app:${environment}`, `vite build --config configs/app/vite.${environment}.config.ts`]))
|
|
6194
|
+
} : {},
|
|
6195
|
+
...blueprint.app.includes("browser") ? {
|
|
6196
|
+
dev: "vite --config configs/app/vite.browser.config.ts",
|
|
6197
|
+
...Object.fromEntries(application.map((name) => [`dev:${name}`, `vite --config configs/app/vite.${name}.config.ts`])),
|
|
6198
|
+
...blueprint.showcase ? {
|
|
6199
|
+
showcase,
|
|
6200
|
+
"build:showcase": buildShowcase,
|
|
6201
|
+
...Object.fromEntries(application.flatMap((name) => [[`showcase:${name}`, `${showcase} --mode ${name}`], [`build:showcase:${name}`, `${buildShowcase} --mode ${name}`]]))
|
|
6202
|
+
} : {}
|
|
6203
|
+
} : {},
|
|
6204
|
+
...blueprint.app.includes("server") ? {
|
|
6205
|
+
serve: "node dist/app/server/main.cjs",
|
|
6206
|
+
"serve:build": "npm run build:app:server && npm run serve"
|
|
6207
|
+
} : {},
|
|
6208
|
+
...publishes ? {
|
|
6209
|
+
prepack: "npm run build",
|
|
6210
|
+
prepublishOnly: [
|
|
6211
|
+
"npm run format:check && npm run lint:check && npm run check && npm run build",
|
|
6212
|
+
...blueprint.showcase && blueprint.app.includes("browser") ? ["npm run build:showcase", ...application.map((name) => `npm run build:showcase:${name}`)] : [],
|
|
6213
|
+
"npm test",
|
|
6214
|
+
...blueprint.studies ? ["npm run test:studies"] : [],
|
|
6215
|
+
RELEASE_PROOF_COMMAND,
|
|
6216
|
+
...blueprint.service ? ["npm run test:service"] : []
|
|
6217
|
+
].join(" && ")
|
|
6218
|
+
} : {}
|
|
5937
6219
|
};
|
|
5938
|
-
if (checks.length > 0) {
|
|
5939
|
-
scripts["check:src"] = checks.join(" && ");
|
|
5940
|
-
for (const environment of blueprint.src) scripts[`check:src:${environment}`] = `tsc --noEmit -p configs/src/tsconfig.${environment}.json`;
|
|
5941
|
-
if (blueprint.bin) scripts["check:src:bin"] = "tsc --noEmit -p configs/src/tsconfig.bin.json";
|
|
5942
|
-
for (const name of [...sheets, ...source]) scripts[`check:src:${name}`] = `tsc --noEmit -p configs/src/tsconfig.${name}.json`;
|
|
5943
|
-
}
|
|
5944
|
-
if (blueprint.app.length > 0) {
|
|
5945
|
-
scripts["check:app"] = [...blueprint.app, ...application].map((environment) => `npm run check:app:${environment}`).join(" && ");
|
|
5946
|
-
for (const environment of blueprint.app) scripts[`check:app:${environment}`] = `tsc --noEmit -p configs/app/tsconfig.${environment}.json`;
|
|
5947
|
-
for (const name of application) scripts[`check:app:${name}`] = `${FRAMEWORK_MATRIX[name].checker} --noEmit -p configs/app/tsconfig.${name}.json`;
|
|
5948
|
-
}
|
|
5949
|
-
if (blueprint.skills) scripts["check:skills"] = `tsc --noEmit -p ${SKILLS_CONFIG_PATH}`;
|
|
5950
|
-
scripts.test = [
|
|
5951
|
-
...compiles ? ["npm run test:src"] : [],
|
|
5952
|
-
...blueprint.app.length > 0 ? ["npm run test:app"] : [],
|
|
5953
|
-
...blueprint.journey && blueprint.app.includes("browser") ? ["npm run test:journey", ...application.map((name) => `npm run test:journey:${name}`)] : [],
|
|
5954
|
-
"npm run test:policy",
|
|
5955
|
-
"npm run test:config",
|
|
5956
|
-
...blueprint.setup.includes("node") || blueprint.global ? ["npm run test:setup"] : [],
|
|
5957
|
-
...blueprint.setup.includes("browser") || targets.length > 0 ? ["npm run test:setup:browser"] : [],
|
|
5958
|
-
...blueprint.skills ? ["npm run test:skills"] : [],
|
|
5959
|
-
...blueprint.guides ? ["npm run test:guides"] : [],
|
|
5960
|
-
...blueprint.conformance ? ["npm run test:conformance"] : [],
|
|
5961
|
-
...integrates ? ["npm run test:integration"] : [],
|
|
5962
|
-
...!publishes && blueprint.service ? ["npm run test:service"] : []
|
|
5963
|
-
].join(" && ");
|
|
5964
|
-
if (compiles) {
|
|
5965
|
-
scripts["test:src"] = [
|
|
5966
|
-
vitest,
|
|
5967
|
-
...blueprint.src.map((environment) => `--project ${SRC_MATRIX[environment].project}`),
|
|
5968
|
-
...source.map((name) => `--project src:${name}`),
|
|
5969
|
-
...blueprint.bin ? ["--project src:bin"] : []
|
|
5970
|
-
].join(" ");
|
|
5971
|
-
for (const environment of blueprint.src) scripts[`test:src:${environment}`] = `${vitest} --project ${SRC_MATRIX[environment].project}`;
|
|
5972
|
-
if (blueprint.bin) scripts["test:src:bin"] = `${vitest} --project src:bin`;
|
|
5973
|
-
for (const name of source) scripts[`test:src:${name}`] = `${vitest} --project src:${name}`;
|
|
5974
|
-
scripts["test:src"] = [...blueprint.src.length > 0 || blueprint.bin ? [scripts["test:src"]] : [], ...targets.map((name) => `npm run test:src:${name}`)].join(" && ");
|
|
5975
|
-
for (const name of targets) scripts[`test:src:${name}`] = `npm run build:src:${name} && ${vitest} --project src:${name}`;
|
|
5976
|
-
}
|
|
5977
|
-
if (blueprint.app.length > 0) {
|
|
5978
|
-
scripts["test:app"] = [
|
|
5979
|
-
vitest,
|
|
5980
|
-
...blueprint.app.map((environment) => `--project ${APP_MATRIX[environment].project}`),
|
|
5981
|
-
...application.map((name) => `--project app:${name}`)
|
|
5982
|
-
].join(" ");
|
|
5983
|
-
for (const environment of blueprint.app) scripts[`test:app:${environment}`] = `${vitest} --project ${APP_MATRIX[environment].project}`;
|
|
5984
|
-
for (const name of application) scripts[`test:app:${name}`] = `${vitest} --project app:${name}`;
|
|
5985
|
-
}
|
|
5986
|
-
scripts["test:policy"] = `${vitest} --project policy`;
|
|
5987
|
-
scripts["test:config"] = `${vitest} --project config`;
|
|
5988
|
-
if (blueprint.setup.includes("node") || blueprint.global) scripts["test:setup"] = `${vitest} --project setup`;
|
|
5989
|
-
if (blueprint.setup.includes("browser") || targets.length > 0) scripts["test:setup:browser"] = `${vitest} --project setup:browser`;
|
|
5990
|
-
if (blueprint.journey && blueprint.app.includes("browser")) {
|
|
5991
|
-
scripts["test:journey"] = `vitest run --config ${JOURNEY_CONFIG_PATH} --no-cache --reporter=dot`;
|
|
5992
|
-
for (const name of application) scripts[`test:journey:${name}`] = `${scripts["test:journey"]} --mode ${name}`;
|
|
5993
|
-
}
|
|
5994
|
-
if (blueprint.skills) scripts["test:skills"] = `${vitest} --project skills`;
|
|
5995
|
-
if (blueprint.guides) scripts["test:guides"] = `node --experimental-strip-types ${GUIDES_TEST_PATH}`;
|
|
5996
|
-
if (blueprint.conformance) scripts["test:conformance"] = `${vitest} --project conformance`;
|
|
5997
|
-
scripts["test:probe"] = "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe";
|
|
5998
|
-
scripts["test:bench"] = "vitest bench --config vite.config.ts --no-cache --project probe";
|
|
5999
|
-
if (publishes) scripts["test:distribution"] = `${vitest} --project distribution`;
|
|
6000
|
-
if (integrates) scripts["test:integration"] = `${vitest} --project integration`;
|
|
6001
|
-
if (blueprint.service) scripts["test:service"] = `${vitest} --project service`;
|
|
6002
|
-
scripts.build = [
|
|
6003
|
-
"npm run clean",
|
|
6004
|
-
...compiles ? ["npm run build:src"] : [],
|
|
6005
|
-
...blueprint.app.length > 0 ? ["npm run build:app"] : []
|
|
6006
|
-
].join(" && ");
|
|
6007
|
-
if (compiles) {
|
|
6008
|
-
scripts["build:src"] = [
|
|
6009
|
-
...blueprint.src.map((environment) => `npm run build:src:${environment}`),
|
|
6010
|
-
...source.map((name) => `npm run build:src:${name}`),
|
|
6011
|
-
...targets.map((name) => `npm run build:src:${name}`),
|
|
6012
|
-
...blueprint.bin ? ["npm run build:src:bin"] : []
|
|
6013
|
-
].join(" && ");
|
|
6014
|
-
for (const environment of blueprint.src) {
|
|
6015
|
-
const build = `vite build --config configs/src/vite.${environment}.config.ts`;
|
|
6016
|
-
scripts[`build:src:${environment}`] = SRC_MATRIX[environment].formats.includes("cjs") ? `${build} && npm run copy dist/src/${environment}/index.d.ts dist/src/${environment}/index.d.cts` : build;
|
|
6017
|
-
}
|
|
6018
|
-
if (blueprint.bin) scripts["build:src:bin"] = "vite build --config configs/src/vite.bin.config.ts";
|
|
6019
|
-
for (const name of source) scripts[`build:src:${name}`] = `vite build --config configs/src/vite.${name}.config.ts`;
|
|
6020
|
-
for (const name of targets) scripts[`build:src:${name}`] = [`vite build --config configs/src/vite.${name}.config.ts`, ...name === "styles" && blueprint.themes ? ["vite build --config configs/src/vite.themes.config.ts"] : []].join(" && ");
|
|
6021
|
-
}
|
|
6022
|
-
if (blueprint.app.length > 0) {
|
|
6023
|
-
scripts["build:app"] = runtime.length > 0 ? [...runtime, ...application].map((environment) => `npm run build:app:${environment}`).join(" && ") : "npm run check:app:core";
|
|
6024
|
-
for (const environment of [...runtime, ...application]) scripts[`build:app:${environment}`] = `vite build --config configs/app/vite.${environment}.config.ts`;
|
|
6025
|
-
}
|
|
6026
|
-
if (blueprint.app.includes("browser")) {
|
|
6027
|
-
scripts.dev = "vite --config configs/app/vite.browser.config.ts";
|
|
6028
|
-
for (const name of application) scripts[`dev:${name}`] = `vite --config configs/app/vite.${name}.config.ts`;
|
|
6029
|
-
if (blueprint.showcase) {
|
|
6030
|
-
scripts.showcase = `vite --config ${SHOWCASE_CONFIG_PATH}`;
|
|
6031
|
-
scripts["build:showcase"] = `vite build --config ${SHOWCASE_CONFIG_PATH}`;
|
|
6032
|
-
for (const name of application) {
|
|
6033
|
-
scripts[`showcase:${name}`] = `${scripts.showcase} --mode ${name}`;
|
|
6034
|
-
scripts[`build:showcase:${name}`] = `${scripts["build:showcase"]} --mode ${name}`;
|
|
6035
|
-
}
|
|
6036
|
-
}
|
|
6037
|
-
}
|
|
6038
|
-
if (blueprint.app.includes("server")) {
|
|
6039
|
-
scripts.serve = "node dist/app/server/main.cjs";
|
|
6040
|
-
scripts["serve:build"] = "npm run build:app:server && npm run serve";
|
|
6041
|
-
}
|
|
6042
|
-
if (publishes) {
|
|
6043
|
-
scripts.prepack = "npm run build";
|
|
6044
|
-
scripts.prepublishOnly = [
|
|
6045
|
-
"npm run format:check && npm run lint:check && npm run check && npm run build",
|
|
6046
|
-
...blueprint.showcase && blueprint.app.includes("browser") ? ["npm run build:showcase", ...application.map((name) => `npm run build:showcase:${name}`)] : [],
|
|
6047
|
-
"npm test",
|
|
6048
|
-
RELEASE_PROOF_COMMAND,
|
|
6049
|
-
...blueprint.service ? ["npm run test:service"] : []
|
|
6050
|
-
].join(" && ");
|
|
6051
|
-
}
|
|
6052
|
-
return scripts;
|
|
6053
6220
|
}
|
|
6054
6221
|
/**
|
|
6055
6222
|
* Projects a blueprint into the manifest scripts a region write may replace.
|
|
@@ -6071,7 +6238,9 @@ function blueprintToScripts(blueprint) {
|
|
|
6071
6238
|
* guides entry accepts the generated command that invoked the guides project
|
|
6072
6239
|
* through Vitest alone. The pack hook accepts the build chain emitted before it
|
|
6073
6240
|
* delegated to `build`. The publication hook accepts the same gate chain without
|
|
6074
|
-
* {@link RELEASE_PROOF_COMMAND}.
|
|
6241
|
+
* {@link RELEASE_PROOF_COMMAND}. A workspace carrying studies also accepts the
|
|
6242
|
+
* chain without its study step and the chain without both its study step and
|
|
6243
|
+
* the release proof. The value being written is always writable, so
|
|
6075
6244
|
* it is not repeated there. Any other value is a script the workspace author
|
|
6076
6245
|
* customized, and {@link replaceManifestScripts} retains it while writing the
|
|
6077
6246
|
* other named scripts independently.
|
|
@@ -6088,35 +6257,38 @@ function blueprintToScripts(blueprint) {
|
|
|
6088
6257
|
function blueprintToWritableScripts(blueprint) {
|
|
6089
6258
|
const scripts = blueprintToScripts(blueprint);
|
|
6090
6259
|
const sheets = [...blueprintToSheets(blueprint), ...blueprint.themes && !blueprint.styles ? ["themes"] : []];
|
|
6091
|
-
const
|
|
6092
|
-
for (const [name, command] of Object.entries(scripts)) {
|
|
6260
|
+
const body = Object.entries(scripts).flatMap(([name, command]) => {
|
|
6093
6261
|
const direct = name.startsWith("test:") && name !== "test:src" && name !== "test:app";
|
|
6094
6262
|
const sheet = sheets.some((face) => name === `build:src:${face}` || name === `check:src:${face}`);
|
|
6095
6263
|
const framework = blueprintToFaces(blueprint).some((extension) => extension.surface === "browser" && extension.axes.some((axis) => name === `check:${axis}:${extension.name}` || name === `build:${axis}:${extension.name}` || axis === "app" && name === `dev:${extension.name}`));
|
|
6096
6264
|
const showcase = name === "showcase" || name.startsWith("showcase:") || name === "build:showcase" || name.startsWith("build:showcase:");
|
|
6097
|
-
if (!direct && !sheet && !framework && !showcase)
|
|
6098
|
-
|
|
6265
|
+
if (!direct && !sheet && !framework && !showcase) return [];
|
|
6266
|
+
return [{
|
|
6099
6267
|
name,
|
|
6100
6268
|
command,
|
|
6101
6269
|
accepted: name === "test:guides" ? ["vitest run --config vite.config.ts --no-cache --reporter=dot --project guides"] : name === "build:src:styles" && blueprint.themes ? ["vite build --config configs/src/vite.styles.config.ts"] : sheets.some((face) => name === `test:src:${face}`) ? [command.slice(command.indexOf(" && ") + 4)] : []
|
|
6102
|
-
}
|
|
6103
|
-
}
|
|
6270
|
+
}];
|
|
6271
|
+
});
|
|
6104
6272
|
const prepack = scripts.prepack;
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6273
|
+
const prepublish = scripts.prepublishOnly;
|
|
6274
|
+
const unreleased = prepublish?.replace(` && ${RELEASE_PROOF_COMMAND}`, "");
|
|
6275
|
+
return [
|
|
6276
|
+
...body,
|
|
6277
|
+
...prepack === void 0 ? [] : [{
|
|
6108
6278
|
name: "prepack",
|
|
6109
6279
|
command: prepack,
|
|
6110
|
-
accepted:
|
|
6111
|
-
}
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6280
|
+
accepted: scripts.build === void 0 ? [] : [scripts.build]
|
|
6281
|
+
}],
|
|
6282
|
+
...prepublish === void 0 || unreleased === void 0 ? [] : [{
|
|
6283
|
+
name: "prepublishOnly",
|
|
6284
|
+
command: prepublish,
|
|
6285
|
+
accepted: blueprint.studies ? [
|
|
6286
|
+
unreleased,
|
|
6287
|
+
prepublish.replace(" && npm run test:studies", ""),
|
|
6288
|
+
unreleased.replace(" && npm run test:studies", "")
|
|
6289
|
+
] : [unreleased]
|
|
6290
|
+
}]
|
|
6291
|
+
];
|
|
6120
6292
|
}
|
|
6121
6293
|
/**
|
|
6122
6294
|
* Compiles a blueprint into its `package.json` content.
|
|
@@ -6158,14 +6330,10 @@ function blueprintToManifest(blueprint) {
|
|
|
6158
6330
|
const targets = [...sheets, ...blueprint.themes ? ["styles/themes"] : []];
|
|
6159
6331
|
const publishes = blueprint.src.length > 0 || targets.length > 0;
|
|
6160
6332
|
const name = publishes ? `@orkestrel/${blueprint.name}` : blueprint.name;
|
|
6161
|
-
const dependencies =
|
|
6162
|
-
|
|
6163
|
-
const peerDependencies =
|
|
6164
|
-
const peerDependenciesMeta = {};
|
|
6165
|
-
for (const peer of [...blueprint.peers].sort((left, right) => compareValues(left.name, right.name))) {
|
|
6166
|
-
peerDependencies[peer.name] = peer.range;
|
|
6167
|
-
if (peer.optional === true) peerDependenciesMeta[peer.name] = { optional: true };
|
|
6168
|
-
}
|
|
6333
|
+
const dependencies = Object.fromEntries([...blueprint.dependencies].sort((left, right) => compareValues(left.name, right.name)).map((dependency) => [dependency.name, dependency.range]));
|
|
6334
|
+
const peers = [...blueprint.peers].sort((left, right) => compareValues(left.name, right.name));
|
|
6335
|
+
const peerDependencies = Object.fromEntries(peers.map((peer) => [peer.name, peer.range]));
|
|
6336
|
+
const peerDependenciesMeta = Object.fromEntries(peers.filter((peer) => peer.optional === true).map((peer) => [peer.name, { optional: true }]));
|
|
6169
6337
|
const entry = srcToEntry(blueprint.src);
|
|
6170
6338
|
const manifest = {
|
|
6171
6339
|
name,
|
|
@@ -6277,23 +6445,37 @@ function blueprintToMachinery(blueprint) {
|
|
|
6277
6445
|
* ```
|
|
6278
6446
|
*/
|
|
6279
6447
|
function blueprintToRootTsconfig(blueprint) {
|
|
6280
|
-
const aliases = [];
|
|
6281
|
-
for (const extension of blueprintToFaces(blueprint)) {
|
|
6282
|
-
if (extension.surface !== "browser") continue;
|
|
6283
|
-
for (const axis of extension.axes) aliases.push([`@${axis}/${extension.name}`, `./${axis}/${extension.name}/index.ts`]);
|
|
6284
|
-
if (extension.axes.includes("src")) aliases.push([`@orkestrel/${blueprint.name}/${extension.name}`, `./src/${extension.name}/index.ts`]);
|
|
6285
|
-
}
|
|
6286
|
-
for (const name of blueprintToSheets(blueprint)) aliases.push([`@src/${name}`, `./src/${name}/index.ts`]);
|
|
6287
|
-
for (const environment of ENVIRONMENTS) if (blueprint.src.includes(environment)) aliases.push([`@src/${environment}`, `./src/${environment}/index.ts`]);
|
|
6288
|
-
for (const environment of ENVIRONMENTS) if (blueprint.app.includes(environment)) aliases.push([`@app/${environment}`, `./app/${environment}/index.ts`]);
|
|
6289
6448
|
const root = srcToRoot(blueprint.src);
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6449
|
+
const aliases = [
|
|
6450
|
+
...blueprintToFaces(blueprint).flatMap((extension) => [...extension.axes.map((axis) => ({
|
|
6451
|
+
specifier: `@${axis}/${extension.name}`,
|
|
6452
|
+
target: `./${axis}/${extension.name}/index.ts`
|
|
6453
|
+
})), ...extension.axes.includes("src") ? [{
|
|
6454
|
+
specifier: `@orkestrel/${blueprint.name}/${extension.name}`,
|
|
6455
|
+
target: `./src/${extension.name}/index.ts`
|
|
6456
|
+
}] : []]),
|
|
6457
|
+
...blueprintToSheets(blueprint).map((name) => ({
|
|
6458
|
+
specifier: `@src/${name}`,
|
|
6459
|
+
target: `./src/${name}/index.ts`
|
|
6460
|
+
})),
|
|
6461
|
+
...ENVIRONMENTS.filter((environment) => blueprint.src.includes(environment)).map((environment) => ({
|
|
6462
|
+
specifier: `@src/${environment}`,
|
|
6463
|
+
target: `./src/${environment}/index.ts`
|
|
6464
|
+
})),
|
|
6465
|
+
...ENVIRONMENTS.filter((environment) => blueprint.app.includes(environment)).map((environment) => ({
|
|
6466
|
+
specifier: `@app/${environment}`,
|
|
6467
|
+
target: `./app/${environment}/index.ts`
|
|
6468
|
+
})),
|
|
6469
|
+
...root === void 0 ? ENVIRONMENTS.filter((environment) => environment !== "core" && blueprint.src.includes(environment)).map((environment) => ({
|
|
6470
|
+
specifier: `@orkestrel/${blueprint.name}${SRC_MATRIX[environment].path.slice(1)}`,
|
|
6471
|
+
target: `./src/${environment}/index.ts`
|
|
6472
|
+
})) : [],
|
|
6473
|
+
...blueprint.src.length > 0 ? [{
|
|
6474
|
+
specifier: `@orkestrel/${blueprint.name}`,
|
|
6475
|
+
target: `./src/${root ?? "core"}/index.ts`
|
|
6476
|
+
}] : []
|
|
6477
|
+
];
|
|
6478
|
+
const paths = aliases.map(({ specifier, target }, index) => {
|
|
6297
6479
|
const separator = index === aliases.length - 1 ? "" : ",";
|
|
6298
6480
|
const line = `\t\t\t"${specifier}": ["${target}"]${separator}`;
|
|
6299
6481
|
if (matchesPrintWidth(line)) return line;
|
|
@@ -6318,28 +6500,28 @@ function blueprintToProjects(blueprint) {
|
|
|
6318
6500
|
const sheets = blueprintToSheets(blueprint);
|
|
6319
6501
|
const styled = sheets.length > 0 || blueprint.themes;
|
|
6320
6502
|
const faces = blueprintToFaces(blueprint);
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6503
|
+
return [
|
|
6504
|
+
...sheets.map((name) => `src:${name}`),
|
|
6505
|
+
...blueprint.themes && !blueprint.styles ? ["src:themes"] : [],
|
|
6506
|
+
...AXES.flatMap((axis) => [
|
|
6507
|
+
...ENVIRONMENTS.filter((environment) => (axis !== "app" || environment !== "server") && blueprint[axis].includes(environment)).map((environment) => `${axis}:${environment}`),
|
|
6508
|
+
...faces.filter((face) => face.axes.includes(axis)).map((face) => `${axis}:${face.name}`),
|
|
6509
|
+
...axis === "src" && blueprint.bin ? ["src:bin"] : [],
|
|
6510
|
+
...axis === "app" && blueprint.app.includes("server") ? ["app:server"] : []
|
|
6511
|
+
]),
|
|
6512
|
+
"policy",
|
|
6513
|
+
"config",
|
|
6514
|
+
...blueprint.setup.includes("node") || blueprint.global ? ["setup"] : [],
|
|
6515
|
+
...blueprint.setup.includes("browser") || styled ? ["setup:browser"] : [],
|
|
6516
|
+
...blueprint.guides ? ["guides"] : [],
|
|
6517
|
+
...blueprint.skills ? ["skills"] : [],
|
|
6518
|
+
...blueprint.conformance ? ["conformance"] : [],
|
|
6519
|
+
...blueprint.service ? ["service"] : [],
|
|
6520
|
+
...blueprint.studies ? ["studies"] : [],
|
|
6521
|
+
...blueprint.src.length > 0 || styled ? ["distribution"] : [],
|
|
6522
|
+
...blueprint.integration ? ["integration"] : [],
|
|
6523
|
+
"probe"
|
|
6524
|
+
];
|
|
6343
6525
|
}
|
|
6344
6526
|
/**
|
|
6345
6527
|
* Compiles the browser projects' pre-bundled dependency list for a blueprint.
|
|
@@ -6398,18 +6580,18 @@ function blueprintToRootVite(blueprint) {
|
|
|
6398
6580
|
const sheets = blueprintToSheets(blueprint);
|
|
6399
6581
|
const styled = sheets.length > 0 || blueprint.themes;
|
|
6400
6582
|
const global = blueprint.global ? " globalSetup: ['./tests/setupGlobal.ts'],\n" : "";
|
|
6401
|
-
const imports = [
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
const projects = [];
|
|
6583
|
+
const imports = [
|
|
6584
|
+
...machinery.browser ? ["import { playwright } from '@vitest/browser-playwright'"] : [],
|
|
6585
|
+
...machinery.frameworks.includes("vue") ? ["import vue from '@vitejs/plugin-vue'"] : [],
|
|
6586
|
+
...machinery.showcase ? [
|
|
6587
|
+
"import { viteSingleFile } from 'vite-plugin-singlefile'",
|
|
6588
|
+
"import { renameSync } from 'node:fs'",
|
|
6589
|
+
"import { resolve as resolvePath } from 'node:path'"
|
|
6590
|
+
] : []
|
|
6591
|
+
];
|
|
6411
6592
|
const external = "external: resolveSourceExternal,";
|
|
6412
|
-
|
|
6593
|
+
const factories = [
|
|
6594
|
+
...blueprint.src.includes("browser") || blueprint.src.includes("server") ? [blueprint.src.includes("core") ? `function resolveSourceExternal(id: string): boolean {
|
|
6413
6595
|
return (
|
|
6414
6596
|
id === '@src/core' ||
|
|
6415
6597
|
resolveExternal(id, {
|
|
@@ -6422,29 +6604,16 @@ function blueprintToRootVite(blueprint) {
|
|
|
6422
6604
|
` : `function resolveSourceExternal(id: string): boolean {
|
|
6423
6605
|
return resolveExternal(id, { peers, refused: [], siblings: [] })
|
|
6424
6606
|
}
|
|
6425
|
-
`
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
if (planned.has("src:themes")) projects.push("'./configs/src/vite.themes.config.ts'");
|
|
6430
|
-
}
|
|
6431
|
-
if (planned.has("src:core")) {
|
|
6432
|
-
factories.push(CONFIG_TEMPLATES.factories.src.core);
|
|
6433
|
-
projects.push("srcCore");
|
|
6434
|
-
}
|
|
6435
|
-
if (planned.has("src:browser")) {
|
|
6436
|
-
const core = blueprint.src.includes("core");
|
|
6437
|
-
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.browser, {
|
|
6607
|
+
`] : [],
|
|
6608
|
+
...styled ? [CONFIG_TEMPLATES.factories.sheet] : [],
|
|
6609
|
+
...planned.has("src:core") ? [CONFIG_TEMPLATES.factories.src.core] : [],
|
|
6610
|
+
...planned.has("src:browser") ? [blueprint.src.includes("core")].map((core) => fillTemplate(CONFIG_TEMPLATES.factories.src.browser, {
|
|
6438
6611
|
external,
|
|
6439
6612
|
output: core ? " output: { paths: { '@src/core': '../core/index.js' } }," : " output: {},",
|
|
6440
6613
|
exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : "",
|
|
6441
6614
|
global
|
|
6442
|
-
}))
|
|
6443
|
-
|
|
6444
|
-
}
|
|
6445
|
-
if (planned.has("src:server")) {
|
|
6446
|
-
const core = blueprint.src.includes("core");
|
|
6447
|
-
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
|
|
6615
|
+
})) : [],
|
|
6616
|
+
...planned.has("src:server") ? [blueprint.src.includes("core")].map((core) => fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
|
|
6448
6617
|
external,
|
|
6449
6618
|
output: core ? `\t\t\t\toutput: [
|
|
6450
6619
|
{
|
|
@@ -6459,80 +6628,58 @@ function blueprintToRootVite(blueprint) {
|
|
|
6459
6628
|
},
|
|
6460
6629
|
],` : " output: {},",
|
|
6461
6630
|
exclude: core ? " exclude: ['tests/src/core/**/*.test.ts'],\n" : ""
|
|
6462
|
-
}))
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
}
|
|
6469
|
-
if (planned.has("src:bin")) {
|
|
6470
|
-
factories.push(CONFIG_TEMPLATES.factories.src.bin);
|
|
6471
|
-
projects.push("srcBin");
|
|
6472
|
-
}
|
|
6473
|
-
if (planned.has("app:core")) {
|
|
6474
|
-
factories.push(CONFIG_TEMPLATES.factories.app.core);
|
|
6475
|
-
projects.push("appCore");
|
|
6476
|
-
}
|
|
6477
|
-
if (planned.has("app:browser")) {
|
|
6478
|
-
const showcaseFactory = machinery.showcase ? CONFIG_TEMPLATES.factories.app.showcase : "";
|
|
6479
|
-
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.app.browser, {
|
|
6480
|
-
showcaseFactory,
|
|
6631
|
+
})) : [],
|
|
6632
|
+
...planned.has("src:vue") ? [CONFIG_TEMPLATES.factories.src.vue] : [],
|
|
6633
|
+
...planned.has("src:bin") ? [CONFIG_TEMPLATES.factories.src.bin] : [],
|
|
6634
|
+
...planned.has("app:core") ? [CONFIG_TEMPLATES.factories.app.core] : [],
|
|
6635
|
+
...planned.has("app:browser") ? [fillTemplate(CONFIG_TEMPLATES.factories.app.browser, {
|
|
6636
|
+
showcaseFactory: machinery.showcase ? CONFIG_TEMPLATES.factories.app.showcase : "",
|
|
6481
6637
|
journeyFactory: blueprint.journey ? CONFIG_TEMPLATES.factories.app.journey : "",
|
|
6482
6638
|
journeyExclude: blueprint.journey ? " exclude: ['tests/app/browser/integration.test.ts'],\n" : ""
|
|
6483
|
-
})
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
if (planned.has("app:server")) {
|
|
6491
|
-
factories.push(CONFIG_TEMPLATES.factories.app.server);
|
|
6492
|
-
projects.push("appServer");
|
|
6493
|
-
}
|
|
6494
|
-
factories.push(CONFIG_TEMPLATES.factories.policy);
|
|
6495
|
-
projects.push("policy");
|
|
6496
|
-
factories.push(CONFIG_TEMPLATES.factories.config);
|
|
6497
|
-
projects.push("config");
|
|
6498
|
-
if (planned.has("setup")) {
|
|
6499
|
-
factories.push(CONFIG_TEMPLATES.factories.setup);
|
|
6500
|
-
projects.push("setup");
|
|
6501
|
-
}
|
|
6502
|
-
if (planned.has("setup:browser")) {
|
|
6503
|
-
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.browser, {
|
|
6639
|
+
})] : [],
|
|
6640
|
+
...planned.has("app:vue") ? [fillTemplate(CONFIG_TEMPLATES.factories.app.vue, { journeyExclude: blueprint.journey ? " exclude: ['tests/app/vue/integration.test.ts'],\n" : " exclude: [],\n" })] : [],
|
|
6641
|
+
...planned.has("app:server") ? [CONFIG_TEMPLATES.factories.app.server] : [],
|
|
6642
|
+
CONFIG_TEMPLATES.factories.policy,
|
|
6643
|
+
CONFIG_TEMPLATES.factories.config,
|
|
6644
|
+
...planned.has("setup") ? [CONFIG_TEMPLATES.factories.setup] : [],
|
|
6645
|
+
...planned.has("setup:browser") ? [fillTemplate(CONFIG_TEMPLATES.factories.browser, {
|
|
6504
6646
|
optimization: machinery.frameworks.includes("vue") ? "optimizeDeps: { include: [...optimizeDeps.include, 'vue'] }" : "optimizeDeps",
|
|
6505
6647
|
plugins: machinery.frameworks.includes("vue") ? " plugins: [vue()],\n" : "",
|
|
6506
6648
|
global
|
|
6507
|
-
})
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6649
|
+
})] : [],
|
|
6650
|
+
...planned.has("guides") ? [CONFIG_TEMPLATES.factories.guides] : [],
|
|
6651
|
+
...planned.has("skills") ? [CONFIG_TEMPLATES.factories.skills] : [],
|
|
6652
|
+
...planned.has("conformance") ? [CONFIG_TEMPLATES.factories.conformance] : [],
|
|
6653
|
+
...planned.has("service") ? [CONFIG_TEMPLATES.factories.service] : [],
|
|
6654
|
+
...planned.has("studies") ? [CONFIG_TEMPLATES.factories.studies] : [],
|
|
6655
|
+
...planned.has("distribution") ? [CONFIG_TEMPLATES.factories.distribution] : [],
|
|
6656
|
+
...planned.has("integration") ? [fillTemplate(styled ? CONFIG_TEMPLATES.factories.integration.sheet : CONFIG_TEMPLATES.factories.integration.module, { global })] : [],
|
|
6657
|
+
CONFIG_TEMPLATES.factories.probe
|
|
6658
|
+
];
|
|
6659
|
+
const projects = [
|
|
6660
|
+
...styled ? [...sheets.map((name) => `'./configs/src/vite.${name}.config.ts'`), ...planned.has("src:themes") ? ["'./configs/src/vite.themes.config.ts'"] : []] : [],
|
|
6661
|
+
...planned.has("src:core") ? ["srcCore"] : [],
|
|
6662
|
+
...planned.has("src:browser") ? ["srcBrowser"] : [],
|
|
6663
|
+
...planned.has("src:server") ? ["srcServer"] : [],
|
|
6664
|
+
...planned.has("src:vue") ? ["srcVue"] : [],
|
|
6665
|
+
...planned.has("src:bin") ? ["srcBin"] : [],
|
|
6666
|
+
...planned.has("app:core") ? ["appCore"] : [],
|
|
6667
|
+
...planned.has("app:browser") ? ["appBrowser"] : [],
|
|
6668
|
+
...planned.has("app:vue") ? ["appVue"] : [],
|
|
6669
|
+
...planned.has("app:server") ? ["appServer"] : [],
|
|
6670
|
+
"policy",
|
|
6671
|
+
"config",
|
|
6672
|
+
...planned.has("setup") ? ["setup"] : [],
|
|
6673
|
+
...planned.has("setup:browser") ? ["setupBrowser"] : [],
|
|
6674
|
+
...planned.has("guides") ? ["guides"] : [],
|
|
6675
|
+
...planned.has("skills") ? ["skills"] : [],
|
|
6676
|
+
...planned.has("conformance") ? ["conformance"] : [],
|
|
6677
|
+
...planned.has("service") ? ["service"] : [],
|
|
6678
|
+
...planned.has("studies") ? ["studies"] : [],
|
|
6679
|
+
...planned.has("distribution") ? ["distribution"] : [],
|
|
6680
|
+
...planned.has("integration") ? ["integration"] : [],
|
|
6681
|
+
"probe"
|
|
6682
|
+
];
|
|
6536
6683
|
const joinedProjects = `\t\tprojects: [${projects.join(", ")}],`;
|
|
6537
6684
|
const projectRows = matchesPrintWidth(joinedProjects) ? joinedProjects : `\t\tprojects: [
|
|
6538
6685
|
${projects.map((project) => `\t\t\t${project},`).join("\n")}
|
|
@@ -6551,7 +6698,7 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
|
|
|
6551
6698
|
journey: blueprint.journey && blueprint.app.includes("browser") ? "import type { JourneyVariant } from '@orkestrel/test'\n" : "",
|
|
6552
6699
|
imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
|
|
6553
6700
|
helpers: helpers.length === 0 ? "" : matchesPrintWidth(helperImport.trimEnd()) ? helperImport : `import {\n${helpers.map((helper) => `\t${helper},`).join("\n")}\n} from './configs/helpers.js'\n`,
|
|
6554
|
-
browsers: machinery.browser ? "import { resolveBrowser, resolvePinnedBrowser } from './configs/browsers.js'\n" : "",
|
|
6701
|
+
browsers: machinery.browser ? "import { resolveBrowser, resolvePinnedBrowser } from './configs/browsers.js'\nimport { commands } from './configs/commands.js'\n" : "",
|
|
6555
6702
|
options: (machinery.browser ? "const browserOptions = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)\n\n" + blueprintToOptimizedDependencies(blueprint) : "") + (blueprint.journey && blueprint.app.includes("browser") ? "const capture = process.env.CAPTURE === '1'\n\n" : "") + ((blueprint.journey || blueprint.showcase) && blueprint.app.includes("browser") ? `const applications = {\n\tbrowser: appBrowser,\n${blueprintToFaces(blueprint).filter((extension) => extension.surface === "browser" && extension.axes.includes("app")).map((extension) => `\t${extension.name}: app${extension.name[0]?.toUpperCase()}${extension.name.slice(1)},\n`).join("")}}\n\n` : ""),
|
|
6556
6703
|
factories: body,
|
|
6557
6704
|
projects: projectRows
|
|
@@ -6573,7 +6720,7 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
|
|
|
6573
6720
|
* ```
|
|
6574
6721
|
*/
|
|
6575
6722
|
function blueprintToConfigArtifacts(blueprint) {
|
|
6576
|
-
const
|
|
6723
|
+
const roots = [{
|
|
6577
6724
|
path: "tsconfig.json",
|
|
6578
6725
|
group: "configs",
|
|
6579
6726
|
ownership: "content",
|
|
@@ -6586,172 +6733,167 @@ function blueprintToConfigArtifacts(blueprint) {
|
|
|
6586
6733
|
origin: "template",
|
|
6587
6734
|
content: blueprintToRootVite(blueprint)
|
|
6588
6735
|
}];
|
|
6589
|
-
|
|
6736
|
+
const browsers = blueprintToMachinery(blueprint).browser ? [{
|
|
6590
6737
|
path: "configs/browsers.ts",
|
|
6591
6738
|
group: "configs",
|
|
6592
6739
|
ownership: "content",
|
|
6593
6740
|
origin: "template",
|
|
6594
6741
|
content: CONFIG_TEMPLATES.browsers
|
|
6595
|
-
}
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6742
|
+
}, {
|
|
6743
|
+
path: "configs/commands.ts",
|
|
6744
|
+
group: "configs",
|
|
6745
|
+
ownership: "presence",
|
|
6746
|
+
origin: "template",
|
|
6747
|
+
content: CONFIG_TEMPLATES.commands
|
|
6748
|
+
}] : [];
|
|
6749
|
+
const sheets = [...blueprintToSheets(blueprint), ...blueprint.themes ? ["styles/themes"] : []].flatMap((name) => {
|
|
6750
|
+
const wrapper = {
|
|
6751
|
+
path: `configs/src/vite.${name === "styles/themes" ? "themes" : name}.config.ts`,
|
|
6600
6752
|
group: "configs",
|
|
6601
6753
|
ownership: "content",
|
|
6602
6754
|
origin: "template",
|
|
6603
6755
|
content: fillTemplate(CONFIG_TEMPLATES.vites.sheet, {
|
|
6604
6756
|
name,
|
|
6605
|
-
label
|
|
6757
|
+
label: name === "styles/themes" ? "themes" : name
|
|
6606
6758
|
})
|
|
6607
|
-
}
|
|
6608
|
-
|
|
6759
|
+
};
|
|
6760
|
+
return name === "styles/themes" ? [wrapper] : [wrapper, {
|
|
6609
6761
|
path: `configs/src/tsconfig.${name}.json`,
|
|
6610
6762
|
group: "configs",
|
|
6611
6763
|
ownership: "content",
|
|
6612
6764
|
origin: "template",
|
|
6613
6765
|
content: fillTemplate(CONFIG_TEMPLATES.tsconfigs.sheet, { name })
|
|
6614
|
-
}
|
|
6615
|
-
}
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
ownership: "content",
|
|
6627
|
-
origin: "template",
|
|
6628
|
-
environment,
|
|
6629
|
-
content
|
|
6630
|
-
});
|
|
6631
|
-
}
|
|
6632
|
-
if (blueprint.bin) {
|
|
6633
|
-
const paths = blueprint.src.map((environment) => `\t\t\t\t\t\t'@src/${environment}': '../src/${environment}/index.js',`);
|
|
6634
|
-
const renderedPaths = paths.length === 0 ? " paths: {}," : `\t\t\t\t\tpaths: {
|
|
6766
|
+
}];
|
|
6767
|
+
});
|
|
6768
|
+
const sources = Iterator.from(blueprint.src).flatMap((environment) => SRC_MATRIX[environment].configs.map((path) => ({
|
|
6769
|
+
path,
|
|
6770
|
+
group: "configs",
|
|
6771
|
+
ownership: "content",
|
|
6772
|
+
origin: "template",
|
|
6773
|
+
environment,
|
|
6774
|
+
content: path === "configs/src/tsconfig.core.json" ? CONFIG_TEMPLATES.tsconfigs.src.core : path === "configs/src/vite.browser.config.ts" ? CONFIG_TEMPLATES.vites.src.browser : path === "configs/src/tsconfig.browser.json" ? CONFIG_TEMPLATES.tsconfigs.src.browser : path === "configs/src/vite.server.config.ts" ? CONFIG_TEMPLATES.vites.src.server : path === "configs/src/tsconfig.server.json" ? CONFIG_TEMPLATES.tsconfigs.src.server : CONFIG_TEMPLATES.vites.src.core
|
|
6775
|
+
}))).toArray();
|
|
6776
|
+
const paths = blueprint.bin ? blueprint.src.map((environment) => `\t\t\t\t\t\t'@src/${environment}': '../src/${environment}/index.js',`) : [];
|
|
6777
|
+
const renderedPaths = paths.length === 0 ? " paths: {}," : `\t\t\t\t\tpaths: {
|
|
6635
6778
|
${paths.join("\n")}
|
|
6636
6779
|
},`;
|
|
6637
|
-
|
|
6638
|
-
|
|
6780
|
+
const bins = blueprint.bin ? BIN_CONFIGS.map((path) => ({
|
|
6781
|
+
path,
|
|
6782
|
+
group: "configs",
|
|
6783
|
+
ownership: "content",
|
|
6784
|
+
origin: "template",
|
|
6785
|
+
content: path === "configs/src/tsconfig.bin.json" ? CONFIG_TEMPLATES.tsconfigs.bin : fillTemplate(CONFIG_TEMPLATES.vites.bin, { paths: renderedPaths })
|
|
6786
|
+
})) : [];
|
|
6787
|
+
const includeSuffixes = [
|
|
6788
|
+
"cts",
|
|
6789
|
+
"mts",
|
|
6790
|
+
"ts",
|
|
6791
|
+
"tsx"
|
|
6792
|
+
];
|
|
6793
|
+
const applications = Iterator.from(blueprint.app).flatMap((environment) => APP_MATRIX[environment].configs.map((path) => ({
|
|
6794
|
+
path,
|
|
6795
|
+
group: "configs",
|
|
6796
|
+
ownership: "content",
|
|
6797
|
+
origin: "template",
|
|
6798
|
+
environment,
|
|
6799
|
+
content: path === "configs/app/vite.browser.config.ts" ? CONFIG_TEMPLATES.vites.app.browser : path === "configs/app/tsconfig.browser.json" ? fillTemplate(CONFIG_TEMPLATES.tsconfigs.app.browser, { include: [
|
|
6800
|
+
...includeSuffixes.map((suffix) => `../../app/browser/**/*.${suffix}`),
|
|
6801
|
+
...blueprint.app.includes("core") ? includeSuffixes.map((suffix) => `../../app/core/**/*.${suffix}`) : [],
|
|
6802
|
+
...includeSuffixes.map((suffix) => `../../tests/app/browser/**/*.${suffix}`),
|
|
6803
|
+
"../../tests/setup.ts",
|
|
6804
|
+
"../../tests/setupBrowser.ts"
|
|
6805
|
+
].map((entry, index, entries) => `\t\t${JSON.stringify(entry)}${index === entries.length - 1 ? "" : ","}`).join("\n") }) : path === "configs/app/vite.server.config.ts" ? CONFIG_TEMPLATES.vites.app.server : path === "configs/app/tsconfig.server.json" ? fillTemplate(CONFIG_TEMPLATES.tsconfigs.app.server, { include: [
|
|
6806
|
+
...includeSuffixes.map((suffix) => `../../app/server/**/*.${suffix}`),
|
|
6807
|
+
...blueprint.app.includes("core") ? includeSuffixes.map((suffix) => `../../app/core/**/*.${suffix}`) : [],
|
|
6808
|
+
...includeSuffixes.map((suffix) => `../../tests/app/server/**/*.${suffix}`),
|
|
6809
|
+
"../../tests/setup.ts",
|
|
6810
|
+
"../../tests/setupServer.ts"
|
|
6811
|
+
].map((entry, index, entries) => `\t\t${JSON.stringify(entry)}${index === entries.length - 1 ? "" : ","}`).join("\n") }) : CONFIG_TEMPLATES.tsconfigs.app.core
|
|
6812
|
+
}))).toArray();
|
|
6813
|
+
const faces = blueprintToFaces(blueprint).flatMap((extension) => extension.axes.flatMap((axis) => {
|
|
6814
|
+
const include = [
|
|
6815
|
+
...[
|
|
6816
|
+
"cts",
|
|
6817
|
+
"mts",
|
|
6818
|
+
"ts",
|
|
6819
|
+
"tsx",
|
|
6820
|
+
...FRAMEWORK_MATRIX[extension.name].suffixes
|
|
6821
|
+
].map((suffix) => `../../app/${extension.name}/**/*.${suffix}`),
|
|
6822
|
+
...blueprint.app.includes("core") ? [
|
|
6823
|
+
"cts",
|
|
6824
|
+
"mts",
|
|
6825
|
+
"ts",
|
|
6826
|
+
"tsx"
|
|
6827
|
+
].map((suffix) => `../../app/core/**/*.${suffix}`) : [],
|
|
6828
|
+
...[
|
|
6829
|
+
"cts",
|
|
6830
|
+
"mts",
|
|
6831
|
+
"ts",
|
|
6832
|
+
"tsx",
|
|
6833
|
+
...FRAMEWORK_MATRIX[extension.name].suffixes
|
|
6834
|
+
].map((suffix) => `../../tests/app/${extension.name}/**/*.${suffix}`),
|
|
6835
|
+
"../../tests/setup.ts",
|
|
6836
|
+
"../../tests/setupBrowser.ts"
|
|
6837
|
+
];
|
|
6838
|
+
const siblings = blueprint.src.filter((environment) => environment === "core" || environment === "browser").flatMap((environment) => ["ts", "js"].map((suffix) => {
|
|
6839
|
+
const key = `\t[resolveWorkspacePath('src/${environment}/index.${suffix}').replaceAll('\\\\', '/')]:`;
|
|
6840
|
+
const value = `'@orkestrel/${blueprint.name}${environment === "browser" ? "/browser" : ""}',`;
|
|
6841
|
+
return matchesPrintWidth(`${key} ${value}`) ? `${key} ${value}` : `${key}\n\t\t${value}`;
|
|
6842
|
+
})).join("\n");
|
|
6843
|
+
return [{
|
|
6844
|
+
path: `configs/${axis}/vite.${extension.name}.config.ts`,
|
|
6639
6845
|
group: "configs",
|
|
6640
6846
|
ownership: "content",
|
|
6641
6847
|
origin: "template",
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
const include = [
|
|
6650
|
-
"../../app/browser/**/*.cts",
|
|
6651
|
-
"../../app/browser/**/*.mts",
|
|
6652
|
-
"../../app/browser/**/*.ts",
|
|
6653
|
-
"../../app/browser/**/*.tsx"
|
|
6654
|
-
];
|
|
6655
|
-
if (blueprint.app.includes("core")) include.push("../../app/core/**/*.cts", "../../app/core/**/*.mts", "../../app/core/**/*.ts", "../../app/core/**/*.tsx");
|
|
6656
|
-
include.push("../../tests/app/browser/**/*.cts", "../../tests/app/browser/**/*.mts", "../../tests/app/browser/**/*.ts", "../../tests/app/browser/**/*.tsx", "../../tests/setup.ts", "../../tests/setupBrowser.ts");
|
|
6657
|
-
content = fillTemplate(CONFIG_TEMPLATES.tsconfigs.app.browser, { include: include.map((entry, index) => `\t\t${JSON.stringify(entry)}${index === include.length - 1 ? "" : ","}`).join("\n") });
|
|
6658
|
-
} else if (path === "configs/app/vite.server.config.ts") content = CONFIG_TEMPLATES.vites.app.server;
|
|
6659
|
-
else if (path === "configs/app/tsconfig.server.json") {
|
|
6660
|
-
const include = [
|
|
6661
|
-
"../../app/server/**/*.cts",
|
|
6662
|
-
"../../app/server/**/*.mts",
|
|
6663
|
-
"../../app/server/**/*.ts",
|
|
6664
|
-
"../../app/server/**/*.tsx"
|
|
6665
|
-
];
|
|
6666
|
-
if (blueprint.app.includes("core")) include.push("../../app/core/**/*.cts", "../../app/core/**/*.mts", "../../app/core/**/*.ts", "../../app/core/**/*.tsx");
|
|
6667
|
-
include.push("../../tests/app/server/**/*.cts", "../../tests/app/server/**/*.mts", "../../tests/app/server/**/*.ts", "../../tests/app/server/**/*.tsx", "../../tests/setup.ts", "../../tests/setupServer.ts");
|
|
6668
|
-
content = fillTemplate(CONFIG_TEMPLATES.tsconfigs.app.server, { include: include.map((entry, index) => `\t\t${JSON.stringify(entry)}${index === include.length - 1 ? "" : ","}`).join("\n") });
|
|
6669
|
-
}
|
|
6670
|
-
artifacts.push({
|
|
6671
|
-
path,
|
|
6848
|
+
environment: "browser",
|
|
6849
|
+
content: axis === "src" ? fillTemplate(CONFIG_TEMPLATES.vites.src.vue, {
|
|
6850
|
+
siblings,
|
|
6851
|
+
refused: `[${FRAMEWORK_MATRIX[extension.name].refused.map((name) => serializeTypeScriptString(name)).join(", ")}]`
|
|
6852
|
+
}) : CONFIG_TEMPLATES.vites.app.vue
|
|
6853
|
+
}, {
|
|
6854
|
+
path: `configs/${axis}/tsconfig.${extension.name}.json`,
|
|
6672
6855
|
group: "configs",
|
|
6673
6856
|
ownership: "content",
|
|
6674
6857
|
origin: "template",
|
|
6675
|
-
environment,
|
|
6676
|
-
content
|
|
6677
|
-
}
|
|
6678
|
-
}
|
|
6679
|
-
|
|
6680
|
-
if (extension.surface !== "browser") continue;
|
|
6681
|
-
for (const axis of extension.axes) {
|
|
6682
|
-
const include = [
|
|
6683
|
-
...[
|
|
6684
|
-
"cts",
|
|
6685
|
-
"mts",
|
|
6686
|
-
"ts",
|
|
6687
|
-
"tsx",
|
|
6688
|
-
...FRAMEWORK_MATRIX[extension.name].suffixes
|
|
6689
|
-
].map((suffix) => `../../app/${extension.name}/**/*.${suffix}`),
|
|
6690
|
-
...blueprint.app.includes("core") ? [
|
|
6691
|
-
"cts",
|
|
6692
|
-
"mts",
|
|
6693
|
-
"ts",
|
|
6694
|
-
"tsx"
|
|
6695
|
-
].map((suffix) => `../../app/core/**/*.${suffix}`) : [],
|
|
6696
|
-
...[
|
|
6697
|
-
"cts",
|
|
6698
|
-
"mts",
|
|
6699
|
-
"ts",
|
|
6700
|
-
"tsx",
|
|
6701
|
-
...FRAMEWORK_MATRIX[extension.name].suffixes
|
|
6702
|
-
].map((suffix) => `../../tests/app/${extension.name}/**/*.${suffix}`),
|
|
6703
|
-
"../../tests/setup.ts",
|
|
6704
|
-
"../../tests/setupBrowser.ts"
|
|
6705
|
-
];
|
|
6706
|
-
const siblings = blueprint.src.filter((environment) => environment === "core" || environment === "browser").flatMap((environment) => ["ts", "js"].map((suffix) => {
|
|
6707
|
-
const key = `\t[resolveWorkspacePath('src/${environment}/index.${suffix}').replaceAll('\\\\', '/')]:`;
|
|
6708
|
-
const value = `'@orkestrel/${blueprint.name}${environment === "browser" ? "/browser" : ""}',`;
|
|
6709
|
-
return matchesPrintWidth(`${key} ${value}`) ? `${key} ${value}` : `${key}\n\t\t${value}`;
|
|
6710
|
-
})).join("\n");
|
|
6711
|
-
artifacts.push({
|
|
6712
|
-
path: `configs/${axis}/vite.${extension.name}.config.ts`,
|
|
6713
|
-
group: "configs",
|
|
6714
|
-
ownership: "content",
|
|
6715
|
-
origin: "template",
|
|
6716
|
-
environment: "browser",
|
|
6717
|
-
content: axis === "src" ? fillTemplate(CONFIG_TEMPLATES.vites.src.vue, {
|
|
6718
|
-
siblings,
|
|
6719
|
-
refused: `[${FRAMEWORK_MATRIX[extension.name].refused.map((name) => serializeTypeScriptString(name)).join(", ")}]`
|
|
6720
|
-
}) : CONFIG_TEMPLATES.vites.app.vue
|
|
6721
|
-
}, {
|
|
6722
|
-
path: `configs/${axis}/tsconfig.${extension.name}.json`,
|
|
6723
|
-
group: "configs",
|
|
6724
|
-
ownership: "content",
|
|
6725
|
-
origin: "template",
|
|
6726
|
-
environment: "browser",
|
|
6727
|
-
content: axis === "src" ? CONFIG_TEMPLATES.tsconfigs.vue.src : fillTemplate(CONFIG_TEMPLATES.tsconfigs.vue.app, { include: include.map((entry, index) => `\t\t${JSON.stringify(entry)}${index === include.length - 1 ? "" : ","}`).join("\n") })
|
|
6728
|
-
});
|
|
6729
|
-
}
|
|
6730
|
-
}
|
|
6731
|
-
if (blueprint.showcase && blueprint.app.includes("browser")) artifacts.push({
|
|
6858
|
+
environment: "browser",
|
|
6859
|
+
content: axis === "src" ? CONFIG_TEMPLATES.tsconfigs.vue.src : fillTemplate(CONFIG_TEMPLATES.tsconfigs.vue.app, { include: include.map((entry, index) => `\t\t${JSON.stringify(entry)}${index === include.length - 1 ? "" : ","}`).join("\n") })
|
|
6860
|
+
}];
|
|
6861
|
+
}));
|
|
6862
|
+
const showcase = blueprint.showcase && blueprint.app.includes("browser") ? [{
|
|
6732
6863
|
path: SHOWCASE_CONFIG_PATH,
|
|
6733
6864
|
group: "configs",
|
|
6734
6865
|
ownership: "content",
|
|
6735
6866
|
origin: "template",
|
|
6736
6867
|
environment: "browser",
|
|
6737
6868
|
content: CONFIG_TEMPLATES.vites.app.showcase
|
|
6738
|
-
}
|
|
6739
|
-
|
|
6869
|
+
}] : [];
|
|
6870
|
+
const journey = blueprint.journey && blueprint.app.includes("browser") ? [{
|
|
6740
6871
|
path: JOURNEY_CONFIG_PATH,
|
|
6741
6872
|
group: "configs",
|
|
6742
6873
|
ownership: "birth",
|
|
6743
6874
|
origin: "template",
|
|
6744
6875
|
environment: "browser",
|
|
6745
6876
|
content: CONFIG_TEMPLATES.vites.app.journey
|
|
6746
|
-
}
|
|
6747
|
-
|
|
6877
|
+
}] : [];
|
|
6878
|
+
const skills = blueprint.skills ? [{
|
|
6748
6879
|
path: SKILLS_CONFIG_PATH,
|
|
6749
6880
|
group: "configs",
|
|
6750
6881
|
ownership: "content",
|
|
6751
6882
|
origin: "template",
|
|
6752
6883
|
content: CONFIG_TEMPLATES.tsconfigs.skills
|
|
6753
|
-
}
|
|
6754
|
-
return
|
|
6884
|
+
}] : [];
|
|
6885
|
+
return [
|
|
6886
|
+
...roots,
|
|
6887
|
+
...browsers,
|
|
6888
|
+
...sheets,
|
|
6889
|
+
...sources,
|
|
6890
|
+
...bins,
|
|
6891
|
+
...applications,
|
|
6892
|
+
...faces,
|
|
6893
|
+
...showcase,
|
|
6894
|
+
...journey,
|
|
6895
|
+
...skills
|
|
6896
|
+
];
|
|
6755
6897
|
}
|
|
6756
6898
|
/**
|
|
6757
6899
|
* Compiles every artifact in the `source` group.
|
|
@@ -6773,100 +6915,109 @@ ${paths.join("\n")}
|
|
|
6773
6915
|
* ```
|
|
6774
6916
|
*/
|
|
6775
6917
|
function blueprintToSourceArtifacts(blueprint) {
|
|
6776
|
-
const
|
|
6777
|
-
if (blueprint.themes && !blueprint.styles) artifacts.push({
|
|
6918
|
+
const tokens = blueprint.themes && !blueprint.styles ? [{
|
|
6778
6919
|
path: "src/styles/_tokens.scss",
|
|
6779
6920
|
group: "source",
|
|
6780
6921
|
ownership: "birth",
|
|
6781
6922
|
origin: "template",
|
|
6782
6923
|
content: ARTIFACT_TEMPLATES.source.sheet["_tokens.scss"]
|
|
6783
|
-
}
|
|
6784
|
-
|
|
6924
|
+
}] : [];
|
|
6925
|
+
const sheets = [...blueprintToSheets(blueprint), ...blueprint.themes ? ["styles/themes"] : []].flatMap((name) => Object.entries(name === "styles/themes" ? ARTIFACT_TEMPLATES.source.themes : ARTIFACT_TEMPLATES.source.sheet).map(([path, content]) => ({
|
|
6785
6926
|
path: `src/${name}/${path}`,
|
|
6786
6927
|
group: "source",
|
|
6787
6928
|
ownership: "birth",
|
|
6788
6929
|
origin: "template",
|
|
6789
6930
|
content
|
|
6790
|
-
});
|
|
6791
|
-
|
|
6931
|
+
})));
|
|
6932
|
+
const sources = Iterator.from(blueprint.src).map((environment) => ({
|
|
6792
6933
|
path: `src/${environment}/index.ts`,
|
|
6793
6934
|
group: "source",
|
|
6794
6935
|
ownership: "birth",
|
|
6795
6936
|
origin: "template",
|
|
6796
6937
|
environment,
|
|
6797
6938
|
content: ARTIFACT_TEMPLATES.source.empty
|
|
6798
|
-
});
|
|
6799
|
-
|
|
6800
|
-
|
|
6939
|
+
})).toArray();
|
|
6940
|
+
const applications = Iterator.from(blueprint.app).flatMap((environment) => {
|
|
6941
|
+
const entry = {
|
|
6801
6942
|
path: `app/${environment}/index.ts`,
|
|
6802
6943
|
group: "source",
|
|
6803
6944
|
ownership: "birth",
|
|
6804
6945
|
origin: "template",
|
|
6805
6946
|
environment,
|
|
6806
6947
|
content: ARTIFACT_TEMPLATES.source.empty
|
|
6807
|
-
}
|
|
6808
|
-
if (environment === "browser")
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6948
|
+
};
|
|
6949
|
+
if (environment === "browser") return [
|
|
6950
|
+
entry,
|
|
6951
|
+
{
|
|
6952
|
+
path: "app/browser/main.ts",
|
|
6953
|
+
group: "source",
|
|
6954
|
+
ownership: "birth",
|
|
6955
|
+
origin: "template",
|
|
6956
|
+
environment,
|
|
6957
|
+
content: fillTemplate(ARTIFACT_TEMPLATES.source.main, { heading: `${matchesPrintWidth(`\t.appendChild(document.createElement('h1')).textContent = ${serializeTypeScriptString(blueprint.name)}`) ? " " : "\n "}${serializeTypeScriptString(blueprint.name)}` })
|
|
6958
|
+
},
|
|
6959
|
+
{
|
|
6960
|
+
path: "app/browser/index.html",
|
|
6961
|
+
group: "source",
|
|
6962
|
+
ownership: "birth",
|
|
6963
|
+
origin: "template",
|
|
6964
|
+
environment,
|
|
6965
|
+
content: ARTIFACT_TEMPLATES.source.browser
|
|
6966
|
+
}
|
|
6967
|
+
];
|
|
6968
|
+
return environment === "server" ? [entry, {
|
|
6969
|
+
path: "app/server/main.ts",
|
|
6817
6970
|
group: "source",
|
|
6818
6971
|
ownership: "birth",
|
|
6819
6972
|
origin: "template",
|
|
6820
6973
|
environment,
|
|
6821
|
-
content: ARTIFACT_TEMPLATES.source.
|
|
6822
|
-
}
|
|
6823
|
-
|
|
6824
|
-
|
|
6974
|
+
content: ARTIFACT_TEMPLATES.source.empty
|
|
6975
|
+
}] : [entry];
|
|
6976
|
+
}).toArray();
|
|
6977
|
+
const faces = blueprintToFaces(blueprint).flatMap((extension) => extension.axes.flatMap((axis) => {
|
|
6978
|
+
const barrel = {
|
|
6979
|
+
path: `${axis}/${extension.name}/index.ts`,
|
|
6825
6980
|
group: "source",
|
|
6826
6981
|
ownership: "birth",
|
|
6827
6982
|
origin: "template",
|
|
6828
|
-
environment,
|
|
6829
|
-
content: ARTIFACT_TEMPLATES.source.empty
|
|
6830
|
-
}
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
for (const axis of extension.axes) {
|
|
6835
|
-
artifacts.push({
|
|
6836
|
-
path: `${axis}/${extension.name}/index.ts`,
|
|
6837
|
-
group: "source",
|
|
6838
|
-
ownership: "birth",
|
|
6839
|
-
origin: "template",
|
|
6840
|
-
environment: "browser",
|
|
6841
|
-
content: axis === "app" ? ARTIFACT_TEMPLATES.source.empty : ARTIFACT_TEMPLATES.source.barrel
|
|
6842
|
-
});
|
|
6843
|
-
if (axis !== "app") continue;
|
|
6844
|
-
artifacts.push({
|
|
6983
|
+
environment: "browser",
|
|
6984
|
+
content: axis === "app" ? ARTIFACT_TEMPLATES.source.empty : ARTIFACT_TEMPLATES.source.barrel
|
|
6985
|
+
};
|
|
6986
|
+
return axis === "app" ? [
|
|
6987
|
+
barrel,
|
|
6988
|
+
{
|
|
6845
6989
|
path: `app/${extension.name}/index.html`,
|
|
6846
6990
|
group: "source",
|
|
6847
6991
|
ownership: "birth",
|
|
6848
6992
|
origin: "template",
|
|
6849
6993
|
environment: "browser",
|
|
6850
6994
|
content: ARTIFACT_TEMPLATES.source.browser
|
|
6851
|
-
}
|
|
6852
|
-
|
|
6995
|
+
},
|
|
6996
|
+
...Object.entries(ARTIFACT_TEMPLATES.source.vue).map(([path, content]) => ({
|
|
6853
6997
|
path: `app/${extension.name}/${path}`,
|
|
6854
6998
|
group: "source",
|
|
6855
6999
|
ownership: "birth",
|
|
6856
7000
|
origin: "template",
|
|
6857
7001
|
environment: "browser",
|
|
6858
7002
|
content: fillTemplate(content, { heading: matchesPrintWidth(`\t<h1>${blueprint.name}</h1>`) ? blueprint.name : `\n\t\t${blueprint.name}\n\t` })
|
|
6859
|
-
})
|
|
6860
|
-
|
|
6861
|
-
}
|
|
6862
|
-
|
|
7003
|
+
}))
|
|
7004
|
+
] : [barrel];
|
|
7005
|
+
}));
|
|
7006
|
+
const bin = blueprint.bin ? [{
|
|
6863
7007
|
path: BIN_ENTRY_PATH,
|
|
6864
7008
|
group: "source",
|
|
6865
7009
|
ownership: "birth",
|
|
6866
7010
|
origin: "template",
|
|
6867
7011
|
content: ARTIFACT_TEMPLATES.source.empty
|
|
6868
|
-
}
|
|
6869
|
-
return
|
|
7012
|
+
}] : [];
|
|
7013
|
+
return [
|
|
7014
|
+
...tokens,
|
|
7015
|
+
...sheets,
|
|
7016
|
+
...sources,
|
|
7017
|
+
...applications,
|
|
7018
|
+
...faces,
|
|
7019
|
+
...bin
|
|
7020
|
+
];
|
|
6870
7021
|
}
|
|
6871
7022
|
/**
|
|
6872
7023
|
* Compiles every artifact in the `tests` group that is not vendored from the host.
|
|
@@ -6885,7 +7036,8 @@ function blueprintToSourceArtifacts(blueprint) {
|
|
|
6885
7036
|
* is not: it names an official artifact only the package knows, so a generated
|
|
6886
7037
|
* placeholder would read as a proof while measuring nothing. `service` emits its
|
|
6887
7038
|
* readiness setup alone, because the root configuration names that module by
|
|
6888
|
-
* path.
|
|
7039
|
+
* path. `studies` emits nothing: the root configuration names no study harness,
|
|
7040
|
+
* so `tests/setupStudy.ts` is the package's own module.
|
|
6889
7041
|
*
|
|
6890
7042
|
* The distribution proof is emitted, and the same test separates it from those
|
|
6891
7043
|
* two: its subject is the packed tarball rather than anything only the package
|
|
@@ -6904,29 +7056,19 @@ function blueprintToSourceArtifacts(blueprint) {
|
|
|
6904
7056
|
* ```
|
|
6905
7057
|
*/
|
|
6906
7058
|
function blueprintToTestArtifacts(blueprint) {
|
|
6907
|
-
const
|
|
6908
|
-
|
|
7059
|
+
const sheets = [...blueprintToSheets(blueprint), ...blueprint.themes ? ["styles/themes"] : []];
|
|
7060
|
+
const faces = blueprintToFaces(blueprint).flatMap((extension) => extension.axes.map((axis) => ({
|
|
7061
|
+
path: `tests/${axis}/${extension.name}/index.test.ts`,
|
|
6909
7062
|
group: "tests",
|
|
6910
7063
|
ownership: "birth",
|
|
6911
7064
|
origin: "template",
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
group: "tests",
|
|
6920
|
-
ownership: "birth",
|
|
6921
|
-
origin: "template",
|
|
6922
|
-
environment: "browser",
|
|
6923
|
-
content: fillTemplate(ARTIFACT_TEMPLATES.tests.entry, {
|
|
6924
|
-
specifier: serializeTypeScriptString(`@${axis}/${extension.name}`),
|
|
6925
|
-
label: serializeTypeScriptString(`${axis} ${extension.name} entry`)
|
|
6926
|
-
})
|
|
6927
|
-
});
|
|
6928
|
-
}
|
|
6929
|
-
if (sheets.length > 0) artifacts.push({
|
|
7065
|
+
environment: "browser",
|
|
7066
|
+
content: fillTemplate(ARTIFACT_TEMPLATES.tests.entry, {
|
|
7067
|
+
specifier: serializeTypeScriptString(`@${axis}/${extension.name}`),
|
|
7068
|
+
label: serializeTypeScriptString(`${axis} ${extension.name} entry`)
|
|
7069
|
+
})
|
|
7070
|
+
})));
|
|
7071
|
+
const styles = sheets.length > 0 ? [{
|
|
6930
7072
|
path: "tests/setupStyles.ts",
|
|
6931
7073
|
group: "tests",
|
|
6932
7074
|
ownership: "birth",
|
|
@@ -6938,10 +7080,10 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
6938
7080
|
ownership: "birth",
|
|
6939
7081
|
origin: "template",
|
|
6940
7082
|
content: ARTIFACT_TEMPLATES.tests.styles.proof
|
|
6941
|
-
}
|
|
6942
|
-
|
|
7083
|
+
}] : [];
|
|
7084
|
+
const sheetTests = sheets.map((name) => {
|
|
6943
7085
|
const tests = "../".repeat(name.split("/").length + 1);
|
|
6944
|
-
|
|
7086
|
+
return {
|
|
6945
7087
|
path: `tests/src/${name}/index.test.ts`,
|
|
6946
7088
|
group: "tests",
|
|
6947
7089
|
ownership: "birth",
|
|
@@ -6951,66 +7093,60 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
6951
7093
|
root: `${tests}../`,
|
|
6952
7094
|
setup: `${tests}setupStyles.js`
|
|
6953
7095
|
})
|
|
6954
|
-
}
|
|
6955
|
-
}
|
|
6956
|
-
|
|
7096
|
+
};
|
|
7097
|
+
});
|
|
7098
|
+
const browsers = blueprintToMachinery(blueprint).browser ? [{
|
|
6957
7099
|
path: "tests/setupBrowser.ts",
|
|
6958
7100
|
group: "tests",
|
|
6959
7101
|
ownership: "birth",
|
|
6960
7102
|
origin: "template",
|
|
6961
7103
|
environment: "browser",
|
|
6962
7104
|
content: blueprint.journey ? ARTIFACT_TEMPLATES.tests.browser : ARTIFACT_TEMPLATES.tests.setup
|
|
6963
|
-
}
|
|
6964
|
-
|
|
7105
|
+
}] : [];
|
|
7106
|
+
const servers = blueprint.src.includes("server") || blueprint.app.includes("server") || blueprint.bin || blueprint.conformance ? [{
|
|
6965
7107
|
path: "tests/setupServer.ts",
|
|
6966
7108
|
group: "tests",
|
|
6967
7109
|
ownership: "birth",
|
|
6968
7110
|
origin: "template",
|
|
6969
7111
|
environment: "server",
|
|
6970
7112
|
content: ARTIFACT_TEMPLATES.tests.setup
|
|
6971
|
-
}
|
|
6972
|
-
|
|
7113
|
+
}] : [];
|
|
7114
|
+
const services = blueprint.service ? [{
|
|
6973
7115
|
path: SERVICE_SETUP_PATH,
|
|
6974
7116
|
group: "tests",
|
|
6975
7117
|
ownership: "birth",
|
|
6976
7118
|
origin: "template",
|
|
6977
7119
|
content: ARTIFACT_TEMPLATES.tests.setup
|
|
6978
|
-
}
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
}
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
arrival: application === "vue" ? " app.mount(container)\n" : " await import('../../../app/browser/main.js')\n",
|
|
7009
|
-
cleanup: application === "vue" ? " app.unmount()\n container.remove()\n" : " for (const main of page.getByRole('main').elements()) main.remove()\n"
|
|
7010
|
-
})
|
|
7011
|
-
});
|
|
7012
|
-
}
|
|
7013
|
-
for (const environment of blueprint.src) artifacts.push({
|
|
7120
|
+
}] : [];
|
|
7121
|
+
const globals = blueprint.global ? [{
|
|
7122
|
+
path: GLOBAL_SETUP_PATH,
|
|
7123
|
+
group: "tests",
|
|
7124
|
+
ownership: "birth",
|
|
7125
|
+
origin: "template",
|
|
7126
|
+
content: ARTIFACT_TEMPLATES.tests.global.module
|
|
7127
|
+
}, {
|
|
7128
|
+
path: "tests/setupGlobal.test.ts",
|
|
7129
|
+
group: "tests",
|
|
7130
|
+
ownership: "birth",
|
|
7131
|
+
origin: "template",
|
|
7132
|
+
content: ARTIFACT_TEMPLATES.tests.global.proof
|
|
7133
|
+
}] : [];
|
|
7134
|
+
const journeys = blueprint.journey && blueprint.app.includes("browser") ? ["browser", ...blueprintToFaces(blueprint).flatMap((extension) => extension.surface === "browser" && extension.axes.includes("app") ? [extension.name] : [])].map((application) => ({
|
|
7135
|
+
path: `tests/app/${application}/integration.test.ts`,
|
|
7136
|
+
group: "tests",
|
|
7137
|
+
ownership: "birth",
|
|
7138
|
+
origin: "template",
|
|
7139
|
+
environment: "browser",
|
|
7140
|
+
content: fillTemplate(ARTIFACT_TEMPLATES.tests.journey, {
|
|
7141
|
+
application,
|
|
7142
|
+
heading: serializeTypeScriptString(blueprint.name),
|
|
7143
|
+
imports: application === "vue" ? "import { createApp } from 'vue'\nimport App from '../../../app/vue/App.vue'\n" : "",
|
|
7144
|
+
mount: application === "vue" ? " const container = document.body.appendChild(document.createElement('main'))\n const app = createApp(App)\n" : "",
|
|
7145
|
+
arrival: application === "vue" ? " app.mount(container)\n" : " await import('../../../app/browser/main.js')\n",
|
|
7146
|
+
cleanup: application === "vue" ? " app.unmount()\n container.remove()\n" : " for (const main of page.getByRole('main').elements()) main.remove()\n"
|
|
7147
|
+
})
|
|
7148
|
+
})) : [];
|
|
7149
|
+
const sources = Iterator.from(blueprint.src).map((environment) => ({
|
|
7014
7150
|
path: `tests/src/${environment}/index.test.ts`,
|
|
7015
7151
|
group: "tests",
|
|
7016
7152
|
ownership: "birth",
|
|
@@ -7020,20 +7156,17 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
7020
7156
|
specifier: serializeTypeScriptString(`@src/${environment}`),
|
|
7021
7157
|
label: serializeTypeScriptString(`src ${environment} entry`)
|
|
7022
7158
|
})
|
|
7023
|
-
});
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
});
|
|
7035
|
-
}
|
|
7036
|
-
for (const environment of blueprint.app) artifacts.push({
|
|
7159
|
+
})).toArray();
|
|
7160
|
+
const binSpecifier = serializeTypeScriptString("../../../src/bin/main.js");
|
|
7161
|
+
const joinedImport = `\t\tconst entry = await import(${binSpecifier})`;
|
|
7162
|
+
const bins = blueprint.bin ? [{
|
|
7163
|
+
path: "tests/src/bin/main.test.ts",
|
|
7164
|
+
group: "tests",
|
|
7165
|
+
ownership: "birth",
|
|
7166
|
+
origin: "template",
|
|
7167
|
+
content: fillTemplate(ARTIFACT_TEMPLATES.tests.bin, { import: matchesPrintWidth(joinedImport) ? joinedImport : `\t\tconst entry =\n\t\t\tawait import(${binSpecifier})` })
|
|
7168
|
+
}] : [];
|
|
7169
|
+
const applications = Iterator.from(blueprint.app).map((environment) => ({
|
|
7037
7170
|
path: `tests/app/${environment}/index.test.ts`,
|
|
7038
7171
|
group: "tests",
|
|
7039
7172
|
ownership: "birth",
|
|
@@ -7043,43 +7176,36 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
7043
7176
|
specifier: serializeTypeScriptString(`@app/${environment}`),
|
|
7044
7177
|
label: serializeTypeScriptString(`app ${environment} entry`)
|
|
7045
7178
|
})
|
|
7046
|
-
});
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
entries.push(entry);
|
|
7072
|
-
}
|
|
7073
|
-
for (const environment of blueprint.app) {
|
|
7074
|
-
const entry = environment === "core" ? "appCore" : environment === "browser" ? "appBrowser" : "appServer";
|
|
7075
|
-
imports.push(`import * as ${entry} from '@app/${environment}'`);
|
|
7076
|
-
entries.push(entry);
|
|
7077
|
-
}
|
|
7179
|
+
})).toArray();
|
|
7180
|
+
const distribution = ARTIFACT_TEMPLATES.tests.distribution;
|
|
7181
|
+
const distributions = blueprint.src.length > 0 || blueprintToSheets(blueprint).length > 0 || blueprint.themes ? [blueprint.src.includes("browser")].map((browser) => ({
|
|
7182
|
+
path: DISTRIBUTION_TEST_PATH,
|
|
7183
|
+
group: "tests",
|
|
7184
|
+
ownership: "presence",
|
|
7185
|
+
origin: "template",
|
|
7186
|
+
content: fillTemplate(distribution.proof, {
|
|
7187
|
+
types: browser ? distribution.types : "",
|
|
7188
|
+
transport: browser ? distribution.transport : "",
|
|
7189
|
+
launcher: browser ? distribution.launcher : "",
|
|
7190
|
+
helpers: browser ? distribution.helpers : "",
|
|
7191
|
+
drive: browser ? distribution.drive : "",
|
|
7192
|
+
guard: browser ? "" : distribution.guard
|
|
7193
|
+
})
|
|
7194
|
+
})) : [];
|
|
7195
|
+
const integrations = blueprint.integration ? [[...Iterator.from(blueprint.src).map((environment) => ({
|
|
7196
|
+
entry: environment === "core" ? "srcCore" : environment === "browser" ? "srcBrowser" : "srcServer",
|
|
7197
|
+
specifier: `@src/${environment}`
|
|
7198
|
+
})).toArray(), ...Iterator.from(blueprint.app).map((environment) => ({
|
|
7199
|
+
entry: environment === "core" ? "appCore" : environment === "browser" ? "appBrowser" : "appServer",
|
|
7200
|
+
specifier: `@app/${environment}`
|
|
7201
|
+
})).toArray()]].map((modules) => {
|
|
7202
|
+
const entries = modules.map(({ entry }) => entry);
|
|
7203
|
+
const imports = modules.map(({ entry, specifier }) => `import * as ${entry} from '${specifier}'`);
|
|
7078
7204
|
const joined = `expect([${entries.map((entry) => `Object.keys(${entry})`).join(", ")}]).toStrictEqual(`;
|
|
7079
7205
|
const actual = matchesPrintWidth(`\t\t${joined}[`) ? joined : `expect([\n${entries.map((entry) => `\t\t\tObject.keys(${entry}),`).join("\n")}\n\t\t]).toStrictEqual(`;
|
|
7080
7206
|
const expectedInline = `[${entries.map(() => "[]").join(", ")}]`;
|
|
7081
7207
|
const expected = actual !== joined || matchesPrintWidth(`\t\t${joined}${expectedInline})`) ? expectedInline : `[\n${entries.map(() => " [],").join("\n")}\n\t\t]`;
|
|
7082
|
-
|
|
7208
|
+
return {
|
|
7083
7209
|
path: INTEGRATION_TEST_PATH,
|
|
7084
7210
|
group: "tests",
|
|
7085
7211
|
ownership: "birth",
|
|
@@ -7089,9 +7215,30 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
7089
7215
|
actual,
|
|
7090
7216
|
expected
|
|
7091
7217
|
})
|
|
7092
|
-
}
|
|
7093
|
-
}
|
|
7094
|
-
return
|
|
7218
|
+
};
|
|
7219
|
+
}) : [];
|
|
7220
|
+
return [
|
|
7221
|
+
{
|
|
7222
|
+
path: "tests/setup.ts",
|
|
7223
|
+
group: "tests",
|
|
7224
|
+
ownership: "birth",
|
|
7225
|
+
origin: "template",
|
|
7226
|
+
content: ARTIFACT_TEMPLATES.tests.setup
|
|
7227
|
+
},
|
|
7228
|
+
...faces,
|
|
7229
|
+
...styles,
|
|
7230
|
+
...sheetTests,
|
|
7231
|
+
...browsers,
|
|
7232
|
+
...servers,
|
|
7233
|
+
...services,
|
|
7234
|
+
...globals,
|
|
7235
|
+
...journeys,
|
|
7236
|
+
...sources,
|
|
7237
|
+
...bins,
|
|
7238
|
+
...applications,
|
|
7239
|
+
...distributions,
|
|
7240
|
+
...integrations
|
|
7241
|
+
];
|
|
7095
7242
|
}
|
|
7096
7243
|
/**
|
|
7097
7244
|
* Compiles the generated workspace's guide index.
|
|
@@ -7109,30 +7256,29 @@ function blueprintToTestArtifacts(blueprint) {
|
|
|
7109
7256
|
* ```
|
|
7110
7257
|
*/
|
|
7111
7258
|
function blueprintToGuideArtifacts(blueprint) {
|
|
7112
|
-
const source = [];
|
|
7113
|
-
const tests = [];
|
|
7114
|
-
const directories = [];
|
|
7115
7259
|
const guide = `guides/${blueprint.name}.md`;
|
|
7116
|
-
|
|
7117
|
-
...
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
}
|
|
7260
|
+
const rows = [
|
|
7261
|
+
...[
|
|
7262
|
+
...blueprint.src,
|
|
7263
|
+
...blueprintToFaces(blueprint).filter((extension) => extension.axes.includes("src")).map((extension) => extension.name),
|
|
7264
|
+
...blueprintToSheets(blueprint),
|
|
7265
|
+
...blueprint.themes ? ["styles/themes"] : []
|
|
7266
|
+
].map((environment) => ({
|
|
7267
|
+
directory: `src/${environment}`,
|
|
7268
|
+
test: `tests/src/${environment}`
|
|
7269
|
+
})),
|
|
7270
|
+
...blueprint.bin ? [{
|
|
7271
|
+
directory: "src/bin",
|
|
7272
|
+
test: "tests/src/bin"
|
|
7273
|
+
}] : [],
|
|
7274
|
+
...[...blueprint.app, ...blueprintToFaces(blueprint).filter((extension) => extension.axes.includes("app")).map((extension) => extension.name)].map((environment) => ({
|
|
7275
|
+
directory: `app/${environment}`,
|
|
7276
|
+
test: `tests/app/${environment}`
|
|
7277
|
+
}))
|
|
7278
|
+
];
|
|
7279
|
+
const source = rows.map(({ directory }) => ` - [\`${directory}\`](../${directory})`);
|
|
7280
|
+
const tests = rows.map(({ test }) => ` - [\`${test}\`](../${test})`);
|
|
7281
|
+
const directories = rows.map(({ directory, test }) => `- [\`${directory}\`](../${directory})\n - Guide: Not created. Create this file when the workspace has a public surface:\n \`${guide}\`\n - Tests: [\`${test}\`](../${test})`);
|
|
7136
7282
|
return [{
|
|
7137
7283
|
path: "guides/README.md",
|
|
7138
7284
|
group: "guides",
|
|
@@ -7384,155 +7530,54 @@ function applyOverrides(artifacts, overrides) {
|
|
|
7384
7530
|
*/
|
|
7385
7531
|
function replaceManifestRanges(manifest, pins) {
|
|
7386
7532
|
if (pins.runtime.length === 0 && pins.development.length === 0) return manifest;
|
|
7533
|
+
const tokens = scanManifestTokens(manifest);
|
|
7534
|
+
if (tokens === void 0) return void 0;
|
|
7387
7535
|
const sectionNames = /* @__PURE__ */ new Set(["dependencies", "devDependencies"]);
|
|
7388
|
-
const
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
const key = parseJSON(manifest.slice(start, end));
|
|
7421
|
-
let value = end;
|
|
7422
|
-
while (value < manifest.length && /\s/u.test(manifest.charAt(value))) value += 1;
|
|
7423
|
-
if (manifest.charAt(value) === ":") {
|
|
7424
|
-
value += 1;
|
|
7425
|
-
while (value < manifest.length && /\s/u.test(manifest.charAt(value))) value += 1;
|
|
7426
|
-
if (isString(key) && sectionNames.has(key) && manifest.charAt(value) === "{") {
|
|
7427
|
-
let sectionDepth = 0;
|
|
7428
|
-
let sectionCursor = value;
|
|
7429
|
-
while (sectionCursor < manifest.length) {
|
|
7430
|
-
const sectionCharacter = manifest.charAt(sectionCursor);
|
|
7431
|
-
if (sectionCharacter === "\"") {
|
|
7432
|
-
sectionCursor += 1;
|
|
7433
|
-
while (sectionCursor < manifest.length) {
|
|
7434
|
-
if (manifest.charAt(sectionCursor) === "\\") {
|
|
7435
|
-
sectionCursor += 2;
|
|
7436
|
-
continue;
|
|
7437
|
-
}
|
|
7438
|
-
if (manifest.charAt(sectionCursor) === "\"") break;
|
|
7439
|
-
sectionCursor += 1;
|
|
7440
|
-
}
|
|
7441
|
-
if (sectionCursor >= manifest.length) return void 0;
|
|
7442
|
-
} else if (sectionCharacter === "{") sectionDepth += 1;
|
|
7443
|
-
else if (sectionCharacter === "}") {
|
|
7444
|
-
sectionDepth -= 1;
|
|
7445
|
-
if (sectionDepth === 0) {
|
|
7446
|
-
sections.push({
|
|
7447
|
-
name: key,
|
|
7448
|
-
start: value,
|
|
7449
|
-
end: sectionCursor + 1
|
|
7450
|
-
});
|
|
7451
|
-
break;
|
|
7452
|
-
}
|
|
7453
|
-
}
|
|
7454
|
-
sectionCursor += 1;
|
|
7536
|
+
const readings = tokens.flatMap((token, at) => {
|
|
7537
|
+
if (token.depth !== 1 || token.value === void 0) return [];
|
|
7538
|
+
if (manifest.charAt(token.value) !== "{") return [];
|
|
7539
|
+
const key = parseJSON(token.text);
|
|
7540
|
+
if (!isString(key) || !sectionNames.has(key)) return [];
|
|
7541
|
+
const close = tokens.slice(at + 1).find((next) => next.text === "}" && next.depth === 1);
|
|
7542
|
+
return close === void 0 ? [] : [{
|
|
7543
|
+
name: key,
|
|
7544
|
+
start: token.value,
|
|
7545
|
+
end: close.index + 1
|
|
7546
|
+
}];
|
|
7547
|
+
}).map((bounds) => {
|
|
7548
|
+
const replacements = new Map((bounds.name === "dependencies" ? pins.runtime : pins.development).map(({ name, range }) => [name, range]));
|
|
7549
|
+
return {
|
|
7550
|
+
name: bounds.name,
|
|
7551
|
+
log: tokens.reduce((log, token, at) => {
|
|
7552
|
+
if (log === void 0) return void 0;
|
|
7553
|
+
if (token.index < bounds.start || token.index >= bounds.end) return log;
|
|
7554
|
+
if (log.at(-1)?.edit.start === token.index) return log;
|
|
7555
|
+
if (token.depth !== 2 || token.value === void 0) return log;
|
|
7556
|
+
const key = parseJSON(token.text);
|
|
7557
|
+
if (!isString(key) || manifest.charAt(token.value) !== "\"") return log;
|
|
7558
|
+
const replacement = replacements.get(key);
|
|
7559
|
+
if (replacement === void 0) return log;
|
|
7560
|
+
const literal = tokens[at + 1];
|
|
7561
|
+
if (literal === void 0) return void 0;
|
|
7562
|
+
return [...log, {
|
|
7563
|
+
name: key,
|
|
7564
|
+
edit: {
|
|
7565
|
+
start: literal.index,
|
|
7566
|
+
end: literal.index + literal.text.length,
|
|
7567
|
+
text: JSON.stringify(replacement)
|
|
7455
7568
|
}
|
|
7456
|
-
}
|
|
7457
|
-
}
|
|
7458
|
-
}
|
|
7459
|
-
|
|
7460
|
-
}
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
let section = compiled.slice(bounds.start, bounds.end);
|
|
7469
|
-
let sectionDepth = 0;
|
|
7470
|
-
let sectionCursor = 0;
|
|
7471
|
-
while (sectionCursor < section.length) {
|
|
7472
|
-
const character = section.charAt(sectionCursor);
|
|
7473
|
-
if (character === "{") {
|
|
7474
|
-
sectionDepth += 1;
|
|
7475
|
-
sectionCursor += 1;
|
|
7476
|
-
continue;
|
|
7477
|
-
}
|
|
7478
|
-
if (character === "}") {
|
|
7479
|
-
sectionDepth -= 1;
|
|
7480
|
-
sectionCursor += 1;
|
|
7481
|
-
continue;
|
|
7482
|
-
}
|
|
7483
|
-
if (character !== "\"") {
|
|
7484
|
-
sectionCursor += 1;
|
|
7485
|
-
continue;
|
|
7486
|
-
}
|
|
7487
|
-
const keyStart = sectionCursor;
|
|
7488
|
-
sectionCursor += 1;
|
|
7489
|
-
while (sectionCursor < section.length) {
|
|
7490
|
-
if (section.charAt(sectionCursor) === "\\") {
|
|
7491
|
-
sectionCursor += 2;
|
|
7492
|
-
continue;
|
|
7493
|
-
}
|
|
7494
|
-
if (section.charAt(sectionCursor) === "\"") break;
|
|
7495
|
-
sectionCursor += 1;
|
|
7496
|
-
}
|
|
7497
|
-
if (sectionCursor >= section.length) return void 0;
|
|
7498
|
-
const keyEnd = sectionCursor + 1;
|
|
7499
|
-
const key = parseJSON(section.slice(keyStart, keyEnd));
|
|
7500
|
-
let valueStart = keyEnd;
|
|
7501
|
-
while (valueStart < section.length && /\s/u.test(section.charAt(valueStart))) valueStart += 1;
|
|
7502
|
-
if (sectionDepth !== 1 || section.charAt(valueStart) !== ":") {
|
|
7503
|
-
sectionCursor = keyEnd;
|
|
7504
|
-
continue;
|
|
7505
|
-
}
|
|
7506
|
-
valueStart += 1;
|
|
7507
|
-
while (valueStart < section.length && /\s/u.test(section.charAt(valueStart))) valueStart += 1;
|
|
7508
|
-
if (!isString(key) || section.charAt(valueStart) !== "\"") {
|
|
7509
|
-
sectionCursor = keyEnd;
|
|
7510
|
-
continue;
|
|
7511
|
-
}
|
|
7512
|
-
const replacement = replacements.get(key);
|
|
7513
|
-
if (replacement === void 0) {
|
|
7514
|
-
sectionCursor = keyEnd;
|
|
7515
|
-
continue;
|
|
7516
|
-
}
|
|
7517
|
-
let valueEnd = valueStart + 1;
|
|
7518
|
-
while (valueEnd < section.length) {
|
|
7519
|
-
if (section.charAt(valueEnd) === "\\") {
|
|
7520
|
-
valueEnd += 2;
|
|
7521
|
-
continue;
|
|
7522
|
-
}
|
|
7523
|
-
if (section.charAt(valueEnd) === "\"") break;
|
|
7524
|
-
valueEnd += 1;
|
|
7525
|
-
}
|
|
7526
|
-
if (valueEnd >= section.length) return void 0;
|
|
7527
|
-
const range = JSON.stringify(replacement);
|
|
7528
|
-
section = section.slice(0, valueStart) + range + section.slice(valueEnd + 1);
|
|
7529
|
-
declared.add(key);
|
|
7530
|
-
sectionCursor = valueStart + range.length;
|
|
7531
|
-
}
|
|
7532
|
-
compiled = compiled.slice(0, bounds.start) + section + compiled.slice(bounds.end);
|
|
7533
|
-
}
|
|
7534
|
-
const declaredRuntime = pins.runtime.every(({ name }) => runtime.has(name));
|
|
7535
|
-
const declaredDevelopment = pins.development.every(({ name }) => development.has(name));
|
|
7569
|
+
}];
|
|
7570
|
+
}, [])
|
|
7571
|
+
};
|
|
7572
|
+
});
|
|
7573
|
+
const settled = readings.flatMap(({ name, log }) => log === void 0 ? [] : [{
|
|
7574
|
+
name,
|
|
7575
|
+
log
|
|
7576
|
+
}]);
|
|
7577
|
+
if (settled.length < readings.length) return void 0;
|
|
7578
|
+
const compiled = settled.flatMap(({ log }) => log.map(({ edit }) => edit)).sort((left, right) => right.start - left.start).reduce((text, edit) => text.slice(0, edit.start) + edit.text + text.slice(edit.end), manifest);
|
|
7579
|
+
const declaredRuntime = pins.runtime.every(({ name }) => settled.some((section) => section.name === "dependencies" && section.log.some((entry) => entry.name === name)));
|
|
7580
|
+
const declaredDevelopment = pins.development.every(({ name }) => settled.some((section) => section.name === "devDependencies" && section.log.some((entry) => entry.name === name)));
|
|
7536
7581
|
return declaredRuntime && declaredDevelopment ? compiled : void 0;
|
|
7537
7582
|
}
|
|
7538
7583
|
/**
|
|
@@ -7573,14 +7618,12 @@ function insertManifestDependencies(manifest, additions) {
|
|
|
7573
7618
|
if (requested.length === 0) return manifest;
|
|
7574
7619
|
const parsed = parseJSON(manifest);
|
|
7575
7620
|
if (!isRecord(parsed)) return void 0;
|
|
7576
|
-
const declared =
|
|
7577
|
-
for (const section of ["dependencies", "devDependencies"]) {
|
|
7621
|
+
const declared = new Set(["dependencies", "devDependencies"].flatMap((section) => {
|
|
7578
7622
|
const entries = parsed[section];
|
|
7579
|
-
|
|
7580
|
-
}
|
|
7623
|
+
return isRecord(entries) ? Object.keys(entries) : [];
|
|
7624
|
+
}));
|
|
7581
7625
|
const names = new Set(requested.map(({ name }) => name));
|
|
7582
7626
|
if (names.size !== requested.length || [...names].some((name) => declared.has(name))) return;
|
|
7583
|
-
let compiled = manifest;
|
|
7584
7627
|
const sections = [{
|
|
7585
7628
|
name: "dependencies",
|
|
7586
7629
|
dependencies: additions.runtime
|
|
@@ -7588,131 +7631,113 @@ function insertManifestDependencies(manifest, additions) {
|
|
|
7588
7631
|
name: "devDependencies",
|
|
7589
7632
|
dependencies: additions.development
|
|
7590
7633
|
}];
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
}
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
const
|
|
7691
|
-
const
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
const separator = opening < 0 ? "" : `\n${level}${level}`;
|
|
7699
|
-
const ending = opening < 0 ? "" : `\n${level}`;
|
|
7700
|
-
compiled = `${compiled.slice(0, open + 1)}${lines.map((line) => `${separator}${line}`).join(",")}${ending}${compiled.slice(close)}`;
|
|
7701
|
-
continue;
|
|
7702
|
-
}
|
|
7703
|
-
const newline = compiled.lastIndexOf("\n", first.start);
|
|
7704
|
-
const indent = newline < 0 ? "" : compiled.slice(newline + 1, first.start);
|
|
7705
|
-
const separator = newline < 0 || /\S/u.test(indent) ? "" : `\n${indent}`;
|
|
7706
|
-
for (const [index, dependency] of ordered.entries()) {
|
|
7707
|
-
const line = lines[index] ?? "";
|
|
7708
|
-
const anchor = declarations.find((declaration) => compareValues(declaration.name, dependency.name) > 0);
|
|
7709
|
-
const position = anchor?.start ?? last.end;
|
|
7710
|
-
const text = anchor === void 0 ? `,${separator}${line}` : `${line},${separator}`;
|
|
7711
|
-
edits.set(position, `${edits.get(position) ?? ""}${text}`);
|
|
7712
|
-
}
|
|
7713
|
-
for (const [position, text] of [...edits].sort(([left], [right]) => right - left)) compiled = compiled.slice(0, position) + text + compiled.slice(position);
|
|
7714
|
-
}
|
|
7715
|
-
return compiled;
|
|
7634
|
+
if (sections.some(({ name, dependencies }) => {
|
|
7635
|
+
const entries = parsed[name];
|
|
7636
|
+
return dependencies.length > 0 && entries !== void 0 && (!isRecord(entries) || !Object.values(entries).every(isString));
|
|
7637
|
+
})) return void 0;
|
|
7638
|
+
return sections.reduce((compiled, section) => compiled === void 0 || section.dependencies.length === 0 ? compiled : insertManifestSection(compiled, section.name, section.dependencies, parsed[section.name] !== void 0), manifest);
|
|
7639
|
+
}
|
|
7640
|
+
/**
|
|
7641
|
+
* Inserts dependencies into one section of package manifest text.
|
|
7642
|
+
*
|
|
7643
|
+
* @param manifest - The manifest text to compile, already known to be a JSON object.
|
|
7644
|
+
* @param section - The section the additions enter: `dependencies` or `devDependencies`.
|
|
7645
|
+
* @param dependencies - The names and ranges to declare; the section declares none of them.
|
|
7646
|
+
* @param present - If `true`, the manifest declares the section as an object; if `false`, it declares none.
|
|
7647
|
+
* @returns The manifest declaring every addition in the section, or `undefined` when the section
|
|
7648
|
+
* cannot be located as an object the text declares.
|
|
7649
|
+
*
|
|
7650
|
+
* @remarks
|
|
7651
|
+
* The one step {@link insertManifestDependencies} repeats per section. Each addition lands before
|
|
7652
|
+
* the first declared key that sorts after it, or after the last declared key when none does, and
|
|
7653
|
+
* copies the indentation of the section's first entry. An empty section takes its entries one
|
|
7654
|
+
* level inside the indentation of its opening line, and an absent section is created as one
|
|
7655
|
+
* top-level key beside its sibling, or last in the manifest object when the sibling is absent too.
|
|
7656
|
+
*
|
|
7657
|
+
* @example
|
|
7658
|
+
* ```ts
|
|
7659
|
+
* import { insertManifestSection } from '@orkestrel/scaffold'
|
|
7660
|
+
*
|
|
7661
|
+
* insertManifestSection('{"dependencies":{}}', 'dependencies', [{ name: 'vite', range: '^8' }], true)
|
|
7662
|
+
* // '{"dependencies":{"vite": "^8"}}'
|
|
7663
|
+
* ```
|
|
7664
|
+
*/
|
|
7665
|
+
function insertManifestSection(manifest, section, dependencies, present) {
|
|
7666
|
+
const tokens = scanManifestTokens(manifest);
|
|
7667
|
+
if (tokens === void 0) return void 0;
|
|
7668
|
+
const ordered = [...dependencies].sort((left, right) => compareValues(left.name, right.name));
|
|
7669
|
+
const lines = ordered.map(({ name, range }) => `${JSON.stringify(name)}: ${JSON.stringify(range)}`);
|
|
7670
|
+
const sibling = section === "dependencies" ? "devDependencies" : "dependencies";
|
|
7671
|
+
const occurrences = tokens.flatMap((token, at) => {
|
|
7672
|
+
if (token.depth !== 1 || token.value === void 0) return [];
|
|
7673
|
+
const key = parseJSON(token.text);
|
|
7674
|
+
if (!isString(key) || key !== section && key !== sibling) return [];
|
|
7675
|
+
const object = manifest.charAt(token.value) === "{";
|
|
7676
|
+
const close = object ? tokens.slice(at + 1).find((next) => next.text === "}" && next.depth === 1) : void 0;
|
|
7677
|
+
return [{
|
|
7678
|
+
key,
|
|
7679
|
+
start: token.index,
|
|
7680
|
+
open: token.value,
|
|
7681
|
+
object,
|
|
7682
|
+
close: close?.index
|
|
7683
|
+
}];
|
|
7684
|
+
});
|
|
7685
|
+
const decisive = occurrences.find(({ key, object, close }) => key === section && (!object || close !== void 0));
|
|
7686
|
+
if (decisive !== void 0 && !decisive.object) return void 0;
|
|
7687
|
+
const closed = occurrences.flatMap(({ key, start, open, close }) => close === void 0 ? [] : [{
|
|
7688
|
+
key,
|
|
7689
|
+
start,
|
|
7690
|
+
open,
|
|
7691
|
+
close
|
|
7692
|
+
}]);
|
|
7693
|
+
const bounds = closed.find(({ key }) => key === section);
|
|
7694
|
+
const neighbor = closed.find(({ key }) => key === sibling);
|
|
7695
|
+
const head = tokens.find((token) => token.depth === 1 && token.value !== void 0)?.index;
|
|
7696
|
+
const root = tokens.find((token) => token.text === "}" && token.depth === 0)?.index;
|
|
7697
|
+
if (bounds === void 0) {
|
|
7698
|
+
if (present || root === void 0) return void 0;
|
|
7699
|
+
const breaking = head === void 0 ? -1 : manifest.lastIndexOf("\n", head);
|
|
7700
|
+
const margin = breaking < 0 ? "" : manifest.slice(breaking + 1, head);
|
|
7701
|
+
const gap = breaking < 0 || /\S/u.test(margin) ? "" : `\n${margin}`;
|
|
7702
|
+
const block = `${JSON.stringify(section)}: {${lines.map((line) => `${gap === "" ? "" : `${gap}${margin}`}${line}`).join(",")}${gap}}`;
|
|
7703
|
+
const tail = manifest.slice(1, root).trimEnd().length;
|
|
7704
|
+
const [position, insertion] = neighbor === void 0 ? [tail + 1, manifest.charAt(tail) === "{" ? block : `,${gap}${block}`] : section === "devDependencies" ? [neighbor.close + 1, `,${gap}${block}`] : [neighbor.start, `${block},${gap}`];
|
|
7705
|
+
return manifest.slice(0, position) + insertion + manifest.slice(position);
|
|
7706
|
+
}
|
|
7707
|
+
const { open, close } = bounds;
|
|
7708
|
+
const literals = tokens.filter((token) => token.index > open && token.index < close && token.text.startsWith("\""));
|
|
7709
|
+
const keys = literals.filter((_, index) => index % 2 === 0);
|
|
7710
|
+
if (keys.some((literal) => !isString(parseJSON(literal.text)))) return void 0;
|
|
7711
|
+
const declarations = keys.flatMap((literal, position) => {
|
|
7712
|
+
const name = parseJSON(literal.text);
|
|
7713
|
+
const value = literals[position * 2 + 1];
|
|
7714
|
+
return isString(name) && value !== void 0 ? [{
|
|
7715
|
+
name,
|
|
7716
|
+
start: literal.index,
|
|
7717
|
+
end: value.index + value.text.length
|
|
7718
|
+
}] : [];
|
|
7719
|
+
});
|
|
7720
|
+
const first = declarations[0];
|
|
7721
|
+
const last = declarations.at(-1);
|
|
7722
|
+
if (first === void 0 || last === void 0) {
|
|
7723
|
+
const opening = manifest.lastIndexOf("\n", open);
|
|
7724
|
+
const level = opening < 0 ? "" : /^\s*/u.exec(manifest.slice(opening + 1, open))?.[0] ?? "";
|
|
7725
|
+
const separator = opening < 0 ? "" : `\n${level}${level}`;
|
|
7726
|
+
const ending = opening < 0 ? "" : `\n${level}`;
|
|
7727
|
+
return `${manifest.slice(0, open + 1)}${lines.map((line) => `${separator}${line}`).join(",")}${ending}${manifest.slice(close)}`;
|
|
7728
|
+
}
|
|
7729
|
+
const newline = manifest.lastIndexOf("\n", first.start);
|
|
7730
|
+
const indent = newline < 0 ? "" : manifest.slice(newline + 1, first.start);
|
|
7731
|
+
const separator = newline < 0 || /\S/u.test(indent) ? "" : `\n${indent}`;
|
|
7732
|
+
const placements = ordered.map((dependency, index) => {
|
|
7733
|
+
const line = lines[index] ?? "";
|
|
7734
|
+
const anchor = declarations.find((declaration) => compareValues(declaration.name, dependency.name) > 0);
|
|
7735
|
+
return {
|
|
7736
|
+
position: anchor?.start ?? last.end,
|
|
7737
|
+
text: anchor === void 0 ? `,${separator}${line}` : `${line},${separator}`
|
|
7738
|
+
};
|
|
7739
|
+
});
|
|
7740
|
+
return [...Map.groupBy(placements, ({ position }) => position)].map(([position, group]) => [position, group.map(({ text }) => text).join("")]).sort(([left], [right]) => right - left).reduce((text, [position, insertion]) => text.slice(0, position) + insertion + text.slice(position), manifest);
|
|
7716
7741
|
}
|
|
7717
7742
|
/**
|
|
7718
7743
|
* Replaces named script values in package manifest text.
|
|
@@ -7756,191 +7781,86 @@ function replaceManifestScripts(manifest, scripts) {
|
|
|
7756
7781
|
const parsed = parseJSON(manifest);
|
|
7757
7782
|
if (!isRecord(parsed) || !isRecord(parsed.scripts)) return void 0;
|
|
7758
7783
|
const declared = parsed.scripts;
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
if (
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
const inner = manifest.charAt(scan);
|
|
7810
|
-
if (inner === "\"") {
|
|
7811
|
-
scan += 1;
|
|
7812
|
-
while (scan < manifest.length) {
|
|
7813
|
-
if (manifest.charAt(scan) === "\\") {
|
|
7814
|
-
scan += 2;
|
|
7815
|
-
continue;
|
|
7816
|
-
}
|
|
7817
|
-
if (manifest.charAt(scan) === "\"") break;
|
|
7818
|
-
scan += 1;
|
|
7819
|
-
}
|
|
7820
|
-
if (scan >= manifest.length) return void 0;
|
|
7821
|
-
} else if (inner === "{") nested += 1;
|
|
7822
|
-
else if (inner === "}") {
|
|
7823
|
-
nested -= 1;
|
|
7824
|
-
if (nested === 0) {
|
|
7825
|
-
end = scan + 1;
|
|
7826
|
-
break;
|
|
7827
|
-
}
|
|
7828
|
-
}
|
|
7829
|
-
scan += 1;
|
|
7830
|
-
}
|
|
7831
|
-
}
|
|
7832
|
-
if (start < 0 || end < 0) return void 0;
|
|
7833
|
-
const edits = [];
|
|
7834
|
-
const written = /* @__PURE__ */ new Set();
|
|
7835
|
-
const anchors = [];
|
|
7836
|
-
let first = -1;
|
|
7837
|
-
let nested = 0;
|
|
7838
|
-
let scan = start;
|
|
7839
|
-
while (scan < end) {
|
|
7840
|
-
const character = manifest.charAt(scan);
|
|
7841
|
-
if (character === "{") {
|
|
7842
|
-
nested += 1;
|
|
7843
|
-
scan += 1;
|
|
7844
|
-
continue;
|
|
7845
|
-
}
|
|
7846
|
-
if (character === "}") {
|
|
7847
|
-
nested -= 1;
|
|
7848
|
-
scan += 1;
|
|
7849
|
-
continue;
|
|
7850
|
-
}
|
|
7851
|
-
if (character !== "\"") {
|
|
7852
|
-
scan += 1;
|
|
7853
|
-
continue;
|
|
7854
|
-
}
|
|
7855
|
-
const keyStart = scan;
|
|
7856
|
-
scan += 1;
|
|
7857
|
-
while (scan < end) {
|
|
7858
|
-
if (manifest.charAt(scan) === "\\") {
|
|
7859
|
-
scan += 2;
|
|
7860
|
-
continue;
|
|
7861
|
-
}
|
|
7862
|
-
if (manifest.charAt(scan) === "\"") break;
|
|
7863
|
-
scan += 1;
|
|
7864
|
-
}
|
|
7865
|
-
if (scan >= end) return void 0;
|
|
7866
|
-
const keyEnd = scan + 1;
|
|
7867
|
-
scan = keyEnd;
|
|
7868
|
-
if (nested !== 1) continue;
|
|
7869
|
-
let valueStart = keyEnd;
|
|
7870
|
-
while (valueStart < end && /\s/u.test(manifest.charAt(valueStart))) valueStart += 1;
|
|
7871
|
-
if (manifest.charAt(valueStart) !== ":") continue;
|
|
7872
|
-
valueStart += 1;
|
|
7873
|
-
while (valueStart < end && /\s/u.test(manifest.charAt(valueStart))) valueStart += 1;
|
|
7874
|
-
if (first < 0) first = keyStart;
|
|
7875
|
-
if (manifest.charAt(valueStart) !== "\"") continue;
|
|
7876
|
-
let valueEnd = valueStart + 1;
|
|
7877
|
-
while (valueEnd < end) {
|
|
7878
|
-
if (manifest.charAt(valueEnd) === "\\") {
|
|
7879
|
-
valueEnd += 2;
|
|
7880
|
-
continue;
|
|
7881
|
-
}
|
|
7882
|
-
if (manifest.charAt(valueEnd) === "\"") break;
|
|
7883
|
-
valueEnd += 1;
|
|
7884
|
-
}
|
|
7885
|
-
if (valueEnd >= end) return void 0;
|
|
7886
|
-
scan = valueEnd + 1;
|
|
7887
|
-
const key = parseJSON(manifest.slice(keyStart, keyEnd));
|
|
7888
|
-
if (isString(key)) anchors.push({
|
|
7889
|
-
name: key,
|
|
7890
|
-
end: valueEnd + 1
|
|
7891
|
-
});
|
|
7892
|
-
const script = scripts.find((entry) => entry.name === key);
|
|
7893
|
-
if (script === void 0) continue;
|
|
7894
|
-
written.add(script.name);
|
|
7895
|
-
const value = declared[script.name];
|
|
7896
|
-
if (value === script.command || !isString(value) || !script.accepted.includes(value)) continue;
|
|
7897
|
-
edits.push({
|
|
7898
|
-
start: valueStart,
|
|
7899
|
-
end: valueEnd + 1,
|
|
7784
|
+
if (Iterator.from(scripts).some((script) => Object.hasOwn(declared, script.name) && !isString(declared[script.name]))) return;
|
|
7785
|
+
const tokens = scanManifestTokens(manifest);
|
|
7786
|
+
if (tokens === void 0) return void 0;
|
|
7787
|
+
const position = tokens.findIndex((token, at) => token.depth === 1 && token.value !== void 0 && parseJSON(token.text) === "scripts" && manifest.charAt(token.value) === "{" && tokens.slice(at + 1).some((next) => next.text === "}" && next.depth === 1));
|
|
7788
|
+
const region = tokens[position];
|
|
7789
|
+
const close = tokens.slice(position + 1).find((token) => token.text === "}" && token.depth === 1);
|
|
7790
|
+
if (region?.value === void 0 || close === void 0) return void 0;
|
|
7791
|
+
const start = region.value;
|
|
7792
|
+
const end = close.index + 1;
|
|
7793
|
+
const entries = tokens.reduce((log, token, at) => {
|
|
7794
|
+
if (log === void 0) return void 0;
|
|
7795
|
+
if (token.index < start || token.index >= end) return log;
|
|
7796
|
+
if (token.depth !== 2 || token.value === void 0) return log;
|
|
7797
|
+
if (manifest.charAt(token.value) !== "\"") return [...log, {
|
|
7798
|
+
token,
|
|
7799
|
+
value: token.value,
|
|
7800
|
+
literal: void 0
|
|
7801
|
+
}];
|
|
7802
|
+
const literal = tokens[at + 1];
|
|
7803
|
+
return literal === void 0 ? void 0 : [...log, {
|
|
7804
|
+
token,
|
|
7805
|
+
value: token.value,
|
|
7806
|
+
literal
|
|
7807
|
+
}];
|
|
7808
|
+
}, []);
|
|
7809
|
+
if (entries === void 0) return void 0;
|
|
7810
|
+
const first = entries[0]?.token.index;
|
|
7811
|
+
const keyed = entries.flatMap(({ token, value, literal }) => literal === void 0 ? [] : [{
|
|
7812
|
+
key: parseJSON(token.text),
|
|
7813
|
+
value,
|
|
7814
|
+
stop: literal.index + literal.text.length
|
|
7815
|
+
}]);
|
|
7816
|
+
const anchors = keyed.flatMap(({ key, stop }) => isString(key) ? [{
|
|
7817
|
+
name: key,
|
|
7818
|
+
end: stop
|
|
7819
|
+
}] : []);
|
|
7820
|
+
const matched = keyed.flatMap((entry) => {
|
|
7821
|
+
const script = scripts.find((candidate) => candidate.name === entry.key);
|
|
7822
|
+
return script === void 0 ? [] : [{
|
|
7823
|
+
script,
|
|
7824
|
+
value: entry.value,
|
|
7825
|
+
stop: entry.stop
|
|
7826
|
+
}];
|
|
7827
|
+
});
|
|
7828
|
+
const written = new Set(matched.map(({ script }) => script.name));
|
|
7829
|
+
const replaced = matched.flatMap(({ script, value, stop }) => {
|
|
7830
|
+
const current = declared[script.name];
|
|
7831
|
+
return current === script.command || !isString(current) || !script.accepted.includes(current) ? [] : [{
|
|
7832
|
+
start: value,
|
|
7833
|
+
end: stop,
|
|
7900
7834
|
text: JSON.stringify(script.command)
|
|
7901
|
-
}
|
|
7902
|
-
}
|
|
7835
|
+
}];
|
|
7836
|
+
});
|
|
7903
7837
|
const missing = scripts.filter((script) => !written.has(script.name));
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
})
|
|
7918
|
-
}
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
const queued = placed.get(anchor);
|
|
7931
|
-
if (queued === void 0) placed.set(anchor, [text]);
|
|
7932
|
-
else queued.push(text);
|
|
7933
|
-
}
|
|
7934
|
-
for (const [anchor, queued] of placed) edits.push({
|
|
7935
|
-
start: anchor,
|
|
7936
|
-
end: anchor,
|
|
7937
|
-
text: queued.join("")
|
|
7938
|
-
});
|
|
7939
|
-
}
|
|
7940
|
-
}
|
|
7941
|
-
let compiled = manifest;
|
|
7942
|
-
for (const edit of edits.sort((left, right) => right.start - left.start)) compiled = compiled.slice(0, edit.start) + edit.text + compiled.slice(edit.end);
|
|
7943
|
-
return compiled;
|
|
7838
|
+
const opening = manifest.lastIndexOf("\n", start);
|
|
7839
|
+
const level = opening < 0 ? "" : /^\s*/u.exec(manifest.slice(opening + 1, start))?.[0] ?? "";
|
|
7840
|
+
const emptySeparator = opening < 0 ? "" : `\n${level}${level}`;
|
|
7841
|
+
const emptyClosing = opening < 0 ? "" : `\n${level}`;
|
|
7842
|
+
const tail = start + manifest.slice(start, end - 1).trimEnd().length;
|
|
7843
|
+
const newline = first === void 0 ? -1 : manifest.lastIndexOf("\n", first);
|
|
7844
|
+
const indent = first === void 0 || newline < 0 ? "" : manifest.slice(newline + 1, first);
|
|
7845
|
+
const separator = newline < 0 || /\S/u.test(indent) ? "" : `\n${indent}`;
|
|
7846
|
+
const placements = missing.map((script) => {
|
|
7847
|
+
const colon = script.name.indexOf(":");
|
|
7848
|
+
const family = colon < 0 ? void 0 : script.name.slice(0, colon + 1);
|
|
7849
|
+
return {
|
|
7850
|
+
anchor: (family === void 0 ? void 0 : anchors.findLast((entry) => entry.name.startsWith(family)))?.end ?? tail,
|
|
7851
|
+
text: `,${separator}${JSON.stringify(script.name)}: ${JSON.stringify(script.command)}`
|
|
7852
|
+
};
|
|
7853
|
+
});
|
|
7854
|
+
const appended = missing.length === 0 ? [] : first === void 0 ? [{
|
|
7855
|
+
start: start + 1,
|
|
7856
|
+
end: end - 1,
|
|
7857
|
+
text: `${missing.map((script) => `${emptySeparator}${JSON.stringify(script.name)}: ${JSON.stringify(script.command)}`).join(",")}${emptyClosing}`
|
|
7858
|
+
}] : [...Map.groupBy(placements, ({ anchor }) => anchor)].map(([anchor, group]) => ({
|
|
7859
|
+
start: anchor,
|
|
7860
|
+
end: anchor,
|
|
7861
|
+
text: group.map(({ text }) => text).join("")
|
|
7862
|
+
}));
|
|
7863
|
+
return [...replaced, ...appended].sort((left, right) => right.start - left.start).reduce((text, edit) => text.slice(0, edit.start) + edit.text + text.slice(edit.end), manifest);
|
|
7944
7864
|
}
|
|
7945
7865
|
/**
|
|
7946
7866
|
* Replaces dependency ranges in a plan's manifest and recomputes its identity.
|
|
@@ -7964,22 +7884,28 @@ function replaceManifestScripts(manifest, scripts) {
|
|
|
7964
7884
|
* ```
|
|
7965
7885
|
*/
|
|
7966
7886
|
function replacePlanRanges(plan, pins) {
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7887
|
+
const outcomes = plan.artifacts.map((artifact) => {
|
|
7888
|
+
if (artifact.path !== "package.json" || artifact.origin === "host") return {
|
|
7889
|
+
artifact,
|
|
7890
|
+
manifest: false,
|
|
7891
|
+
refused: false
|
|
7892
|
+
};
|
|
7971
7893
|
const content = replaceManifestRanges(artifact.content, pins);
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7894
|
+
return content === void 0 ? {
|
|
7895
|
+
artifact,
|
|
7896
|
+
manifest: true,
|
|
7897
|
+
refused: true
|
|
7898
|
+
} : {
|
|
7899
|
+
artifact: {
|
|
7900
|
+
...artifact,
|
|
7901
|
+
content
|
|
7902
|
+
},
|
|
7903
|
+
manifest: true,
|
|
7904
|
+
refused: false
|
|
7980
7905
|
};
|
|
7981
7906
|
});
|
|
7982
|
-
if (!
|
|
7907
|
+
if (!outcomes.some((outcome) => outcome.manifest) || outcomes.some((outcome) => outcome.refused)) return;
|
|
7908
|
+
const artifacts = outcomes.map((outcome) => outcome.artifact);
|
|
7983
7909
|
const compiled = {
|
|
7984
7910
|
...plan,
|
|
7985
7911
|
artifacts
|
|
@@ -8054,24 +7980,21 @@ function planToHash(plan) {
|
|
|
8054
7980
|
* ```
|
|
8055
7981
|
*/
|
|
8056
7982
|
function planToFindings(plan, current) {
|
|
8057
|
-
const
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
}
|
|
8063
|
-
|
|
8064
|
-
if (planned.has(path)) continue;
|
|
7983
|
+
const listed = Iterator.from(plan.artifacts).map((artifact) => ({
|
|
7984
|
+
path: artifact.path,
|
|
7985
|
+
finding: artifactToFinding(artifact, current[artifact.path])
|
|
7986
|
+
})).toArray();
|
|
7987
|
+
const planned = new Set(listed.map(({ path }) => path));
|
|
7988
|
+
return [...listed.map(({ finding }) => finding), ...Object.entries(current).flatMap(([path, observed]) => {
|
|
7989
|
+
if (planned.has(path)) return [];
|
|
8065
7990
|
const group = inferGroup(path);
|
|
8066
|
-
|
|
8067
|
-
findings.push({
|
|
7991
|
+
return plan.groups.includes(group) ? [{
|
|
8068
7992
|
path,
|
|
8069
7993
|
group,
|
|
8070
7994
|
drift: "foreign",
|
|
8071
7995
|
observed
|
|
8072
|
-
}
|
|
8073
|
-
}
|
|
8074
|
-
return findings;
|
|
7996
|
+
}] : [];
|
|
7997
|
+
})];
|
|
8075
7998
|
}
|
|
8076
7999
|
/**
|
|
8077
8000
|
* Measures one declared package list against the name and range syntax it accepts.
|
|
@@ -8108,27 +8031,30 @@ function planToFindings(plan, current) {
|
|
|
8108
8031
|
* ```
|
|
8109
8032
|
*/
|
|
8110
8033
|
function dependenciesToQuestions(dependencies, field, name, range) {
|
|
8111
|
-
const
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
}
|
|
8131
|
-
|
|
8034
|
+
const listed = Iterator.from(dependencies).map((dependency) => {
|
|
8035
|
+
const declared = dependency.name;
|
|
8036
|
+
const valid = name.test(declared);
|
|
8037
|
+
const pinned = dependency.range;
|
|
8038
|
+
return {
|
|
8039
|
+
declared,
|
|
8040
|
+
valid,
|
|
8041
|
+
pinned,
|
|
8042
|
+
accepted: range.test(pinned)
|
|
8043
|
+
};
|
|
8044
|
+
}).toArray();
|
|
8045
|
+
return listed.flatMap(({ declared, valid, pinned, accepted }, index) => [...!valid ? [{
|
|
8046
|
+
field,
|
|
8047
|
+
message: `${declared} is not a package name ${field} accepts.`,
|
|
8048
|
+
blocking: true
|
|
8049
|
+
}] : listed.findIndex((other) => other.declared === declared) < index ? [{
|
|
8050
|
+
field,
|
|
8051
|
+
message: `${declared} is declared more than once on ${field}.`,
|
|
8052
|
+
blocking: true
|
|
8053
|
+
}] : [], ...!accepted ? [{
|
|
8054
|
+
field,
|
|
8055
|
+
message: `${declared} declares the range ${pinned}, which ${field} does not accept.`,
|
|
8056
|
+
blocking: true
|
|
8057
|
+
}] : []]);
|
|
8132
8058
|
}
|
|
8133
8059
|
/**
|
|
8134
8060
|
* Measures a blueprint against every law its own fields decide.
|
|
@@ -8176,131 +8102,125 @@ function dependenciesToQuestions(dependencies, field, name, range) {
|
|
|
8176
8102
|
* ```
|
|
8177
8103
|
*/
|
|
8178
8104
|
function blueprintToQuestions(blueprint) {
|
|
8179
|
-
const
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8105
|
+
const own = `@orkestrel/${blueprint.name}`;
|
|
8106
|
+
return [
|
|
8107
|
+
...!NAME_PATTERN.test(blueprint.name) ? [{
|
|
8108
|
+
field: "name",
|
|
8109
|
+
message: `${blueprint.name} is not a lowercase alphanumeric name starting with a letter.`,
|
|
8110
|
+
blocking: true
|
|
8111
|
+
}] : [],
|
|
8112
|
+
...!VERSION_PATTERN.test(blueprint.version) ? [{
|
|
8113
|
+
field: "version",
|
|
8114
|
+
message: `${blueprint.version} is not an exact three-component version.`,
|
|
8115
|
+
blocking: true
|
|
8116
|
+
}] : [],
|
|
8117
|
+
...!matchesEngines(blueprint.engines) ? [{
|
|
8118
|
+
field: "engines",
|
|
8119
|
+
message: `${blueprint.engines} is not a supported minimum-Node floor.`,
|
|
8120
|
+
blocking: true
|
|
8121
|
+
}] : [],
|
|
8122
|
+
...blueprint.src.length === 0 && blueprint.app.length === 0 && blueprintToSheets(blueprint).length === 0 && !blueprint.themes ? [{
|
|
8123
|
+
field: "src",
|
|
8124
|
+
message: "A workspace declares at least one environment on src or app.",
|
|
8125
|
+
blocking: true,
|
|
8126
|
+
candidates: ENVIRONMENTS
|
|
8127
|
+
}] : [],
|
|
8128
|
+
...blueprint.src.length > 1 && !blueprint.src.includes("core") ? [{
|
|
8129
|
+
field: "src",
|
|
8130
|
+
message: "Several published environments put core at the package root, so this manifest names a core build the workspace never runs. Declare core on src, or publish one environment.",
|
|
8131
|
+
blocking: false,
|
|
8132
|
+
candidates: ENVIRONMENTS
|
|
8133
|
+
}] : [],
|
|
8134
|
+
...ENVIRONMENTS.flatMap((environment) => [...blueprint.src.filter((declared) => declared === environment).length > 1 ? [{
|
|
8209
8135
|
field: "src",
|
|
8210
8136
|
message: `src declares ${environment} more than once.`,
|
|
8211
8137
|
blocking: true,
|
|
8212
8138
|
candidates: ENVIRONMENTS
|
|
8213
|
-
})
|
|
8214
|
-
if (blueprint.app.filter((declared) => declared === environment).length > 1) questions.push({
|
|
8139
|
+
}] : [], ...blueprint.app.filter((declared) => declared === environment).length > 1 ? [{
|
|
8215
8140
|
field: "app",
|
|
8216
8141
|
message: `app declares ${environment} more than once.`,
|
|
8217
8142
|
blocking: true,
|
|
8218
8143
|
candidates: ENVIRONMENTS
|
|
8219
|
-
})
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8144
|
+
}] : []]),
|
|
8145
|
+
...Iterator.from(blueprint.extensions).map((extension) => {
|
|
8146
|
+
const selection = `${extension.surface}:${extension.name}`;
|
|
8147
|
+
return {
|
|
8148
|
+
selection,
|
|
8149
|
+
questions: extension.surface === "browser" ? [...extension.axes.length === 0 ? [{
|
|
8150
|
+
field: "extensions",
|
|
8151
|
+
message: `${selection} occupies no axis.`,
|
|
8152
|
+
blocking: false
|
|
8153
|
+
}] : [], ...Iterator.from(extension.axes).flatMap((axis) => blueprint[axis].includes("browser") ? [] : [{
|
|
8154
|
+
field: "extensions",
|
|
8155
|
+
message: `${selection} occupies ${axis}, whose selection lacks browser.`,
|
|
8156
|
+
blocking: false
|
|
8157
|
+
}]).toArray()] : !blueprint.styles ? [{
|
|
8158
|
+
field: "extensions",
|
|
8159
|
+
message: `${selection} extends a styles surface this workspace does not declare.`,
|
|
8160
|
+
blocking: false
|
|
8161
|
+
}] : []
|
|
8162
|
+
};
|
|
8163
|
+
}).toArray().flatMap(({ selection, questions }, index, selected) => [...selected.findIndex((other) => other.selection === selection) < index ? [{
|
|
8225
8164
|
field: "extensions",
|
|
8226
8165
|
message: `${selection} is declared more than once on extensions.`,
|
|
8227
8166
|
blocking: true
|
|
8228
|
-
})
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
field: "extensions",
|
|
8233
|
-
message: `${selection} occupies no axis.`,
|
|
8234
|
-
blocking: false
|
|
8235
|
-
});
|
|
8236
|
-
for (const axis of extension.axes) if (!blueprint[axis].includes("browser")) questions.push({
|
|
8237
|
-
field: "extensions",
|
|
8238
|
-
message: `${selection} occupies ${axis}, whose selection lacks browser.`,
|
|
8239
|
-
blocking: false
|
|
8240
|
-
});
|
|
8241
|
-
} else if (!blueprint.styles) questions.push({
|
|
8242
|
-
field: "extensions",
|
|
8243
|
-
message: `${selection} extends a styles surface this workspace does not declare.`,
|
|
8167
|
+
}] : [], ...questions]),
|
|
8168
|
+
...blueprint.integration && blueprint.src.length + blueprint.app.length < 2 ? [{
|
|
8169
|
+
field: "integration",
|
|
8170
|
+
message: "integration drives features across environments, and this workspace declares fewer than two, so its seed composes nothing.",
|
|
8244
8171
|
blocking: false
|
|
8245
|
-
}
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
blocking: false
|
|
8251
|
-
});
|
|
8252
|
-
const vendors = /* @__PURE__ */ new Set();
|
|
8253
|
-
for (const vendor of blueprint.vendors) {
|
|
8254
|
-
if (!NAME_PATTERN.test(vendor)) questions.push({
|
|
8172
|
+
}] : [],
|
|
8173
|
+
...Iterator.from(blueprint.vendors).map((vendor) => ({
|
|
8174
|
+
vendor,
|
|
8175
|
+
valid: NAME_PATTERN.test(vendor)
|
|
8176
|
+
})).toArray().flatMap(({ vendor, valid }, index, declared) => !valid ? [{
|
|
8255
8177
|
field: "vendors",
|
|
8256
8178
|
message: `${vendor} is not a lowercase alphanumeric vendor name starting with a letter.`,
|
|
8257
8179
|
blocking: true
|
|
8258
|
-
})
|
|
8259
|
-
else if (vendors.has(vendor)) questions.push({
|
|
8180
|
+
}] : declared.findIndex((other) => other.vendor === vendor) < index ? [{
|
|
8260
8181
|
field: "vendors",
|
|
8261
8182
|
message: `${vendor} is declared more than once on vendors.`,
|
|
8262
8183
|
blocking: true
|
|
8263
|
-
})
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
[
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
const own = `@orkestrel/${blueprint.name}`;
|
|
8284
|
-
for (const [field, list] of lists) for (const dependency of list) {
|
|
8285
|
-
if (dependency.name === own || dependency.name === blueprint.name) questions.push({
|
|
8286
|
-
field,
|
|
8287
|
-
message: `${dependency.name} is the workspace itself.`,
|
|
8288
|
-
blocking: true
|
|
8289
|
-
});
|
|
8290
|
-
const first = declared.get(dependency.name);
|
|
8291
|
-
if (first === void 0) declared.set(dependency.name, field);
|
|
8292
|
-
else if (first !== field) questions.push({
|
|
8184
|
+
}] : []),
|
|
8185
|
+
...blueprint.showcase && !blueprint.app.includes("browser") ? [{
|
|
8186
|
+
field: "showcase",
|
|
8187
|
+
message: "showcase projects a browser app, and this workspace declares none, so it emits nothing.",
|
|
8188
|
+
blocking: false
|
|
8189
|
+
}] : [],
|
|
8190
|
+
...blueprint.journey && !blueprint.app.includes("browser") ? [{
|
|
8191
|
+
field: "journey",
|
|
8192
|
+
message: "journey projects a browser app, and this workspace declares none, so it emits nothing.",
|
|
8193
|
+
blocking: false
|
|
8194
|
+
}] : [],
|
|
8195
|
+
...dependenciesToQuestions(blueprint.dependencies, "dependencies", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN),
|
|
8196
|
+
...dependenciesToQuestions(blueprint.peers.filter((peer) => peer.name.startsWith("@orkestrel/")), "peers", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN),
|
|
8197
|
+
...dependenciesToQuestions(blueprint.peers.filter((peer) => !peer.name.startsWith("@orkestrel/")), "peers", FOREIGN_NAME_PATTERN, FLOOR_RANGE_PATTERN),
|
|
8198
|
+
...dependenciesToQuestions(blueprint.extras, "extras", FOREIGN_NAME_PATTERN, EXTRA_RANGE_PATTERN),
|
|
8199
|
+
...[
|
|
8200
|
+
["dependencies", blueprint.dependencies],
|
|
8201
|
+
["peers", blueprint.peers],
|
|
8202
|
+
["extras", blueprint.extras]
|
|
8203
|
+
].flatMap(([field, list]) => Iterator.from(list).map((dependency) => ({
|
|
8293
8204
|
field,
|
|
8294
|
-
|
|
8205
|
+
name: dependency.name
|
|
8206
|
+
})).toArray()).flatMap(({ field, name }, _, declared) => {
|
|
8207
|
+
const first = declared.find((other) => other.name === name)?.field;
|
|
8208
|
+
return [...name === own || name === blueprint.name ? [{
|
|
8209
|
+
field,
|
|
8210
|
+
message: `${name} is the workspace itself.`,
|
|
8211
|
+
blocking: true
|
|
8212
|
+
}] : [], ...first !== void 0 && first !== field ? [{
|
|
8213
|
+
field,
|
|
8214
|
+
message: `${name} is declared on both ${first} and ${field}.`,
|
|
8215
|
+
blocking: true
|
|
8216
|
+
}] : []];
|
|
8217
|
+
}),
|
|
8218
|
+
...Iterator.from(blueprint.extras).flatMap((extra) => Object.hasOwn(BASE_DEV_DEPENDENCIES, extra.name) ? [{
|
|
8219
|
+
field: "extras",
|
|
8220
|
+
message: `${extra.name} is pinned by the shared toolchain, which every workspace carries at one version.`,
|
|
8295
8221
|
blocking: true
|
|
8296
|
-
})
|
|
8297
|
-
|
|
8298
|
-
for (const extra of blueprint.extras) if (Object.hasOwn(BASE_DEV_DEPENDENCIES, extra.name)) questions.push({
|
|
8299
|
-
field: "extras",
|
|
8300
|
-
message: `${extra.name} is pinned by the shared toolchain, which every workspace carries at one version.`,
|
|
8301
|
-
blocking: true
|
|
8302
|
-
});
|
|
8303
|
-
return questions;
|
|
8222
|
+
}] : []).toArray()
|
|
8223
|
+
];
|
|
8304
8224
|
}
|
|
8305
8225
|
/**
|
|
8306
8226
|
* Measures a drafted artifact list against the laws a whole plan decides.
|
|
@@ -8329,35 +8249,32 @@ function blueprintToQuestions(blueprint) {
|
|
|
8329
8249
|
* ```
|
|
8330
8250
|
*/
|
|
8331
8251
|
function artifactsToQuestions(artifacts) {
|
|
8332
|
-
const
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8252
|
+
const listed = Iterator.from(artifacts).map((artifact) => ({
|
|
8253
|
+
path: artifact.path,
|
|
8254
|
+
bytes: artifact.origin === "host" ? artifact.hex === void 0 ? 0 : artifact.hex.length / 2 : computeBytes(artifact.content)
|
|
8255
|
+
})).toArray();
|
|
8256
|
+
const total = computeTotal(listed.map(({ bytes }) => bytes));
|
|
8257
|
+
return [
|
|
8258
|
+
...listed.flatMap(({ path, bytes }, index) => [...listed.findIndex((other) => other.path === path) < index ? [{
|
|
8337
8259
|
field: "artifacts",
|
|
8338
|
-
message: `Two artifacts claim ${
|
|
8260
|
+
message: `Two artifacts claim ${path}.`,
|
|
8339
8261
|
blocking: true
|
|
8340
|
-
}
|
|
8341
|
-
claimed.add(artifact.path);
|
|
8342
|
-
const bytes = artifact.origin === "host" ? artifact.hex === void 0 ? 0 : artifact.hex.length / 2 : computeBytes(artifact.content);
|
|
8343
|
-
if (bytes > 5242880) questions.push({
|
|
8262
|
+
}] : [], ...bytes > 5242880 ? [{
|
|
8344
8263
|
field: "artifacts",
|
|
8345
|
-
message: `${
|
|
8264
|
+
message: `${path} carries ${bytes} bytes, above the ${MAX_ARTIFACT_BYTES} one artifact admits.`,
|
|
8346
8265
|
blocking: true
|
|
8347
|
-
})
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
});
|
|
8360
|
-
return questions;
|
|
8266
|
+
}] : []]),
|
|
8267
|
+
...artifacts.length > 1e3 ? [{
|
|
8268
|
+
field: "artifacts",
|
|
8269
|
+
message: `A plan of ${artifacts.length} artifacts is above the ${MAX_COLLECTION_ITEMS} one collection admits.`,
|
|
8270
|
+
blocking: true
|
|
8271
|
+
}] : [],
|
|
8272
|
+
...total > 104857600 ? [{
|
|
8273
|
+
field: "artifacts",
|
|
8274
|
+
message: `A plan of ${total} bytes is above the ${MAX_TOTAL_ARTIFACT_BYTES} one plan retains.`,
|
|
8275
|
+
blocking: true
|
|
8276
|
+
}] : []
|
|
8277
|
+
];
|
|
8361
8278
|
}
|
|
8362
8279
|
/**
|
|
8363
8280
|
* Measures a blueprint's overrides against the artifacts drafted for it.
|
|
@@ -8385,41 +8302,28 @@ function artifactsToQuestions(artifacts) {
|
|
|
8385
8302
|
* ```
|
|
8386
8303
|
*/
|
|
8387
8304
|
function overridesToQuestions(overrides, artifacts) {
|
|
8388
|
-
const
|
|
8389
|
-
const
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
if (seen.has(override.path)) questions.push({
|
|
8305
|
+
const planned = new Map(Iterator.from(artifacts).map((artifact) => [artifact.path, artifact]).toArray().reverse());
|
|
8306
|
+
const listed = Iterator.from(overrides).map((override) => override.path).toArray();
|
|
8307
|
+
return listed.flatMap((path, index) => {
|
|
8308
|
+
const artifact = planned.get(path);
|
|
8309
|
+
return [...listed.indexOf(path) < index ? [{
|
|
8394
8310
|
field: "overrides",
|
|
8395
|
-
message: `${
|
|
8311
|
+
message: `${path} is overridden more than once.`,
|
|
8396
8312
|
blocking: true
|
|
8397
|
-
}
|
|
8398
|
-
seen.add(override.path);
|
|
8399
|
-
const artifact = planned.get(override.path);
|
|
8400
|
-
if (artifact === void 0) {
|
|
8401
|
-
questions.push({
|
|
8402
|
-
field: "overrides",
|
|
8403
|
-
message: `${override.path} is not a path this plan carries.`,
|
|
8404
|
-
blocking: true
|
|
8405
|
-
});
|
|
8406
|
-
continue;
|
|
8407
|
-
}
|
|
8408
|
-
if (artifact.origin === "host") {
|
|
8409
|
-
questions.push({
|
|
8410
|
-
field: "overrides",
|
|
8411
|
-
message: `${override.path} is byte-copied from the vendored data root.`,
|
|
8412
|
-
blocking: true
|
|
8413
|
-
});
|
|
8414
|
-
continue;
|
|
8415
|
-
}
|
|
8416
|
-
if (artifact.group === "manifest") questions.push({
|
|
8313
|
+
}] : [], ...artifact === void 0 ? [{
|
|
8417
8314
|
field: "overrides",
|
|
8418
|
-
message: `${
|
|
8315
|
+
message: `${path} is not a path this plan carries.`,
|
|
8419
8316
|
blocking: true
|
|
8420
|
-
}
|
|
8421
|
-
|
|
8422
|
-
|
|
8317
|
+
}] : artifact.origin === "host" ? [{
|
|
8318
|
+
field: "overrides",
|
|
8319
|
+
message: `${path} is byte-copied from the vendored data root.`,
|
|
8320
|
+
blocking: true
|
|
8321
|
+
}] : artifact.group === "manifest" ? [{
|
|
8322
|
+
field: "overrides",
|
|
8323
|
+
message: `${path} is the manifest, which the blueprint's own fields decide.`,
|
|
8324
|
+
blocking: true
|
|
8325
|
+
}] : []];
|
|
8326
|
+
});
|
|
8423
8327
|
}
|
|
8424
8328
|
//#endregion
|
|
8425
8329
|
//#region src/core/factories.ts
|
|
@@ -8489,6 +8393,7 @@ function createBlueprint(name, input) {
|
|
|
8489
8393
|
conformance: input?.conformance ?? false,
|
|
8490
8394
|
service: input?.service ?? false,
|
|
8491
8395
|
vendors: input?.vendors ?? [],
|
|
8396
|
+
studies: input?.studies ?? false,
|
|
8492
8397
|
global: input?.global ?? false,
|
|
8493
8398
|
showcase: input?.showcase ?? false,
|
|
8494
8399
|
journey: input?.journey ?? false,
|
|
@@ -8675,9 +8580,7 @@ var Compiler = class {
|
|
|
8675
8580
|
#scaffold(blueprint, groups) {
|
|
8676
8581
|
const stages = [];
|
|
8677
8582
|
const draft = this.#draft(blueprint);
|
|
8678
|
-
const
|
|
8679
|
-
for (const group of groups) for (const artifact of draft) if (artifact.group === group) selected.push(artifact);
|
|
8680
|
-
const artifacts = applyOverrides(selected, blueprint.overrides);
|
|
8583
|
+
const artifacts = applyOverrides(groups.flatMap((group) => draft.filter((artifact) => artifact.group === group)), blueprint.overrides);
|
|
8681
8584
|
stages.push({
|
|
8682
8585
|
stage: "draft",
|
|
8683
8586
|
input: {
|
|
@@ -8801,6 +8704,6 @@ var Compiler = class {
|
|
|
8801
8704
|
}
|
|
8802
8705
|
};
|
|
8803
8706
|
//#endregion
|
|
8804
|
-
export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, AXES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, BROWSE_DEV_DEPENDENCIES, BROWSE_UPSTREAM, CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONFIG_TEMPLATES, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_PATTERN, FRAMEWORKS, FRAMEWORK_MATRIX, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_INVENTORY_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, JOURNEY_CONFIG_PATH, MANIFEST_PATH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_SCRIPT_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, MINIMUM_NODE_VERSION, MINIMUM_NPM_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, PRINT_WIDTH, REFERENCE_PATHS, RELEASE_PROOF_COMMAND, RESERVED_SHEET_NAMES, SEED_GUIDE_PATHS, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHEET_ENTRY_NAME, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SHOWCASE_OVERRIDES, SHOWCASE_PAGES_PATH, SKILLS_CONFIG_PATH, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, STYLES_DEV_DEPENDENCIES, STYLES_ENTRY_PATH, SURFACES, ScaffoldError, TAB_WIDTH, TARGET_SKILL_NAMES, THEMES_BARREL_PATH, THEMES_ENTRY_PATH, VERSION_PATTERN, WORKSPACE_DEV_ENGINES, WORKSPACE_OWNED_PATHS, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToExports, blueprintToFaces, blueprintToGuideArtifacts, blueprintToHostArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToManifestOverrides, blueprintToOptimizedDependencies, blueprintToOrchestrationArtifacts, blueprintToProjects, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSheets, blueprintToSourceArtifacts, blueprintToTestArtifacts, blueprintToWritableScripts, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, dependenciesToQuestions, extractRangeMajor, extractVersion, inferDrift, inferGroup, insertManifestDependencies, isArtifact, isAudit, isBlueprint, isBrowserExtension, isCanonPath, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDeferredPath, isDependency, isDependencyName, isEnvironment, isExtension, isFinding, isFloorPath, isGroup, isGroups, isHex, isManifestScript, isMirror, isOverride, isPath, isPlan, isQuestion, isRetainedPath, isScaffoldError, isSheetName, isSnapshot, isStylesExtension, isSurface, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesPrintWidth, matchesRange, nameToGuide, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseExtension, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, renderSkillPointer, replaceManifestOverrides, replaceManifestRanges, replaceManifestScripts, replacePlanRanges, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
|
|
8707
|
+
export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, AXES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, BROWSE_DEV_DEPENDENCIES, BROWSE_UPSTREAM, CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONFIG_TEMPLATES, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_PATTERN, FRAMEWORKS, FRAMEWORK_MATRIX, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_INVENTORY_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, JOURNEY_CONFIG_PATH, MANIFEST_PATH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_SCRIPT_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, MINIMUM_NODE_VERSION, MINIMUM_NPM_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, PRINT_WIDTH, REFERENCE_PATHS, RELEASE_PROOF_COMMAND, RESERVED_SHEET_NAMES, SEED_GUIDE_PATHS, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHEET_ENTRY_NAME, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SHOWCASE_OVERRIDES, SHOWCASE_PAGES_PATH, SKILLS_CONFIG_PATH, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, STUDIES_TEST_INCLUDE, STYLES_DEV_DEPENDENCIES, STYLES_ENTRY_PATH, SURFACES, ScaffoldError, TAB_WIDTH, TARGET_SKILL_NAMES, THEMES_BARREL_PATH, THEMES_ENTRY_PATH, VERSION_PATTERN, WORKSPACE_DEV_ENGINES, WORKSPACE_OWNED_PATHS, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToExports, blueprintToFaces, blueprintToGuideArtifacts, blueprintToHostArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToManifestOverrides, blueprintToOptimizedDependencies, blueprintToOrchestrationArtifacts, blueprintToProjects, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSheets, blueprintToSourceArtifacts, blueprintToTestArtifacts, blueprintToWritableScripts, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeHash, computeTotal, contentToHex, createBlueprint, dependenciesToQuestions, extractRangeMajor, extractVersion, inferDrift, inferGroup, insertManifestDependencies, insertManifestSection, isArtifact, isAudit, isBlueprint, isBrowserExtension, isCanonPath, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDeferredPath, isDependency, isDependencyName, isEnvironment, isExtension, isFinding, isFloorPath, isGroup, isGroups, isHex, isManifestScript, isMirror, isOverride, isPath, isPlan, isQuestion, isRetainedPath, isScaffoldError, isSheetName, isSnapshot, isStylesExtension, isSurface, iterateAnswers, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesPrintWidth, matchesRange, nameToGuide, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseExtension, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, renderSkillPointer, replaceManifestOverride, replaceManifestOverrides, replaceManifestRanges, replaceManifestScripts, replacePlanRanges, scanManifestTokens, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
|
|
8805
8708
|
|
|
8806
8709
|
//# sourceMappingURL=index.js.map
|