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