@orkestrel/scaffold 0.0.25 → 0.0.26
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/README.md +5 -0
- package/dist/bin/main.js +45 -4
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +40 -11
- package/dist/host/claude/agents/orkestrel.md +63 -48
- package/dist/host/claude/rules/documentation.md +1 -1
- package/dist/host/guides/guide.md +211 -100
- package/dist/host/guides/scaffold.md +165 -10
- package/dist/host/manifest.json +5 -5
- package/dist/host/tests/config.test.ts +30 -7
- package/dist/src/core/index.cjs +242 -149
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +185 -98
- package/dist/src/core/index.d.ts +185 -98
- package/dist/src/core/index.js +240 -150
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +171 -66
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +140 -26
- package/dist/src/server/index.d.ts +140 -26
- package/dist/src/server/index.js +173 -69
- package/dist/src/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/src/core/index.js
CHANGED
|
@@ -139,6 +139,25 @@ var HOST_PATHS = Object.freeze([
|
|
|
139
139
|
"guides/scaffold.md"
|
|
140
140
|
]);
|
|
141
141
|
/**
|
|
142
|
+
* The vendored paths a target receives with its executable bit set, frozen.
|
|
143
|
+
*
|
|
144
|
+
* @remarks
|
|
145
|
+
* Declared rather than read from the staging host's filesystem, because that
|
|
146
|
+
* reading is not portable: Windows carries no executable bit, so a host staged
|
|
147
|
+
* there reports every file non-executable and every target receives hooks it
|
|
148
|
+
* cannot run. Declaring the set here makes one checkout stage one manifest on
|
|
149
|
+
* every host.
|
|
150
|
+
*
|
|
151
|
+
* Every entry is also a {@link HOST_PATHS} member or sits beneath one. A file
|
|
152
|
+
* that must run when a target invokes it belongs here the moment it is vendored.
|
|
153
|
+
*/
|
|
154
|
+
var EXECUTABLE_PATHS = Object.freeze([
|
|
155
|
+
"scripts/codex.sh",
|
|
156
|
+
"scripts/cursor.sh",
|
|
157
|
+
"scripts/deps.sh",
|
|
158
|
+
"scripts/ollama.sh"
|
|
159
|
+
]);
|
|
160
|
+
/**
|
|
142
161
|
* The path prefixes whose contents instruct or wire an agent, frozen.
|
|
143
162
|
*
|
|
144
163
|
* @remarks
|
|
@@ -226,7 +245,7 @@ var ENGINES_PATTERN = /^>=(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
|
226
245
|
var HEX_PATTERN = /^(?:[0-9a-f]{2})*$/;
|
|
227
246
|
/** Unicode controls, formatting controls, and line and paragraph separators rejected in text. */
|
|
228
247
|
var CONTROL_CHARACTER_PATTERN = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
|
|
229
|
-
/** Visible characters a
|
|
248
|
+
/** Visible characters a target-relative path and a Markdown path cell both forbid. */
|
|
230
249
|
var INVALID_PATH_CHARACTER_PATTERN = /[<>:"|?*\\]/;
|
|
231
250
|
/**
|
|
232
251
|
* Maximum bare workspace name length.
|
|
@@ -244,6 +263,8 @@ var MAX_RANGE_LENGTH = 2048;
|
|
|
244
263
|
var MAX_PATH_LENGTH = 32767;
|
|
245
264
|
/** Maximum items accepted in one public collection. */
|
|
246
265
|
var MAX_COLLECTION_ITEMS = 1e3;
|
|
266
|
+
/** Maximum findings one audit can produce from a bounded plan and snapshot. */
|
|
267
|
+
var MAX_AUDIT_FINDINGS = MAX_COLLECTION_ITEMS * 2;
|
|
247
268
|
/** Maximum bytes accepted for one artifact. */
|
|
248
269
|
var MAX_ARTIFACT_BYTES = 5242880;
|
|
249
270
|
/** Maximum length of the hexadecimal string carrying one artifact's bytes. */
|
|
@@ -262,7 +283,7 @@ var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
|
|
|
262
283
|
var BASE_DEV_DEPENDENCIES = Object.freeze({
|
|
263
284
|
"@microsoft/api-extractor": "^7.58.12",
|
|
264
285
|
"@orkestrel/guide": "^0.0.9",
|
|
265
|
-
"@orkestrel/scaffold": "^0.0.
|
|
286
|
+
"@orkestrel/scaffold": "^0.0.26",
|
|
266
287
|
"@types/node": "^26.2.0",
|
|
267
288
|
oxfmt: "^0.62.0",
|
|
268
289
|
oxlint: "^1.77.0",
|
|
@@ -355,12 +376,10 @@ var CONFIG_TEMPLATES = Object.freeze({
|
|
|
355
376
|
"exclude": ["node_modules", "dist", "tmp"]
|
|
356
377
|
}
|
|
357
378
|
`,
|
|
358
|
-
vite: `import type {
|
|
359
|
-
{{imports}}
|
|
360
|
-
import { defineConfig, mergeConfig } from 'vitest/config'
|
|
379
|
+
vite: `import type { {{viteTypes}} } from 'vite'
|
|
380
|
+
{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'
|
|
361
381
|
import tsconfig from './tsconfig.json' with { type: 'json' }
|
|
362
|
-
import {
|
|
363
|
-
import { lstatSync, readdirSync, realpathSync } from 'node:fs'
|
|
382
|
+
{{helpers}}import { lstatSync, readdirSync, realpathSync } from 'node:fs'
|
|
364
383
|
import { basename, join, parse, relative, resolve as resolvePath, sep } from 'node:path'
|
|
365
384
|
import { fileURLToPath, URL } from 'node:url'
|
|
366
385
|
|
|
@@ -552,14 +571,9 @@ const resolve = {
|
|
|
552
571
|
`,
|
|
553
572
|
browser: `function applicationBrowser(showcase: boolean): UserConfig {
|
|
554
573
|
const output = showcase ? 'dist/showcase' : 'dist/app/browser'
|
|
555
|
-
return {
|
|
574
|
+
{{showcasePlugins}} return {
|
|
556
575
|
resolve,
|
|
557
|
-
|
|
558
|
-
outputBoundary(output),
|
|
559
|
-
environmentBoundary('app/browser'),
|
|
560
|
-
vue(),
|
|
561
|
-
{{showcasePlugin}} ],
|
|
562
|
-
root: resolveWorkspacePath('app/browser'),
|
|
576
|
+
{{plugins}} root: resolveWorkspacePath('app/browser'),
|
|
563
577
|
publicDir: false,
|
|
564
578
|
build: {
|
|
565
579
|
{{showcaseBuild}} emptyOutDir: true,
|
|
@@ -942,9 +956,13 @@ export default defineConfig(appShowcase())
|
|
|
942
956
|
*
|
|
943
957
|
* @remarks
|
|
944
958
|
* Builders in `compilers.ts` fill every varying span through
|
|
945
|
-
* `@orkestrel/template`. Empty barrels and setup modules are
|
|
946
|
-
* generated workspace starts with no sample domain API, while
|
|
947
|
-
* Vitest project gets a real test that proves its barrel has no
|
|
959
|
+
* `@orkestrel/template`. Empty barrels, entries, and setup modules are
|
|
960
|
+
* intentional: the generated workspace starts with no sample domain API, while
|
|
961
|
+
* each selected Vitest project gets a real test that proves its barrel has no
|
|
962
|
+
* starter exports. An entry starts empty for the same reason its barrel does,
|
|
963
|
+
* and because the vendored lint config refuses an unassigned import outside a
|
|
964
|
+
* stylesheet, so a starter `import './index.js'` would fail the workspace's own
|
|
965
|
+
* `lint:check` on the day it is written.
|
|
948
966
|
*
|
|
949
967
|
* @example
|
|
950
968
|
* ```ts
|
|
@@ -956,8 +974,6 @@ export default defineConfig(appShowcase())
|
|
|
956
974
|
var ARTIFACT_TEMPLATES = Object.freeze({
|
|
957
975
|
source: Object.freeze({
|
|
958
976
|
empty: "",
|
|
959
|
-
main: `import './index.js'
|
|
960
|
-
`,
|
|
961
977
|
browser: `<!doctype html>
|
|
962
978
|
<html lang="en">
|
|
963
979
|
<head>
|
|
@@ -1142,16 +1158,20 @@ printf '%s\\n' \\
|
|
|
1142
1158
|
* The one error this package throws, carrying the coded reason it was raised.
|
|
1143
1159
|
*
|
|
1144
1160
|
* @remarks
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
* `
|
|
1149
|
-
*
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1154
|
-
*
|
|
1161
|
+
* Each code names one cause: `INVALID` for off-contract input, `DESTROYED` for
|
|
1162
|
+
* any call made after teardown, `TARGET` for a destination that is not what the
|
|
1163
|
+
* caller's observation said it was, `WRITE` for a mutation that could not be
|
|
1164
|
+
* completed, `FETCH` for an upstream read that produced no answer the caller can
|
|
1165
|
+
* be given, and `BLOCKED` for a refused blueprint.
|
|
1166
|
+
*
|
|
1167
|
+
* `BLOCKED` covers both refusals a blueprint can meet, because they are one fact
|
|
1168
|
+
* — this blueprint will not be built — and the questions say which. The compiler
|
|
1169
|
+
* answers its refusal rather than throwing it: the gate fails closed, returns the
|
|
1170
|
+
* questions that closed it, and records `BLOCKED` on its stage, so a caller reads
|
|
1171
|
+
* that refusal from the value it asked for. A verb that creates a workspace
|
|
1172
|
+
* throws it, because it chose the shape and has nothing to hand back. A blocking
|
|
1173
|
+
* question closed the gate; a non-blocking one is a shape this package can
|
|
1174
|
+
* describe and declines to create.
|
|
1155
1175
|
*
|
|
1156
1176
|
* `context` carries whatever the raising site can say about the failure. It is
|
|
1157
1177
|
* `unknown` because nothing narrows it usefully at the catch site; read it for
|
|
@@ -1205,19 +1225,20 @@ function isScaffoldError(value) {
|
|
|
1205
1225
|
//#endregion
|
|
1206
1226
|
//#region src/core/validators.ts
|
|
1207
1227
|
/**
|
|
1208
|
-
* Narrow a value to a
|
|
1228
|
+
* Narrow a value to a logical target-relative path.
|
|
1209
1229
|
*
|
|
1210
1230
|
* @param value - The candidate path.
|
|
1211
1231
|
* @returns `true` for a bounded relative path with no traversal, empty segment,
|
|
1212
|
-
* control character, or
|
|
1232
|
+
* control character, or reserved syntax character.
|
|
1213
1233
|
*
|
|
1214
1234
|
* @remarks
|
|
1215
1235
|
* Every path this package reads or writes passes here, so one law covers a
|
|
1216
1236
|
* planned artifact, an override target, an audit finding, a guide mirror, and a
|
|
1217
1237
|
* snapshot key. Rejecting `..`, a leading `/`, and a backslash at the guard is
|
|
1218
1238
|
* what stops a caller-supplied path from naming a destination outside the
|
|
1219
|
-
* target
|
|
1220
|
-
*
|
|
1239
|
+
* target. Host-location validation is a separate server boundary: this guard
|
|
1240
|
+
* does not reject a device spelling, a trailing dot or space, or a segment that
|
|
1241
|
+
* exceeds a host filesystem's byte ceiling.
|
|
1221
1242
|
*
|
|
1222
1243
|
* @example
|
|
1223
1244
|
* ```ts
|
|
@@ -1495,20 +1516,34 @@ var isQuestion = recordOf({
|
|
|
1495
1516
|
* @remarks
|
|
1496
1517
|
* `observed` is required exactly where the mutation it precedes is held to it,
|
|
1497
1518
|
* absent where the destination had no bytes to record, and optional where the
|
|
1498
|
-
* comparison may not have been made.
|
|
1519
|
+
* comparison may not have been made. Planned findings require `ownership`;
|
|
1520
|
+
* foreign findings forbid it because no artifact was planned for their path.
|
|
1521
|
+
*
|
|
1522
|
+
* That is the whole claim. This guard proves the shape a reader may destructure
|
|
1523
|
+
* and nothing about whether the verdict is one an audit could have reached: the
|
|
1524
|
+
* correlation between `ownership`, `drift`, and `observed` belongs to
|
|
1525
|
+
* {@link inferDrift}, and it is re-derived at the verb that acts on the finding.
|
|
1499
1526
|
*/
|
|
1500
1527
|
var isFinding = unionOf(recordOf({
|
|
1501
1528
|
path: isPath,
|
|
1502
1529
|
group: isGroup,
|
|
1503
|
-
|
|
1530
|
+
ownership: literalOf("content", "presence", "birth"),
|
|
1531
|
+
drift: literalOf("stale"),
|
|
1532
|
+
observed: isHex
|
|
1533
|
+
}), recordOf({
|
|
1534
|
+
path: isPath,
|
|
1535
|
+
group: isGroup,
|
|
1536
|
+
drift: literalOf("foreign"),
|
|
1504
1537
|
observed: isHex
|
|
1505
1538
|
}), recordOf({
|
|
1506
1539
|
path: isPath,
|
|
1507
1540
|
group: isGroup,
|
|
1541
|
+
ownership: literalOf("content", "presence", "birth"),
|
|
1508
1542
|
drift: literalOf("missing")
|
|
1509
1543
|
}), recordOf({
|
|
1510
1544
|
path: isPath,
|
|
1511
1545
|
group: isGroup,
|
|
1546
|
+
ownership: literalOf("content", "presence", "birth"),
|
|
1512
1547
|
drift: literalOf("aligned"),
|
|
1513
1548
|
observed: isHex
|
|
1514
1549
|
}, ["observed"]));
|
|
@@ -1517,10 +1552,11 @@ var isFinding = unionOf(recordOf({
|
|
|
1517
1552
|
*
|
|
1518
1553
|
* @remarks
|
|
1519
1554
|
* An audit reaches the writer and the destructive verb, so it is guarded as
|
|
1520
|
-
* strictly as the plan beside it.
|
|
1555
|
+
* strictly as the plan beside it. Findings use the sum of the two producer
|
|
1556
|
+
* bounds: one per planned artifact, then one per unplanned snapshot path.
|
|
1521
1557
|
*/
|
|
1522
1558
|
var isAudit = recordOf({
|
|
1523
|
-
findings: andOf(
|
|
1559
|
+
findings: andOf((value) => holds(() => isArray(value) && value.length <= 2e3), arrayOf(isFinding)),
|
|
1524
1560
|
questions: andOf(isCollection, arrayOf(isQuestion))
|
|
1525
1561
|
});
|
|
1526
1562
|
/**
|
|
@@ -2110,6 +2146,23 @@ function inferDrift(artifact, observed) {
|
|
|
2110
2146
|
return observed === artifactToHex(artifact) ? "aligned" : "stale";
|
|
2111
2147
|
}
|
|
2112
2148
|
/**
|
|
2149
|
+
* Test whether {@link inferDrift} could have produced a finding for an ownership.
|
|
2150
|
+
*
|
|
2151
|
+
* @param ownership - What scaffold claims at the planned path.
|
|
2152
|
+
* @param finding - The audit verdict to test.
|
|
2153
|
+
* @returns Whether the ownership and verdict are reachable through {@link inferDrift}.
|
|
2154
|
+
*
|
|
2155
|
+
* @remarks
|
|
2156
|
+
* This predicate keeps the comparison law beside the reachability law it
|
|
2157
|
+
* restates. A mutation uses it so a refusal can distinguish an impossible
|
|
2158
|
+
* verdict from a target that genuinely moved after its audit.
|
|
2159
|
+
*/
|
|
2160
|
+
function matchesDriftReachability(ownership, finding) {
|
|
2161
|
+
if (finding.drift === "aligned") return ownership === "birth" || finding.observed !== void 0;
|
|
2162
|
+
if (finding.drift === "missing") return ownership !== "birth";
|
|
2163
|
+
return finding.drift === "stale" && ownership === "content";
|
|
2164
|
+
}
|
|
2165
|
+
/**
|
|
2113
2166
|
* Project a plan into its tally by artifact origin.
|
|
2114
2167
|
*
|
|
2115
2168
|
* @param plan - The plan to summarize.
|
|
@@ -2537,10 +2590,9 @@ function srcToExports(src) {
|
|
|
2537
2590
|
*
|
|
2538
2591
|
* @example
|
|
2539
2592
|
* ```ts
|
|
2540
|
-
* import
|
|
2541
|
-
* import { blueprintToDevDependencies } from '@orkestrel/scaffold'
|
|
2593
|
+
* import { blueprintToDevDependencies, createBlueprint } from '@orkestrel/scaffold'
|
|
2542
2594
|
*
|
|
2543
|
-
*
|
|
2595
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2544
2596
|
*
|
|
2545
2597
|
* blueprintToDevDependencies(blueprint).typescript // the shared TypeScript pin
|
|
2546
2598
|
* ```
|
|
@@ -2551,7 +2603,7 @@ function blueprintToDevDependencies(blueprint) {
|
|
|
2551
2603
|
...blueprint.src.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
|
|
2552
2604
|
...blueprint.app.length > 0 ? APP_DEV_DEPENDENCIES : {},
|
|
2553
2605
|
...blueprint.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
|
|
2554
|
-
...blueprint.showcase ? SHOWCASE_DEV_DEPENDENCIES : {},
|
|
2606
|
+
...blueprint.showcase && blueprint.app.includes("browser") ? SHOWCASE_DEV_DEPENDENCIES : {},
|
|
2555
2607
|
...blueprint.app.includes("server") ? APP_SERVER_DEV_DEPENDENCIES : {}
|
|
2556
2608
|
};
|
|
2557
2609
|
for (const extra of blueprint.extras) merged[extra.name] = extra.range;
|
|
@@ -2580,10 +2632,9 @@ function blueprintToDevDependencies(blueprint) {
|
|
|
2580
2632
|
*
|
|
2581
2633
|
* @example
|
|
2582
2634
|
* ```ts
|
|
2583
|
-
* import
|
|
2584
|
-
* import { blueprintToScripts } from '@orkestrel/scaffold'
|
|
2635
|
+
* import { blueprintToScripts, createBlueprint } from '@orkestrel/scaffold'
|
|
2585
2636
|
*
|
|
2586
|
-
*
|
|
2637
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2587
2638
|
*
|
|
2588
2639
|
* blueprintToScripts(blueprint)['format:check'] // 'oxfmt --config .oxfmtrc.json --check .'
|
|
2589
2640
|
* ```
|
|
@@ -2699,10 +2750,9 @@ function blueprintToScripts(blueprint) {
|
|
|
2699
2750
|
*
|
|
2700
2751
|
* @example
|
|
2701
2752
|
* ```ts
|
|
2702
|
-
* import
|
|
2703
|
-
* import { blueprintToManifest } from '@orkestrel/scaffold'
|
|
2753
|
+
* import { blueprintToManifest, createBlueprint } from '@orkestrel/scaffold'
|
|
2704
2754
|
*
|
|
2705
|
-
*
|
|
2755
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2706
2756
|
*
|
|
2707
2757
|
* blueprintToManifest(blueprint).endsWith('}\n') // true
|
|
2708
2758
|
* ```
|
|
@@ -2778,12 +2828,11 @@ function blueprintToManifest(blueprint) {
|
|
|
2778
2828
|
*
|
|
2779
2829
|
* @example
|
|
2780
2830
|
* ```ts
|
|
2781
|
-
* import
|
|
2782
|
-
* import { blueprintToMachinery } from '@orkestrel/scaffold'
|
|
2831
|
+
* import { blueprintToMachinery, createBlueprint } from '@orkestrel/scaffold'
|
|
2783
2832
|
*
|
|
2784
|
-
*
|
|
2833
|
+
* const blueprint = createBlueprint('router', { app: ['browser'] })
|
|
2785
2834
|
*
|
|
2786
|
-
* blueprintToMachinery(blueprint).vue // true
|
|
2835
|
+
* blueprintToMachinery(blueprint).vue // true
|
|
2787
2836
|
* ```
|
|
2788
2837
|
*/
|
|
2789
2838
|
function blueprintToMachinery(blueprint) {
|
|
@@ -2803,10 +2852,9 @@ function blueprintToMachinery(blueprint) {
|
|
|
2803
2852
|
*
|
|
2804
2853
|
* @example
|
|
2805
2854
|
* ```ts
|
|
2806
|
-
* import
|
|
2807
|
-
* import { blueprintToRootTsconfig } from '@orkestrel/scaffold'
|
|
2855
|
+
* import { blueprintToRootTsconfig, createBlueprint } from '@orkestrel/scaffold'
|
|
2808
2856
|
*
|
|
2809
|
-
*
|
|
2857
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2810
2858
|
*
|
|
2811
2859
|
* blueprintToRootTsconfig(blueprint).startsWith('{') // true
|
|
2812
2860
|
* ```
|
|
@@ -2831,10 +2879,9 @@ function blueprintToRootTsconfig(blueprint) {
|
|
|
2831
2879
|
*
|
|
2832
2880
|
* @example
|
|
2833
2881
|
* ```ts
|
|
2834
|
-
* import
|
|
2835
|
-
* import { blueprintToRootVite } from '@orkestrel/scaffold'
|
|
2882
|
+
* import { blueprintToRootVite, createBlueprint } from '@orkestrel/scaffold'
|
|
2836
2883
|
*
|
|
2837
|
-
*
|
|
2884
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2838
2885
|
*
|
|
2839
2886
|
* blueprintToRootVite(blueprint).includes('defineConfig') // true
|
|
2840
2887
|
* ```
|
|
@@ -2864,8 +2911,7 @@ function blueprintToRootVite(blueprint) {
|
|
|
2864
2911
|
const core = blueprint.src.includes("core");
|
|
2865
2912
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
|
|
2866
2913
|
external: core ? `external: (id: string) =>
|
|
2867
|
-
id === '@src/core' || id.startsWith('node:') || id.startsWith('@orkestrel/'),` :
|
|
2868
|
-
id.startsWith('node:') || id.startsWith('@orkestrel/'),`,
|
|
2914
|
+
id === '@src/core' || id.startsWith('node:') || id.startsWith('@orkestrel/'),` : "external: (id: string) => id.startsWith('node:') || id.startsWith('@orkestrel/'),",
|
|
2869
2915
|
output: core ? `\t\t\t\t\toutput: [
|
|
2870
2916
|
{
|
|
2871
2917
|
format: 'es',
|
|
@@ -2891,28 +2937,35 @@ function blueprintToRootVite(blueprint) {
|
|
|
2891
2937
|
projects.push("appCore");
|
|
2892
2938
|
}
|
|
2893
2939
|
if (blueprint.app.includes("browser")) {
|
|
2894
|
-
const
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
},
|
|
2911
|
-
},
|
|
2940
|
+
const showcasePlugins = machinery.showcase ? ` const showcasePlugins: PluginOption[] = showcase
|
|
2941
|
+
? [
|
|
2942
|
+
viteSingleFile({
|
|
2943
|
+
removeViteModuleLoader: true,
|
|
2944
|
+
useRecommendedBuildConfig: true,
|
|
2945
|
+
}),
|
|
2946
|
+
{
|
|
2947
|
+
name: 'orkestrel-showcase-html',
|
|
2948
|
+
transformIndexHtml: {
|
|
2949
|
+
order: 'post',
|
|
2950
|
+
handler(html) {
|
|
2951
|
+
const stamp = new Date().toISOString()
|
|
2952
|
+
return html.replace(
|
|
2953
|
+
'</head>',
|
|
2954
|
+
'\t\t<meta name="build-id" content="' + stamp + '" />\\n\t</head>',
|
|
2955
|
+
)
|
|
2912
2956
|
},
|
|
2913
|
-
|
|
2914
|
-
|
|
2957
|
+
},
|
|
2958
|
+
},
|
|
2959
|
+
]
|
|
2960
|
+
: []
|
|
2915
2961
|
` : "";
|
|
2962
|
+
const plugins = machinery.showcase ? `\t\tplugins: [
|
|
2963
|
+
outputBoundary(output),
|
|
2964
|
+
environmentBoundary('app/browser'),
|
|
2965
|
+
vue(),
|
|
2966
|
+
...showcasePlugins,
|
|
2967
|
+
],
|
|
2968
|
+
` : " plugins: [outputBoundary(output), environmentBoundary('app/browser'), vue()],\n";
|
|
2916
2969
|
const showcaseBuild = machinery.showcase ? `\t\t\t...(showcase
|
|
2917
2970
|
? {
|
|
2918
2971
|
cssMinify: 'lightningcss',
|
|
@@ -2931,11 +2984,12 @@ export function appShowcase(...options: never[]): UserConfig {
|
|
|
2931
2984
|
}
|
|
2932
2985
|
` : "";
|
|
2933
2986
|
factories.push(fillTemplate(CONFIG_TEMPLATES.factories.app.browser, {
|
|
2934
|
-
|
|
2987
|
+
plugins,
|
|
2988
|
+
showcasePlugins,
|
|
2935
2989
|
showcaseBuild,
|
|
2936
2990
|
showcaseFactory
|
|
2937
2991
|
}));
|
|
2938
|
-
projects.push("appBrowser");
|
|
2992
|
+
projects.push("appBrowser()");
|
|
2939
2993
|
}
|
|
2940
2994
|
if (blueprint.app.includes("server")) {
|
|
2941
2995
|
factories.push(CONFIG_TEMPLATES.factories.app.server);
|
|
@@ -2956,9 +3010,13 @@ export function appShowcase(...options: never[]): UserConfig {
|
|
|
2956
3010
|
const projectRows = `\t\tprojects: [
|
|
2957
3011
|
${projects.map((project) => `\t\t\t${project},`).join("\n")}
|
|
2958
3012
|
\t],`;
|
|
3013
|
+
const body = `${factories.join("\n")}\n`;
|
|
3014
|
+
const boundaries = ["environmentBoundary", "outputBoundary"].filter((boundary) => body.includes(boundary));
|
|
2959
3015
|
return fillTemplate(CONFIG_TEMPLATES.root.vite, {
|
|
3016
|
+
viteTypes: machinery.showcase ? "PluginOption, UserConfig" : "UserConfig",
|
|
2960
3017
|
imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
|
|
2961
|
-
|
|
3018
|
+
helpers: boundaries.length === 0 ? "" : `import { ${boundaries.join(", ")} } from './configs/helpers.js'\n`,
|
|
3019
|
+
factories: body,
|
|
2962
3020
|
projects: projectRows
|
|
2963
3021
|
});
|
|
2964
3022
|
}
|
|
@@ -2970,10 +3028,9 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
|
|
|
2970
3028
|
*
|
|
2971
3029
|
* @example
|
|
2972
3030
|
* ```ts
|
|
2973
|
-
* import
|
|
2974
|
-
* import { blueprintToConfigArtifacts } from '@orkestrel/scaffold'
|
|
3031
|
+
* import { blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
|
|
2975
3032
|
*
|
|
2976
|
-
*
|
|
3033
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
2977
3034
|
*
|
|
2978
3035
|
* blueprintToConfigArtifacts(blueprint)[0]?.path // 'tsconfig.json'
|
|
2979
3036
|
* ```
|
|
@@ -2999,7 +3056,8 @@ function blueprintToConfigArtifacts(blueprint) {
|
|
|
2999
3056
|
else if (path === "configs/src/tsconfig.browser.json") content = CONFIG_TEMPLATES.tsconfigs.src.browser;
|
|
3000
3057
|
else if (path === "configs/src/vite.server.config.ts") {
|
|
3001
3058
|
const packageName = serializeTypeScriptString(`@orkestrel/${blueprint.name}`);
|
|
3002
|
-
const
|
|
3059
|
+
const joined = `\t\t\t\t\t\t? content.replaceAll(/(?:\\.\\.\\/)+core\\/index\\.ts/g, ${packageName})`;
|
|
3060
|
+
const replacement = joined.replaceAll(" ", " ").length <= 100 ? joined : [
|
|
3003
3061
|
" ? content.replaceAll(",
|
|
3004
3062
|
" /(?:\\.\\.\\/)+core\\/index\\.ts/g,",
|
|
3005
3063
|
`\t\t\t\t\t\t\t\t${packageName},`,
|
|
@@ -3064,7 +3122,7 @@ ${paths.join("\n")}
|
|
|
3064
3122
|
content
|
|
3065
3123
|
});
|
|
3066
3124
|
}
|
|
3067
|
-
if (blueprint.showcase) artifacts.push({
|
|
3125
|
+
if (blueprint.showcase && blueprint.app.includes("browser")) artifacts.push({
|
|
3068
3126
|
path: SHOWCASE_CONFIG_PATH,
|
|
3069
3127
|
group: "configs",
|
|
3070
3128
|
ownership: "content",
|
|
@@ -3081,16 +3139,18 @@ ${paths.join("\n")}
|
|
|
3081
3139
|
* @returns Empty published barrels, selected application entries, and the optional bin entry.
|
|
3082
3140
|
*
|
|
3083
3141
|
* @remarks
|
|
3084
|
-
* The barrels and
|
|
3085
|
-
* entity is too easy to mistake for package implementation, so the
|
|
3086
|
-
* establishes only the selected environment boundaries.
|
|
3142
|
+
* The barrels and every runtime entry intentionally hold nothing. A generated
|
|
3143
|
+
* sample entity is too easy to mistake for package implementation, so the
|
|
3144
|
+
* scaffold establishes only the selected environment boundaries. An application
|
|
3145
|
+
* entry is empty for the same reason the bin entry is, and because the vendored
|
|
3146
|
+
* lint config refuses an unassigned import outside a stylesheet, so the entry
|
|
3147
|
+
* cannot start by importing its barrel for effect either.
|
|
3087
3148
|
*
|
|
3088
3149
|
* @example
|
|
3089
3150
|
* ```ts
|
|
3090
|
-
* import
|
|
3091
|
-
* import { blueprintToSourceArtifacts } from '@orkestrel/scaffold'
|
|
3151
|
+
* import { blueprintToSourceArtifacts, createBlueprint } from '@orkestrel/scaffold'
|
|
3092
3152
|
*
|
|
3093
|
-
*
|
|
3153
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
3094
3154
|
*
|
|
3095
3155
|
* blueprintToSourceArtifacts(blueprint).every(({ group }) => group === 'source') // true
|
|
3096
3156
|
* ```
|
|
@@ -3120,7 +3180,7 @@ function blueprintToSourceArtifacts(blueprint) {
|
|
|
3120
3180
|
ownership: "birth",
|
|
3121
3181
|
origin: "template",
|
|
3122
3182
|
environment,
|
|
3123
|
-
content: ARTIFACT_TEMPLATES.source.
|
|
3183
|
+
content: ARTIFACT_TEMPLATES.source.empty
|
|
3124
3184
|
}, {
|
|
3125
3185
|
path: "app/browser/index.html",
|
|
3126
3186
|
group: "source",
|
|
@@ -3135,7 +3195,7 @@ function blueprintToSourceArtifacts(blueprint) {
|
|
|
3135
3195
|
ownership: "birth",
|
|
3136
3196
|
origin: "template",
|
|
3137
3197
|
environment,
|
|
3138
|
-
content: ARTIFACT_TEMPLATES.source.
|
|
3198
|
+
content: ARTIFACT_TEMPLATES.source.empty
|
|
3139
3199
|
});
|
|
3140
3200
|
}
|
|
3141
3201
|
if (blueprint.bin) artifacts.push({
|
|
@@ -3163,10 +3223,9 @@ function blueprintToSourceArtifacts(blueprint) {
|
|
|
3163
3223
|
*
|
|
3164
3224
|
* @example
|
|
3165
3225
|
* ```ts
|
|
3166
|
-
* import
|
|
3167
|
-
* import { blueprintToTestArtifacts } from '@orkestrel/scaffold'
|
|
3226
|
+
* import { blueprintToTestArtifacts, createBlueprint } from '@orkestrel/scaffold'
|
|
3168
3227
|
*
|
|
3169
|
-
*
|
|
3228
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
3170
3229
|
*
|
|
3171
3230
|
* blueprintToTestArtifacts(blueprint)[0]?.path // 'tests/setup.ts'
|
|
3172
3231
|
* ```
|
|
@@ -3376,10 +3435,9 @@ function nameToHostArtifacts(name) {
|
|
|
3376
3435
|
*
|
|
3377
3436
|
* @example
|
|
3378
3437
|
* ```ts
|
|
3379
|
-
* import
|
|
3380
|
-
* import { applyOverrides } from '@orkestrel/scaffold'
|
|
3438
|
+
* import { applyOverrides, blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
|
|
3381
3439
|
*
|
|
3382
|
-
*
|
|
3440
|
+
* const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
|
|
3383
3441
|
*
|
|
3384
3442
|
* applyOverrides(artifacts, [{ path: 'README.md', content: '# Title\n' }])
|
|
3385
3443
|
* ```
|
|
@@ -3417,12 +3475,11 @@ function applyOverrides(artifacts, overrides) {
|
|
|
3417
3475
|
*
|
|
3418
3476
|
* @example
|
|
3419
3477
|
* ```ts
|
|
3420
|
-
* import
|
|
3421
|
-
* import { planToHash } from '@orkestrel/scaffold'
|
|
3478
|
+
* import { createBlueprint, createCompiler, planToHash } from '@orkestrel/scaffold'
|
|
3422
3479
|
*
|
|
3423
|
-
*
|
|
3480
|
+
* const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
|
|
3424
3481
|
*
|
|
3425
|
-
* planToHash(plan)?.length // 16
|
|
3482
|
+
* plan === undefined ? undefined : planToHash(plan)?.length // 16
|
|
3426
3483
|
* ```
|
|
3427
3484
|
*/
|
|
3428
3485
|
function planToHash(plan) {
|
|
@@ -3440,13 +3497,16 @@ function planToHash(plan) {
|
|
|
3440
3497
|
* @param artifact - The planned artifact.
|
|
3441
3498
|
* @param observed - The destination's exact bytes as hexadecimal; absent when
|
|
3442
3499
|
* the destination holds no file.
|
|
3443
|
-
* @returns The finding, carrying
|
|
3500
|
+
* @returns The finding, carrying the artifact's ownership and `observed`
|
|
3501
|
+
* exactly where bytes were read.
|
|
3444
3502
|
*
|
|
3445
3503
|
* @remarks
|
|
3446
3504
|
* The comparison itself is {@link inferDrift}'s, so ownership decides it here
|
|
3447
3505
|
* exactly as it does everywhere else. This adds only the shape: a missing
|
|
3448
3506
|
* destination has no bytes to record, and every other verdict records the bytes
|
|
3449
3507
|
* it was given, which is the precondition the mutation that follows is held to.
|
|
3508
|
+
* Ownership is copied rather than inferred from drift because aligned findings
|
|
3509
|
+
* span all three ownership tiers.
|
|
3450
3510
|
*
|
|
3451
3511
|
* `foreign` is not answerable here, because it describes a path no artifact was
|
|
3452
3512
|
* planned for.
|
|
@@ -3458,29 +3518,34 @@ function planToHash(plan) {
|
|
|
3458
3518
|
* artifactToFinding(
|
|
3459
3519
|
* { path: 'README.md', group: 'docs', ownership: 'content', origin: 'computed', content: 'hi\n' },
|
|
3460
3520
|
* '6279650a',
|
|
3461
|
-
* ) // { path: 'README.md', group: 'docs', drift: 'stale', observed: '6279650a' }
|
|
3521
|
+
* ) // { path: 'README.md', group: 'docs', ownership: 'content', drift: 'stale', observed: '6279650a' }
|
|
3462
3522
|
* ```
|
|
3463
3523
|
*/
|
|
3464
3524
|
function artifactToFinding(artifact, observed) {
|
|
3465
3525
|
const path = artifact.path;
|
|
3466
3526
|
const group = artifact.group;
|
|
3527
|
+
const ownership = artifact.ownership;
|
|
3467
3528
|
if (observed === void 0) return inferDrift(artifact) === "aligned" ? {
|
|
3468
3529
|
path,
|
|
3469
3530
|
group,
|
|
3531
|
+
ownership,
|
|
3470
3532
|
drift: "aligned"
|
|
3471
3533
|
} : {
|
|
3472
3534
|
path,
|
|
3473
3535
|
group,
|
|
3536
|
+
ownership,
|
|
3474
3537
|
drift: "missing"
|
|
3475
3538
|
};
|
|
3476
3539
|
return inferDrift(artifact, observed) === "stale" ? {
|
|
3477
3540
|
path,
|
|
3478
3541
|
group,
|
|
3542
|
+
ownership,
|
|
3479
3543
|
drift: "stale",
|
|
3480
3544
|
observed
|
|
3481
3545
|
} : {
|
|
3482
3546
|
path,
|
|
3483
3547
|
group,
|
|
3548
|
+
ownership,
|
|
3484
3549
|
drift: "aligned",
|
|
3485
3550
|
observed
|
|
3486
3551
|
};
|
|
@@ -3504,12 +3569,11 @@ function artifactToFinding(artifact, observed) {
|
|
|
3504
3569
|
*
|
|
3505
3570
|
* @example
|
|
3506
3571
|
* ```ts
|
|
3507
|
-
* import
|
|
3508
|
-
* import { planToFindings } from '@orkestrel/scaffold'
|
|
3572
|
+
* import { createBlueprint, createCompiler, planToFindings } from '@orkestrel/scaffold'
|
|
3509
3573
|
*
|
|
3510
|
-
*
|
|
3574
|
+
* const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
|
|
3511
3575
|
*
|
|
3512
|
-
* planToFindings(plan, { 'AGENTS.md': '68690a' })
|
|
3576
|
+
* plan === undefined ? [] : planToFindings(plan, { 'AGENTS.md': '68690a' })
|
|
3513
3577
|
* ```
|
|
3514
3578
|
*/
|
|
3515
3579
|
function planToFindings(plan, current) {
|
|
@@ -3593,8 +3657,8 @@ function dependenciesToQuestions(dependencies, field, name, range) {
|
|
|
3593
3657
|
* Measure a blueprint against every law its own fields decide.
|
|
3594
3658
|
*
|
|
3595
3659
|
* @param blueprint - The workspace specification.
|
|
3596
|
-
* @returns One
|
|
3597
|
-
*
|
|
3660
|
+
* @returns One question per rejected field, in blueprint field order, with the
|
|
3661
|
+
* rules that span several fields last.
|
|
3598
3662
|
*
|
|
3599
3663
|
* @remarks
|
|
3600
3664
|
* Only the laws a blueprint answers alone are here. The structural record and
|
|
@@ -3605,19 +3669,25 @@ function dependenciesToQuestions(dependencies, field, name, range) {
|
|
|
3605
3669
|
* a drafted plan belong to {@link artifactsToQuestions} and
|
|
3606
3670
|
* {@link overridesToQuestions}.
|
|
3607
3671
|
*
|
|
3608
|
-
*
|
|
3609
|
-
*
|
|
3610
|
-
*
|
|
3611
|
-
*
|
|
3672
|
+
* A question blocks when it describes a workspace this package cannot generate.
|
|
3673
|
+
* Three do not, because each describes a workspace it can describe honestly and
|
|
3674
|
+
* should not create: a published axis of several environments without core, whose
|
|
3675
|
+
* manifest names a core build the workspace never runs, and a structural flag
|
|
3676
|
+
* whose required axis is absent, which emits nothing. Blocking those closed the
|
|
3677
|
+
* gate for every verb, and the verbs that read an existing workspace need the
|
|
3678
|
+
* plan the gate refused. The caller that chooses the shape refuses the advisory;
|
|
3679
|
+
* the callers that read one report it.
|
|
3680
|
+
*
|
|
3681
|
+
* An environment question carries `ENVIRONMENTS` as its candidates, so a caller
|
|
3682
|
+
* reads the accepted values from the question instead of from the documentation.
|
|
3612
3683
|
*
|
|
3613
3684
|
* @example
|
|
3614
3685
|
* ```ts
|
|
3615
|
-
* import
|
|
3616
|
-
* import { blueprintToQuestions } from '@orkestrel/scaffold'
|
|
3686
|
+
* import { blueprintToQuestions, createBlueprint } from '@orkestrel/scaffold'
|
|
3617
3687
|
*
|
|
3618
|
-
*
|
|
3688
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
3619
3689
|
*
|
|
3620
|
-
* blueprintToQuestions(blueprint).length === 0 // true
|
|
3690
|
+
* blueprintToQuestions(blueprint).length === 0 // true
|
|
3621
3691
|
* ```
|
|
3622
3692
|
*/
|
|
3623
3693
|
function blueprintToQuestions(blueprint) {
|
|
@@ -3643,6 +3713,12 @@ function blueprintToQuestions(blueprint) {
|
|
|
3643
3713
|
blocking: true,
|
|
3644
3714
|
candidates: ENVIRONMENTS
|
|
3645
3715
|
});
|
|
3716
|
+
if (blueprint.src.length > 1 && !blueprint.src.includes("core")) questions.push({
|
|
3717
|
+
field: "src",
|
|
3718
|
+
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.",
|
|
3719
|
+
blocking: false,
|
|
3720
|
+
candidates: ENVIRONMENTS
|
|
3721
|
+
});
|
|
3646
3722
|
for (const environment of ENVIRONMENTS) {
|
|
3647
3723
|
if (blueprint.src.filter((declared) => declared === environment).length > 1) questions.push({
|
|
3648
3724
|
field: "src",
|
|
@@ -3657,11 +3733,10 @@ function blueprintToQuestions(blueprint) {
|
|
|
3657
3733
|
candidates: ENVIRONMENTS
|
|
3658
3734
|
});
|
|
3659
3735
|
}
|
|
3660
|
-
if (blueprint.
|
|
3661
|
-
field: "
|
|
3662
|
-
message: "
|
|
3663
|
-
blocking:
|
|
3664
|
-
candidates: ENVIRONMENTS
|
|
3736
|
+
if (blueprint.integration && blueprint.src.length === 0) questions.push({
|
|
3737
|
+
field: "integration",
|
|
3738
|
+
message: "integration projects a published src, and this workspace declares none, so it emits nothing.",
|
|
3739
|
+
blocking: false
|
|
3665
3740
|
});
|
|
3666
3741
|
const services = /* @__PURE__ */ new Set();
|
|
3667
3742
|
for (const service of blueprint.services) {
|
|
@@ -3677,6 +3752,11 @@ function blueprintToQuestions(blueprint) {
|
|
|
3677
3752
|
});
|
|
3678
3753
|
services.add(service);
|
|
3679
3754
|
}
|
|
3755
|
+
if (blueprint.showcase && !blueprint.app.includes("browser")) questions.push({
|
|
3756
|
+
field: "showcase",
|
|
3757
|
+
message: "showcase projects a browser app, and this workspace declares none, so it emits nothing.",
|
|
3758
|
+
blocking: false
|
|
3759
|
+
});
|
|
3680
3760
|
questions.push(...dependenciesToQuestions(blueprint.dependencies, "dependencies", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers, "peers", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.extras, "extras", EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN));
|
|
3681
3761
|
const lists = [
|
|
3682
3762
|
["dependencies", blueprint.dependencies],
|
|
@@ -3725,12 +3805,11 @@ function blueprintToQuestions(blueprint) {
|
|
|
3725
3805
|
*
|
|
3726
3806
|
* @example
|
|
3727
3807
|
* ```ts
|
|
3728
|
-
* import
|
|
3729
|
-
* import { artifactsToQuestions } from '@orkestrel/scaffold'
|
|
3808
|
+
* import { artifactsToQuestions, blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
|
|
3730
3809
|
*
|
|
3731
|
-
*
|
|
3810
|
+
* const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
|
|
3732
3811
|
*
|
|
3733
|
-
* artifactsToQuestions(artifacts).length === 0 // true
|
|
3812
|
+
* artifactsToQuestions(artifacts).length === 0 // true
|
|
3734
3813
|
* ```
|
|
3735
3814
|
*/
|
|
3736
3815
|
function artifactsToQuestions(artifacts) {
|
|
@@ -3782,10 +3861,9 @@ function artifactsToQuestions(artifacts) {
|
|
|
3782
3861
|
*
|
|
3783
3862
|
* @example
|
|
3784
3863
|
* ```ts
|
|
3785
|
-
* import
|
|
3786
|
-
* import { overridesToQuestions } from '@orkestrel/scaffold'
|
|
3864
|
+
* import { blueprintToConfigArtifacts, createBlueprint, overridesToQuestions } from '@orkestrel/scaffold'
|
|
3787
3865
|
*
|
|
3788
|
-
*
|
|
3866
|
+
* const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
|
|
3789
3867
|
*
|
|
3790
3868
|
* overridesToQuestions([{ path: 'package.json', content: '{}\n' }], artifacts).length // 1
|
|
3791
3869
|
* ```
|
|
@@ -3912,12 +3990,19 @@ var Compiler = class {
|
|
|
3912
3990
|
* carries no plan, then `compile` with the whole outcome either way, so an
|
|
3913
3991
|
* observer reads every compile from one event and the refusals from the other.
|
|
3914
3992
|
*
|
|
3993
|
+
* A plan says the blueprint can be built. It does not say the blueprint should
|
|
3994
|
+
* be created, and the questions beside it are what this compiler could not
|
|
3995
|
+
* settle. A caller creating a fresh workspace answers them first and writes
|
|
3996
|
+
* nothing while any remains, which is the rule the `new` verb applies; a caller
|
|
3997
|
+
* describing or repairing an existing target carries them through instead.
|
|
3998
|
+
* Nothing downstream repeats that check, because only the caller knows which of
|
|
3999
|
+
* the two it is.
|
|
4000
|
+
*
|
|
3915
4001
|
* @example
|
|
3916
4002
|
* ```ts
|
|
3917
|
-
* import
|
|
3918
|
-
* import { createCompiler } from '@orkestrel/scaffold'
|
|
4003
|
+
* import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
|
|
3919
4004
|
*
|
|
3920
|
-
*
|
|
4005
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
3921
4006
|
*
|
|
3922
4007
|
* createCompiler().compile(blueprint, ['manifest']).plan?.artifacts.length // 1
|
|
3923
4008
|
* ```
|
|
@@ -3945,14 +4030,19 @@ var Compiler = class {
|
|
|
3945
4030
|
* reports no findings and carries the questions instead. Emits `block` in that
|
|
3946
4031
|
* case, then `audit` with the verdict either way.
|
|
3947
4032
|
*
|
|
4033
|
+
* Ownership decides each verdict, not absence. A birth-owned path is never
|
|
4034
|
+
* compared and reads `aligned` against a target holding nothing, while a
|
|
4035
|
+
* content-owned path with no bytes to read is `missing`. An empty snapshot
|
|
4036
|
+
* therefore produces both verdicts rather than one.
|
|
4037
|
+
*
|
|
3948
4038
|
* @example
|
|
3949
4039
|
* ```ts
|
|
3950
|
-
* import
|
|
3951
|
-
* import { createCompiler } from '@orkestrel/scaffold'
|
|
4040
|
+
* import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
|
|
3952
4041
|
*
|
|
3953
|
-
*
|
|
4042
|
+
* const blueprint = createBlueprint('router', { src: ['core'] })
|
|
3954
4043
|
*
|
|
3955
|
-
* createCompiler().audit(blueprint, {}).findings
|
|
4044
|
+
* createCompiler().audit(blueprint, {}, ['manifest']).findings[0]?.drift // 'aligned'
|
|
4045
|
+
* createCompiler().audit(blueprint, {}, ['configs']).findings[0]?.drift // 'missing'
|
|
3956
4046
|
* ```
|
|
3957
4047
|
*/
|
|
3958
4048
|
audit(blueprint, current, groups) {
|
|
@@ -3990,7 +4080,10 @@ var Compiler = class {
|
|
|
3990
4080
|
}
|
|
3991
4081
|
#scaffold(blueprint, groups) {
|
|
3992
4082
|
const stages = [];
|
|
3993
|
-
const
|
|
4083
|
+
const draft = this.#draft(blueprint);
|
|
4084
|
+
const selected = [];
|
|
4085
|
+
for (const group of groups) for (const artifact of draft) if (artifact.group === group) selected.push(artifact);
|
|
4086
|
+
const artifacts = applyOverrides(selected, blueprint.overrides);
|
|
3994
4087
|
stages.push({
|
|
3995
4088
|
stage: "draft",
|
|
3996
4089
|
input: {
|
|
@@ -3999,7 +4092,7 @@ var Compiler = class {
|
|
|
3999
4092
|
},
|
|
4000
4093
|
output: artifacts
|
|
4001
4094
|
});
|
|
4002
|
-
const questions = this.#gate(blueprint, artifacts);
|
|
4095
|
+
const questions = this.#gate(blueprint, draft, artifacts);
|
|
4003
4096
|
const blocking = questions.filter((question) => question.blocking);
|
|
4004
4097
|
if (blocking.length > 0) {
|
|
4005
4098
|
stages.push({
|
|
@@ -4068,8 +4161,8 @@ var Compiler = class {
|
|
|
4068
4161
|
stages
|
|
4069
4162
|
};
|
|
4070
4163
|
}
|
|
4071
|
-
#draft(blueprint
|
|
4072
|
-
|
|
4164
|
+
#draft(blueprint) {
|
|
4165
|
+
return [
|
|
4073
4166
|
{
|
|
4074
4167
|
path: "package.json",
|
|
4075
4168
|
group: "manifest",
|
|
@@ -4085,14 +4178,11 @@ var Compiler = class {
|
|
|
4085
4178
|
...blueprintToOrchestrationArtifacts(blueprint),
|
|
4086
4179
|
...nameToHostArtifacts(blueprint.name)
|
|
4087
4180
|
];
|
|
4088
|
-
const covered = [];
|
|
4089
|
-
for (const group of groups) for (const artifact of drafted) if (artifact.group === group) covered.push(artifact);
|
|
4090
|
-
return applyOverrides(covered, blueprint.overrides);
|
|
4091
4181
|
}
|
|
4092
|
-
#gate(blueprint, artifacts) {
|
|
4182
|
+
#gate(blueprint, draft, artifacts) {
|
|
4093
4183
|
return [
|
|
4094
4184
|
...blueprintToQuestions(blueprint),
|
|
4095
|
-
...overridesToQuestions(blueprint.overrides,
|
|
4185
|
+
...overridesToQuestions(blueprint.overrides, draft),
|
|
4096
4186
|
...artifactsToQuestions(artifacts)
|
|
4097
4187
|
];
|
|
4098
4188
|
}
|
|
@@ -4197,6 +4287,6 @@ function createCompiler(options) {
|
|
|
4197
4287
|
return new Compiler(options);
|
|
4198
4288
|
}
|
|
4199
4289
|
//#endregion
|
|
4200
|
-
export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFIG_TEMPLATES, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, SERVICE_SCRIPT_PATH, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, VERSION_PATTERN, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToGuideArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSourceArtifacts, blueprintToTestArtifacts, bytesToHex, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, createCompiler, dependenciesToQuestions, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDependency, isDependencyName, isEnvironment, isFinding, isGroup, isGroups, isHex, isMirror, isOverride, isPath, isPlan, isQuestion, isScaffoldError, isSnapshot, manifestToDependencies, manifestToName, matchesEngines, matchesOrchestrationPath, matchesRange, nameToGuide, nameToHostArtifacts, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
|
|
4290
|
+
export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFIG_TEMPLATES, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, SERVICE_SCRIPT_PATH, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, VERSION_PATTERN, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToGuideArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSourceArtifacts, blueprintToTestArtifacts, bytesToHex, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, createCompiler, dependenciesToQuestions, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDependency, isDependencyName, isEnvironment, isFinding, isGroup, isGroups, isHex, isMirror, isOverride, isPath, isPlan, isQuestion, isScaffoldError, isSnapshot, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesRange, nameToGuide, nameToHostArtifacts, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
|
|
4201
4291
|
|
|
4202
4292
|
//# sourceMappingURL=index.js.map
|