@orkestrel/scaffold 0.0.85 → 0.0.86
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 +2 -2
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +16 -2
- package/dist/bin/main.js +172 -22
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +6 -6
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +3 -2
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +20 -7
- package/dist/host/claude/agents/orkestrel.md +1 -1
- package/dist/host/guides/scaffold.md +32 -7
- package/dist/host/manifest.json +6 -6
- package/dist/src/core/index.cjs +181 -1
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +39 -0
- package/dist/src/core/index.d.ts +39 -0
- package/dist/src/core/index.js +181 -2
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +31 -7
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +19 -6
- package/dist/src/server/index.d.ts +19 -6
- package/dist/src/server/index.js +32 -8
- package/dist/src/server/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -20,12 +20,12 @@ description: Run an Orkestrel release from layer order to registry confirmation.
|
|
|
20
20
|
|
|
21
21
|
## Scripts
|
|
22
22
|
|
|
23
|
-
| Script | Does
|
|
24
|
-
| -------------------- |
|
|
25
|
-
| `scripts/compare.ts` | `[--package NAME] [--version V] [--tarball PATH] [--dist dist] [--json]`, run from the package root after its build: fetches the published tarball and lists the material differences from the rebuilt `dist/` (sourcemaps excluded, whitespace-only differences ignored). Exit 0 when nothing differs, 3 when something does, 2 when the tarball cannot be read, 64 on usage (no package name, no `dist/`, or `--tarball` with no path).
|
|
26
|
-
| `scripts/pins.ts` | `--version PRIOR [--range PRIOR_RANGE ...] [--paths src,tests] [--json]`, run from the package root: lists every line under the paths carrying the prior version literal or a prior range literal, once per line, sweeping a one-comparator range such as `^8.3.0` for its bare version in any form. Exit 0 with no hits, 3 with hits, 64 on usage (no literal, or a flag with no value).
|
|
27
|
-
| `scripts/wave.ts` | `--visit [--target DIR] [--offline] [--from STEP] [--to STEP] [--prior VERSION] [--dry-run] [--json] [--out FILE]` runs one repository's visit in the order [wave.md](references/wave.md) § Visit a repository fixes (pin, commit, overwrite, verify, install, pins, format, gates, compare), stops at the first failing step, and prints each step's exit, the bump ruling (the rebuilt dist against the published tarball, and the final runtime dependency set against the published manifest), and a row for `.orkestrel/release.md`; `--prior` names the version a pre-ruled bump replaced so the self-pin sweep finds it; `--plan` prints the packages by layer from the catalog table. Exit 0 when every step passed, 1 when one failed, 2 when a reading failed, 64 on usage. |
|
|
28
|
-
| `scripts/window.ts` | `--whoami [--wait SECONDS]` reads or polls `npm whoami`; `--login` prints the operator's login command and polls `whoami` until it answers; `--publish DIR... --otp CODE` uploads back to back with `npm publish --ignore-scripts --otp`, journals each upload under `tmp/units/`, stops at the first refusal naming where to resume, and confirms each accepted version against the registry; `--confirm NAME@VERSION...` re-reads the registry until it serves the version. Exit 0 on success, 3 when not.
|
|
23
|
+
| Script | Does |
|
|
24
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
25
|
+
| `scripts/compare.ts` | `[--package NAME] [--version V] [--tarball PATH] [--dist dist] [--json]`, run from the package root after its build: fetches the published tarball and lists the material differences from the rebuilt `dist/` (sourcemaps excluded, whitespace-only differences ignored). Exit 0 when nothing differs, 3 when something does, 2 when the tarball cannot be read, 64 on usage (no package name, no `dist/`, or `--tarball` with no path). |
|
|
26
|
+
| `scripts/pins.ts` | `--version PRIOR [--range PRIOR_RANGE ...] [--paths src,tests] [--json]`, run from the package root: lists every line under the paths carrying the prior version literal or a prior range literal, once per line, sweeping a one-comparator range such as `^8.3.0` for its bare version in any form. Exit 0 with no hits, 3 with hits, 64 on usage (no literal, or a flag with no value). |
|
|
27
|
+
| `scripts/wave.ts` | `--visit [--target DIR] [--offline] [--from STEP] [--to STEP] [--prior VERSION] [--dry-run] [--json] [--out FILE]` runs one repository's visit in the order [wave.md](references/wave.md) § Visit a repository fixes (pin, commit, overwrite, verify, install, pins, format, gates, compare), stops at the first failing step, and prints each step's exit (a failed step names the `code: message` refusal or the `note` a JSON verb writes on stdout, else the last stderr lines), the bump ruling (the rebuilt dist against the published tarball, and the final runtime dependency set against the published manifest), and a row for `.orkestrel/release.md`; `--prior` names the version a pre-ruled bump replaced so the self-pin sweep finds it; `--plan` prints the packages by layer from the catalog table. Exit 0 when every step passed, 1 when one failed, 2 when a reading failed, 64 on usage. |
|
|
28
|
+
| `scripts/window.ts` | `--whoami [--wait SECONDS]` reads or polls `npm whoami`; `--login` prints the operator's login command and polls `whoami` until it answers; `--publish DIR... --otp CODE` uploads back to back with `npm publish --ignore-scripts --otp`, journals each upload under `tmp/units/`, stops at the first refusal naming where to resume, and confirms each accepted version against the registry; `--confirm NAME@VERSION...` re-reads the registry until it serves the version. Exit 0 on success, 3 when not. |
|
|
29
29
|
|
|
30
30
|
The user's current instruction wins. `references/release.md` owns the credential
|
|
31
31
|
and authorization law; nothing here weakens it.
|
|
@@ -35,8 +35,9 @@ by hand only to repair it, then resume with `--from <step>`.
|
|
|
35
35
|
again. Keep a local MCP server registration outside the repository rather than at `.mcp.json`.
|
|
36
36
|
4. Force-verify every `@orkestrel` range against a registry sweep taken after the previous layer
|
|
37
37
|
published.
|
|
38
|
-
5. Run the full install. The overwrite re-declares the toolchain ranges
|
|
39
|
-
install regenerated no longer matches the
|
|
38
|
+
5. Run the full install. The overwrite re-declares the toolchain ranges and declares each planned
|
|
39
|
+
dependency the manifest lacks, so the lockfile the first install regenerated no longer matches the
|
|
40
|
+
manifest.
|
|
40
41
|
6. Sweep the self-pins, per § Sweep the self-pins: the re-pin moves the snapshot class.
|
|
41
42
|
7. Run the mutating `format` script to converge generated writes.
|
|
42
43
|
8. Run the quality gates.
|
|
@@ -14,11 +14,12 @@
|
|
|
14
14
|
// fatal), format, gates (format:check, lint:check, check, build, test), and compare (the rebuilt
|
|
15
15
|
// dist against the published tarball, and the final runtime dependency set against the published
|
|
16
16
|
// manifest `npm view NAME --json` serves; both readings are reported, not fatal). The summary
|
|
17
|
-
// carries each step's exit and duration,
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
17
|
+
// carries each step's exit and duration, a failed step's refusal (the `code: message` envelope or
|
|
18
|
+
// the `note` a JSON verb prints on stdout, else the last stderr lines), the bump ruling, and a
|
|
19
|
+
// Markdown row for `.orkestrel/release.md`. --dry-run prints the commands and runs nothing, so its
|
|
20
|
+
// ruling is unanswered. --plan reads the marker-bounded catalog table in
|
|
21
|
+
// `.claude/agents/orkestrel.md` and prints the packages by layer. Exit 0 when every step passed, 1
|
|
22
|
+
// when a step failed, 2 when a reading failed, 64 on usage.
|
|
22
23
|
import type { SpawnSyncReturns } from 'node:child_process'
|
|
23
24
|
import { spawnSync } from 'node:child_process'
|
|
24
25
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
@@ -158,8 +159,20 @@ function describeCommand(file: string, args: readonly string[]): string {
|
|
|
158
159
|
return [file === process.execPath ? 'node' : file, ...args].join(' ')
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
// A JSON verb writes its refusal envelope or its partial-run note on stdout, so the stderr tail
|
|
163
|
+
// alone reads empty for exactly the failures the operator needs named.
|
|
161
164
|
function describeFailure(result: SpawnSyncReturns<string>): string | undefined {
|
|
162
165
|
if (result.status === 0) return undefined
|
|
166
|
+
const value = readJsonObject(result.stdout)
|
|
167
|
+
const error = value?.error
|
|
168
|
+
if (typeof error === 'object' && error !== null && !Array.isArray(error)) {
|
|
169
|
+
const envelope = Object.fromEntries(Object.entries(error))
|
|
170
|
+
const code = readString(envelope, 'code')
|
|
171
|
+
const message = readString(envelope, 'message')
|
|
172
|
+
if (code !== undefined && message !== undefined) return `${code}: ${message}`
|
|
173
|
+
}
|
|
174
|
+
const note = readString(value, 'note')
|
|
175
|
+
if (note !== undefined) return note
|
|
163
176
|
return result.stderr
|
|
164
177
|
.trim()
|
|
165
178
|
.split(/\r\n|\n/)
|
|
@@ -341,11 +354,11 @@ function runOverwrite(
|
|
|
341
354
|
runner.target,
|
|
342
355
|
)
|
|
343
356
|
if (runner.offline && written !== undefined && written.status === 1) {
|
|
344
|
-
const note = readString(readJsonObject(written.stdout)
|
|
357
|
+
const note = readString(readJsonObject(written.stdout), 'note')
|
|
345
358
|
if (note !== undefined && note.includes(OFFLINE_REFUSAL)) {
|
|
346
359
|
replaceLastStep(runner, 0, 'offline overwrite skipped the catalog step by design')
|
|
347
360
|
} else {
|
|
348
|
-
replaceLastStep(runner, 1,
|
|
361
|
+
replaceLastStep(runner, 1, describeFailure(written))
|
|
349
362
|
}
|
|
350
363
|
}
|
|
351
364
|
if (!failed(runner)) {
|
|
@@ -78,7 +78,7 @@ so network-controlled descriptions never enter agent instruction context.
|
|
|
78
78
|
| `@orkestrel/reason` | `0.0.12` | L2 | `@orkestrel/emitter` `^0.0.11`, `@orkestrel/contract` `^0.0.18` | |
|
|
79
79
|
| `@orkestrel/relation` | `0.0.14` | L3 | `@orkestrel/emitter` `^0.0.11`, `@orkestrel/contract` `^0.0.18`, `@orkestrel/database` `^0.0.16` | |
|
|
80
80
|
| `@orkestrel/router` | `0.0.16` | L2 | `@orkestrel/abort` `^0.0.12`, `@orkestrel/emitter` `^0.0.11`, `@orkestrel/contract` `^0.0.18` | |
|
|
81
|
-
| `@orkestrel/scaffold` | `0.0.
|
|
81
|
+
| `@orkestrel/scaffold` | `0.0.85` | L3 | `@orkestrel/console` `^0.0.15`, `@orkestrel/emitter` `^0.0.11`, `@orkestrel/process` `^0.0.14`, `@orkestrel/contract` `^0.0.19`, `@orkestrel/markdown` `^0.0.17`, `@orkestrel/template` `^0.0.9` | |
|
|
82
82
|
| `@orkestrel/sea` | `0.0.18` | L3 | `@orkestrel/emitter` `^0.0.11`, `@orkestrel/process` `^0.0.14`, `@orkestrel/contract` `^0.0.18` | |
|
|
83
83
|
| `@orkestrel/server` | `0.0.22` | L3 | `@orkestrel/abort` `^0.0.12`, `@orkestrel/codec` `^0.0.5`, `@orkestrel/router` `^0.0.16`, `@orkestrel/emitter` `^0.0.11`, `@orkestrel/timeout` `^0.0.12`, `@orkestrel/contract` `^0.0.19` | |
|
|
84
84
|
| `@orkestrel/sqlite` | `0.0.13` | L1 | `@orkestrel/contract` `^0.0.18` | |
|
|
@@ -306,6 +306,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
306
306
|
| `blueprintToTestArtifacts` | function | Compiles every artifact in the `tests` group that is not vendored from the host. |
|
|
307
307
|
| `blueprintToWritableScripts` | function | Projects a blueprint into the manifest scripts a region write may replace. |
|
|
308
308
|
| `dependenciesToQuestions` | function | Measures one declared package list against the name and range syntax it accepts. |
|
|
309
|
+
| `insertManifestDependencies` | function | Inserts dependencies a package manifest does not declare into the section each one names. |
|
|
309
310
|
| `overridesToQuestions` | function | Measures a blueprint's overrides against the artifacts drafted for it. |
|
|
310
311
|
| `pathToCondition` | function | Builds one `exports` condition block for a built environment. |
|
|
311
312
|
| `planToFindings` | function | Compares a plan against a target's current content. |
|
|
@@ -539,7 +540,7 @@ option grants a write.
|
|
|
539
540
|
| `audit` | Nothing |
|
|
540
541
|
| `repair` | Each planned path the target is missing or has let drift, and the range and script regions |
|
|
541
542
|
| `catalog` | The package table, the guide mirrors, and the range region |
|
|
542
|
-
| `overwrite` | Everything `repair` and `catalog` write,
|
|
543
|
+
| `overwrite` | Everything `repair` and `catalog` write, deletions, and missing planned dependencies |
|
|
543
544
|
|
|
544
545
|
### Baselines
|
|
545
546
|
|
|
@@ -589,7 +590,7 @@ scaffold <verb> [options]
|
|
|
589
590
|
scaffold catalog [--all] [--from <path>] [--target <path>] [--json]
|
|
590
591
|
regenerate the package table and refresh the guide mirrors
|
|
591
592
|
scaffold overwrite [--groups <list>] [--dirty] [--offline] [--from <path>] [--target <path>] [--json]
|
|
592
|
-
do everything repair and catalog do, then delete what the plan does not own
|
|
593
|
+
do everything repair and catalog do, then delete what the plan does not own, re-declare the dependency ranges, and declare each planned dependency the manifest lacks
|
|
593
594
|
|
|
594
595
|
options
|
|
595
596
|
--src <list> the published library environments to build: core, browser, server
|
|
@@ -802,9 +803,20 @@ live in either section, and how current a declared range is belongs to the regis
|
|
|
802
803
|
Dependency floors describes rather than to this question. A present section that is not an object
|
|
803
804
|
produces a question instead of a crash. This question belongs to `configs` and `tests`. `audit`
|
|
804
805
|
reports it only when its selection includes either group, without changing its exit semantics.
|
|
805
|
-
`repair`
|
|
806
|
-
|
|
807
|
-
|
|
806
|
+
`repair` refuses before writing a selected `configs` or `tests` group, and a selection that
|
|
807
|
+
excludes those groups proceeds: `package.json` is birth-owned, and `repair` rewrites only its range
|
|
808
|
+
and script regions. `overwrite` declares each missing package instead, in the `devDependencies` map
|
|
809
|
+
the plan assigns it, at its planned range, before the first declared key that sorts after it. A
|
|
810
|
+
manifest with no `devDependencies` map gets one: `overwrite` creates it as one top-level key after
|
|
811
|
+
`dependencies`, or last in the manifest object when `dependencies` is absent too, in the indentation
|
|
812
|
+
of the manifest's first key. The declaration lands with the repair, before the catalog step, so a
|
|
813
|
+
partial run keeps it. The JSON result names each declaration in `additions`, and the human report
|
|
814
|
+
prints one `Declared "<name>": "<range>" in devDependencies. Run npm install to install it.` line
|
|
815
|
+
per declaration, because the lockfile does not carry the package until the next install. A
|
|
816
|
+
`devDependencies` value that is not an object, or an entry in that map whose value is not a version
|
|
817
|
+
string, leaves `overwrite` no map to declare in. `overwrite` refuses that manifest before any write,
|
|
818
|
+
whatever `--groups` selects, and names the section or each malformed entry. A malformed section
|
|
819
|
+
refuses `repair` as well.
|
|
808
820
|
|
|
809
821
|
`audit` reports a further non-blocking question, on the `setup` field.
|
|
810
822
|
|
|
@@ -844,6 +856,17 @@ write: a writing verb reports it in the terminal audit it prints, because refusi
|
|
|
844
856
|
gap no write can close would block every write. Run across a fleet, the question is the list of
|
|
845
857
|
packages carrying a filled, exporting setup module that no proof covers.
|
|
846
858
|
|
|
859
|
+
`audit` reports a non-blocking question on the `tests` field for each planned sheet test the target
|
|
860
|
+
holds that imports by a root-relative specifier. A sheet test is birth-owned, so a target born
|
|
861
|
+
before the template imported the built sheet by a relative path keeps the
|
|
862
|
+
`'/dist/src/<name>/index.css?raw'` import, and the content-owned `.oxlintrc.json` refuses it under
|
|
863
|
+
`--deny-warnings` through `import/no-absolute-path`. The message names the file and each
|
|
864
|
+
root-relative specifier beside the relative one to write: one `../` per directory between the file
|
|
865
|
+
and the workspace root, so `tests/src/styles/index.test.ts` writes
|
|
866
|
+
`'../../../dist/src/styles/index.css?raw'`. Scaffold never rewrites the file. The question belongs to
|
|
867
|
+
the `tests` group, and `repair` and `overwrite` report it in their terminal audit without
|
|
868
|
+
refusing a write.
|
|
869
|
+
|
|
847
870
|
`audit` reads the instruction canon as findings rather than as a question. Each `CANON_PATHS` member
|
|
848
871
|
the target holds enters the comparison, by file where the member is a directory, and a path the plan
|
|
849
872
|
does not claim there reports `foreign`. Ownership and drift states that population, and Vendored data
|
|
@@ -886,12 +909,14 @@ standard error, so a piped value is never polluted.
|
|
|
886
909
|
| `audit` | `Audit` — `findings` and `questions` — plus `releases` and `provenance`; findings carry `ownership` |
|
|
887
910
|
| `repair` | `MaterializeResult` plus `audit`, the terminal audit taken after the write, `releases`, and `provenance` |
|
|
888
911
|
| `catalog` | `MaterializeResult` plus `mirrors`, `provenance`, optional `membership` with `entries`, `dropped`, and `releases`, and an explanatory `note` on a partial run |
|
|
889
|
-
| `overwrite` | The `catalog` value plus `audit
|
|
912
|
+
| `overwrite` | The `catalog` value plus `audit`, top-level `releases` from its version read, and `additions`; `note` explains a partial run |
|
|
890
913
|
|
|
891
914
|
The `membership` entity is present only when the catalog read completes. Its `entries` holds the
|
|
892
915
|
package table, `dropped` names packages the preceding table carried that the registry no longer
|
|
893
916
|
lists, and `releases` measures declared fleet ranges against the catalog read. The `overwrite`
|
|
894
|
-
result also retains top-level `releases` from its separate version read, including foreign tools
|
|
917
|
+
result also retains top-level `releases` from its separate version read, including foreign tools,
|
|
918
|
+
and `additions`, the `DependencyPinSet` of planned dependencies it declared, empty when the
|
|
919
|
+
manifest lacked none.
|
|
895
920
|
An absent `membership` identifies an incomplete catalog read; `note` explains the cause.
|
|
896
921
|
|
|
897
922
|
The following JSON excerpt shows the membership evidence in a completed catalog result:
|
package/dist/host/manifest.json
CHANGED
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
"storage": "agents/skills/orkestrel-publish/SKILL.md",
|
|
353
353
|
"destination": ".agents/skills/orkestrel-publish/SKILL.md",
|
|
354
354
|
"executable": false,
|
|
355
|
-
"digest": "
|
|
355
|
+
"digest": "f4bcc24e910bbd40de268ba6a9d4ba57b3e5f9ce69075dea395479a45ec0f9d4"
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
"storage": "agents/skills/orkestrel-publish/agents/openai.yaml",
|
|
@@ -370,7 +370,7 @@
|
|
|
370
370
|
"storage": "agents/skills/orkestrel-publish/references/wave.md",
|
|
371
371
|
"destination": ".agents/skills/orkestrel-publish/references/wave.md",
|
|
372
372
|
"executable": false,
|
|
373
|
-
"digest": "
|
|
373
|
+
"digest": "2d5479e0d3ed0529015f5f1f21345fb389f8119333b6c5530d2320be432fe1e1"
|
|
374
374
|
},
|
|
375
375
|
{
|
|
376
376
|
"storage": "agents/skills/orkestrel-publish/references/window.md",
|
|
@@ -394,7 +394,7 @@
|
|
|
394
394
|
"storage": "agents/skills/orkestrel-publish/scripts/wave.ts",
|
|
395
395
|
"destination": ".agents/skills/orkestrel-publish/scripts/wave.ts",
|
|
396
396
|
"executable": false,
|
|
397
|
-
"digest": "
|
|
397
|
+
"digest": "e7a492aee9f3c63fcb22e3ab6a90f7a1a292a408d1824d75e3de26ea07a3f3e9"
|
|
398
398
|
},
|
|
399
399
|
{
|
|
400
400
|
"storage": "agents/skills/orkestrel-publish/scripts/window.ts",
|
|
@@ -496,7 +496,7 @@
|
|
|
496
496
|
"storage": "claude/agents/orkestrel.md",
|
|
497
497
|
"destination": ".claude/agents/orkestrel.md",
|
|
498
498
|
"executable": false,
|
|
499
|
-
"digest": "
|
|
499
|
+
"digest": "6b3af62e323ff6725680f6a13c3505904154e1d2c0afcb8ba7151a00ff5875c2"
|
|
500
500
|
},
|
|
501
501
|
{
|
|
502
502
|
"storage": "claude/agents/planner.md",
|
|
@@ -1042,7 +1042,7 @@
|
|
|
1042
1042
|
"storage": "guides/scaffold.md",
|
|
1043
1043
|
"destination": "guides/scaffold.md",
|
|
1044
1044
|
"executable": false,
|
|
1045
|
-
"digest": "
|
|
1045
|
+
"digest": "9d6ea9f86610e3237d6ddbe120aabdec137f022092fc5311ca18e87d4b4e6212"
|
|
1046
1046
|
},
|
|
1047
1047
|
{
|
|
1048
1048
|
"storage": "guides/sea.md",
|
|
@@ -2144,5 +2144,5 @@
|
|
|
2144
2144
|
]
|
|
2145
2145
|
}
|
|
2146
2146
|
],
|
|
2147
|
-
"digest": "
|
|
2147
|
+
"digest": "ccbd92a2462e0a17fb972b7582bf05e6deec0c1f11cf4d2d17e6ebec5cc431bf"
|
|
2148
2148
|
}
|
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.86",
|
|
8
8
|
description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
|
|
9
9
|
keywords: [
|
|
10
10
|
"audit",
|
|
@@ -7361,6 +7361,185 @@ function replaceManifestRanges(manifest, pins) {
|
|
|
7361
7361
|
return declaredRuntime && declaredDevelopment ? compiled : void 0;
|
|
7362
7362
|
}
|
|
7363
7363
|
/**
|
|
7364
|
+
* Inserts dependencies a package manifest does not declare into the section each one names.
|
|
7365
|
+
*
|
|
7366
|
+
* @param manifest - The manifest text to compile.
|
|
7367
|
+
* @param additions - The runtime and development names and ranges to declare.
|
|
7368
|
+
* @returns The manifest declaring every addition, or `undefined` when the text is not a
|
|
7369
|
+
* manifest, an addition's section is not an object or holds a value that is not a range, a name
|
|
7370
|
+
* is repeated, or `dependencies` or `devDependencies` already declares a name.
|
|
7371
|
+
*
|
|
7372
|
+
* @remarks
|
|
7373
|
+
* Runtime additions enter `dependencies` and development additions enter `devDependencies`. The
|
|
7374
|
+
* compiler inserts text instead of serializing the manifest, so every declared byte survives.
|
|
7375
|
+
* Each addition lands before the first declared key that sorts after it, or after the last
|
|
7376
|
+
* declared key when none does, so a section kept in key order stays in key order. An addition
|
|
7377
|
+
* copies the indentation of the section's first entry; an empty section takes its entries one
|
|
7378
|
+
* level inside the indentation of its opening line. An absent section is created as one
|
|
7379
|
+
* top-level key holding its additions: `devDependencies` after `dependencies`, `dependencies`
|
|
7380
|
+
* before `devDependencies`, and either one last in the manifest object when its sibling is
|
|
7381
|
+
* absent. The created key copies the indentation of the manifest's first key, and its entries sit
|
|
7382
|
+
* one level further in. A name either writable section already declares is the caller's mistake
|
|
7383
|
+
* rather than an addition, so the compiler refuses it instead of declaring a package twice.
|
|
7384
|
+
*
|
|
7385
|
+
* @example
|
|
7386
|
+
* ```ts
|
|
7387
|
+
* import { insertManifestDependencies } from '@orkestrel/scaffold'
|
|
7388
|
+
*
|
|
7389
|
+
* insertManifestDependencies('{\n\t"devDependencies": {\n\t\t"vite": "^8.3.2"\n\t}\n}\n', {
|
|
7390
|
+
* runtime: [],
|
|
7391
|
+
* development: [{ name: 'typescript', range: '^6.0.3' }],
|
|
7392
|
+
* })
|
|
7393
|
+
* // '{\n\t"devDependencies": {\n\t\t"typescript": "^6.0.3",\n\t\t"vite": "^8.3.2"\n\t}\n}\n'
|
|
7394
|
+
* ```
|
|
7395
|
+
*/
|
|
7396
|
+
function insertManifestDependencies(manifest, additions) {
|
|
7397
|
+
const requested = [...additions.runtime, ...additions.development];
|
|
7398
|
+
if (requested.length === 0) return manifest;
|
|
7399
|
+
const parsed = (0, _orkestrel_contract.parseJSON)(manifest);
|
|
7400
|
+
if (!(0, _orkestrel_contract.isRecord)(parsed)) return void 0;
|
|
7401
|
+
const declared = /* @__PURE__ */ new Set();
|
|
7402
|
+
for (const section of ["dependencies", "devDependencies"]) {
|
|
7403
|
+
const entries = parsed[section];
|
|
7404
|
+
if ((0, _orkestrel_contract.isRecord)(entries)) for (const name of Object.keys(entries)) declared.add(name);
|
|
7405
|
+
}
|
|
7406
|
+
const names = new Set(requested.map(({ name }) => name));
|
|
7407
|
+
if (names.size !== requested.length || [...names].some((name) => declared.has(name))) return;
|
|
7408
|
+
let compiled = manifest;
|
|
7409
|
+
const sections = [{
|
|
7410
|
+
name: "dependencies",
|
|
7411
|
+
dependencies: additions.runtime
|
|
7412
|
+
}, {
|
|
7413
|
+
name: "devDependencies",
|
|
7414
|
+
dependencies: additions.development
|
|
7415
|
+
}];
|
|
7416
|
+
for (const section of sections) {
|
|
7417
|
+
if (section.dependencies.length === 0) continue;
|
|
7418
|
+
const entries = parsed[section.name];
|
|
7419
|
+
if (entries !== void 0 && (!(0, _orkestrel_contract.isRecord)(entries) || !Object.values(entries).every(_orkestrel_contract.isString))) return;
|
|
7420
|
+
const ordered = [...section.dependencies].sort((left, right) => (0, _orkestrel_contract.compareValues)(left.name, right.name));
|
|
7421
|
+
const lines = ordered.map(({ name, range }) => `${JSON.stringify(name)}: ${JSON.stringify(range)}`);
|
|
7422
|
+
const sibling = section.name === "dependencies" ? "devDependencies" : "dependencies";
|
|
7423
|
+
const located = /* @__PURE__ */ new Map();
|
|
7424
|
+
let current;
|
|
7425
|
+
let head = -1;
|
|
7426
|
+
let root = -1;
|
|
7427
|
+
let depth = 0;
|
|
7428
|
+
let cursor = 0;
|
|
7429
|
+
while (cursor < compiled.length && root < 0) {
|
|
7430
|
+
const character = compiled.charAt(cursor);
|
|
7431
|
+
if (character === "\"") {
|
|
7432
|
+
const start = cursor;
|
|
7433
|
+
let quote = cursor + 1;
|
|
7434
|
+
while (quote < compiled.length && compiled.charAt(quote) !== "\"") quote += compiled.charAt(quote) === "\\" ? 2 : 1;
|
|
7435
|
+
if (quote >= compiled.length) return void 0;
|
|
7436
|
+
let colon = quote + 1;
|
|
7437
|
+
while (/\s/u.test(compiled.charAt(colon))) colon += 1;
|
|
7438
|
+
cursor = quote + 1;
|
|
7439
|
+
if (depth !== 1 || compiled.charAt(colon) !== ":") continue;
|
|
7440
|
+
if (head < 0) head = start;
|
|
7441
|
+
const name = (0, _orkestrel_contract.parseJSON)(compiled.slice(start, quote + 1));
|
|
7442
|
+
if (!(0, _orkestrel_contract.isString)(name) || name !== section.name && name !== sibling) continue;
|
|
7443
|
+
if (located.has(name)) continue;
|
|
7444
|
+
let brace = colon + 1;
|
|
7445
|
+
while (/\s/u.test(compiled.charAt(brace))) brace += 1;
|
|
7446
|
+
if (compiled.charAt(brace) !== "{") {
|
|
7447
|
+
if (name === section.name) return void 0;
|
|
7448
|
+
continue;
|
|
7449
|
+
}
|
|
7450
|
+
current = {
|
|
7451
|
+
name,
|
|
7452
|
+
start,
|
|
7453
|
+
open: brace
|
|
7454
|
+
};
|
|
7455
|
+
depth += 1;
|
|
7456
|
+
cursor = brace + 1;
|
|
7457
|
+
continue;
|
|
7458
|
+
}
|
|
7459
|
+
if (character === "{") depth += 1;
|
|
7460
|
+
else if (character === "}") {
|
|
7461
|
+
depth -= 1;
|
|
7462
|
+
if (depth === 1 && current !== void 0) {
|
|
7463
|
+
located.set(current.name, {
|
|
7464
|
+
...current,
|
|
7465
|
+
close: cursor
|
|
7466
|
+
});
|
|
7467
|
+
current = void 0;
|
|
7468
|
+
}
|
|
7469
|
+
if (depth === 0) root = cursor;
|
|
7470
|
+
}
|
|
7471
|
+
cursor += 1;
|
|
7472
|
+
}
|
|
7473
|
+
const bounds = located.get(section.name);
|
|
7474
|
+
if (bounds === void 0) {
|
|
7475
|
+
if (entries !== void 0 || root < 0) return void 0;
|
|
7476
|
+
const breaking = head < 0 ? -1 : compiled.lastIndexOf("\n", head);
|
|
7477
|
+
const margin = breaking < 0 ? "" : compiled.slice(breaking + 1, head);
|
|
7478
|
+
const gap = breaking < 0 || /\S/u.test(margin) ? "" : `\n${margin}`;
|
|
7479
|
+
const block = `${JSON.stringify(section.name)}: {${lines.map((line) => `${gap === "" ? "" : `${gap}${margin}`}${line}`).join(",")}${gap}}`;
|
|
7480
|
+
const neighbor = located.get(sibling);
|
|
7481
|
+
let tail = root - 1;
|
|
7482
|
+
while (tail > 0 && /\s/u.test(compiled.charAt(tail))) tail -= 1;
|
|
7483
|
+
const [position, insertion] = neighbor === void 0 ? [tail + 1, compiled.charAt(tail) === "{" ? block : `,${gap}${block}`] : section.name === "devDependencies" ? [neighbor.close + 1, `,${gap}${block}`] : [neighbor.start, `${block},${gap}`];
|
|
7484
|
+
compiled = compiled.slice(0, position) + insertion + compiled.slice(position);
|
|
7485
|
+
continue;
|
|
7486
|
+
}
|
|
7487
|
+
const { open, close } = bounds;
|
|
7488
|
+
const declarations = [];
|
|
7489
|
+
let key;
|
|
7490
|
+
let scan = open + 1;
|
|
7491
|
+
while (scan < close) {
|
|
7492
|
+
if (compiled.charAt(scan) !== "\"") {
|
|
7493
|
+
scan += 1;
|
|
7494
|
+
continue;
|
|
7495
|
+
}
|
|
7496
|
+
let quote = scan + 1;
|
|
7497
|
+
while (quote < close && compiled.charAt(quote) !== "\"") quote += compiled.charAt(quote) === "\\" ? 2 : 1;
|
|
7498
|
+
if (quote >= close) return void 0;
|
|
7499
|
+
if (key === void 0) {
|
|
7500
|
+
const name = (0, _orkestrel_contract.parseJSON)(compiled.slice(scan, quote + 1));
|
|
7501
|
+
if (!(0, _orkestrel_contract.isString)(name)) return void 0;
|
|
7502
|
+
key = {
|
|
7503
|
+
name,
|
|
7504
|
+
start: scan
|
|
7505
|
+
};
|
|
7506
|
+
} else {
|
|
7507
|
+
declarations.push({
|
|
7508
|
+
...key,
|
|
7509
|
+
end: quote + 1
|
|
7510
|
+
});
|
|
7511
|
+
key = void 0;
|
|
7512
|
+
}
|
|
7513
|
+
scan = quote + 1;
|
|
7514
|
+
}
|
|
7515
|
+
const first = declarations[0];
|
|
7516
|
+
const last = declarations.at(-1);
|
|
7517
|
+
const edits = /* @__PURE__ */ new Map();
|
|
7518
|
+
if (first === void 0 || last === void 0) {
|
|
7519
|
+
const opening = compiled.lastIndexOf("\n", open);
|
|
7520
|
+
let column = opening + 1;
|
|
7521
|
+
while (column < open && /\s/u.test(compiled.charAt(column))) column += 1;
|
|
7522
|
+
const level = opening < 0 ? "" : compiled.slice(opening + 1, column);
|
|
7523
|
+
const separator = opening < 0 ? "" : `\n${level}${level}`;
|
|
7524
|
+
const ending = opening < 0 ? "" : `\n${level}`;
|
|
7525
|
+
compiled = `${compiled.slice(0, open + 1)}${lines.map((line) => `${separator}${line}`).join(",")}${ending}${compiled.slice(close)}`;
|
|
7526
|
+
continue;
|
|
7527
|
+
}
|
|
7528
|
+
const newline = compiled.lastIndexOf("\n", first.start);
|
|
7529
|
+
const indent = newline < 0 ? "" : compiled.slice(newline + 1, first.start);
|
|
7530
|
+
const separator = newline < 0 || /\S/u.test(indent) ? "" : `\n${indent}`;
|
|
7531
|
+
for (const [index, dependency] of ordered.entries()) {
|
|
7532
|
+
const line = lines[index] ?? "";
|
|
7533
|
+
const anchor = declarations.find((declaration) => (0, _orkestrel_contract.compareValues)(declaration.name, dependency.name) > 0);
|
|
7534
|
+
const position = anchor?.start ?? last.end;
|
|
7535
|
+
const text = anchor === void 0 ? `,${separator}${line}` : `${line},${separator}`;
|
|
7536
|
+
edits.set(position, `${edits.get(position) ?? ""}${text}`);
|
|
7537
|
+
}
|
|
7538
|
+
for (const [position, text] of [...edits].sort(([left], [right]) => right - left)) compiled = compiled.slice(0, position) + text + compiled.slice(position);
|
|
7539
|
+
}
|
|
7540
|
+
return compiled;
|
|
7541
|
+
}
|
|
7542
|
+
/**
|
|
7364
7543
|
* Replaces named script values in package manifest text.
|
|
7365
7544
|
*
|
|
7366
7545
|
* @param manifest - The manifest text to compile.
|
|
@@ -8570,6 +8749,7 @@ exports.extractRangeMajor = extractRangeMajor;
|
|
|
8570
8749
|
exports.extractVersion = extractVersion;
|
|
8571
8750
|
exports.inferDrift = inferDrift;
|
|
8572
8751
|
exports.inferGroup = inferGroup;
|
|
8752
|
+
exports.insertManifestDependencies = insertManifestDependencies;
|
|
8573
8753
|
exports.isArtifact = isArtifact;
|
|
8574
8754
|
exports.isAudit = isAudit;
|
|
8575
8755
|
exports.isBlueprint = isBlueprint;
|