@orkestrel/scaffold 0.0.41 → 0.0.42
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/host/guides/scaffold.md +10 -3
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +0 -0
- package/dist/host/tests/config.test.ts +27 -5
- package/dist/src/core/index.cjs +29 -16
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +34 -20
- package/dist/src/core/index.d.ts +34 -20
- package/dist/src/core/index.js +28 -16
- package/dist/src/core/index.js.map +1 -1
- package/package.json +7 -7
|
@@ -102,8 +102,9 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
102
102
|
| `ENGINES_PATTERN` | const | The minimum-Node engine syntax a blueprint declares. |
|
|
103
103
|
| `ENVIRONMENTS` | const | The three `Environment` values, frozen. |
|
|
104
104
|
| `EXECUTABLE_PATHS` | const | The vendored paths a target receives with its executable bit set, frozen. |
|
|
105
|
-
| `EXTRA_NAME_PATTERN` | const | The development extra name syntax: any valid npm package name. |
|
|
106
105
|
| `EXTRA_RANGE_PATTERN` | const | The registry-only semver subset accepted for a development extra's range. |
|
|
106
|
+
| `FLOOR_RANGE_PATTERN` | const | The exact three-component floor accepted for a foreign peer's range. |
|
|
107
|
+
| `FOREIGN_NAME_PATTERN` | const | The package name syntax for a dependency this package does not publish. |
|
|
107
108
|
| `GLOBAL_SETUP_PATH` | const | The shared Vitest global-setup module whose presence makes a workspace `global`. |
|
|
108
109
|
| `GROUPS` | const | The seven `Group` values in plan order, frozen. |
|
|
109
110
|
| `GUIDES_TEST_PATH` | const | The guide-parity proof whose presence selects the planned `guides` project. |
|
|
@@ -587,8 +588,14 @@ blueprint.engines // '>=22.12.0'
|
|
|
587
588
|
|
|
588
589
|
`src` selects published library environments and `app` selects private application environments.
|
|
589
590
|
The two axes are independent, so a library-only, an application-only, and a mixed workspace are all
|
|
590
|
-
first class. `dependencies`
|
|
591
|
-
development dependencies and may carry any
|
|
591
|
+
first class. `dependencies` are runtime `@orkestrel/*` packages. A peer in the `@orkestrel` scope is
|
|
592
|
+
a fleet pin; every other peer is a floor. `extras` are development dependencies and may carry any
|
|
593
|
+
valid npm name. A peer reaches the generated workspace through two representations:
|
|
594
|
+
`Blueprint.peers` validates the scope rule and compiles the manifest declarations, while the
|
|
595
|
+
`peers` binding in the generated `vite.config.ts` derives from the target's live
|
|
596
|
+
`peerDependencies`. Each published build face — core, browser, server, and `bin` — externalizes
|
|
597
|
+
every name in that binding, so a peer the workspace declares by hand, such as `vitest`, is left as
|
|
598
|
+
an import in the emitted bundle rather than inlined into it.
|
|
592
599
|
|
|
593
600
|
One published environment owns the package root directly. Several published environments require
|
|
594
601
|
`core`, which owns that root while each other environment keeps its subpath. A multi-environment
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
rmSync,
|
|
13
13
|
writeFileSync,
|
|
14
14
|
} from 'node:fs'
|
|
15
|
+
import { createRequire } from 'node:module'
|
|
15
16
|
import { dirname, join, resolve } from 'node:path'
|
|
16
17
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
17
18
|
import { build, loadConfigFromFile } from 'vite'
|
|
@@ -588,16 +589,37 @@ describe('policy plugin', () => {
|
|
|
588
589
|
].join('\n'),
|
|
589
590
|
)
|
|
590
591
|
|
|
591
|
-
|
|
592
|
+
// Run oxlint's real Node entry through the current interpreter rather than the
|
|
593
|
+
// `node_modules/.bin/oxlint` shim. That shim is a POSIX `sh` script — a symlink to one on
|
|
594
|
+
// Linux, a `.cmd`/`.ps1` pair on Windows — and Windows `CreateProcess` cannot execute the
|
|
595
|
+
// extensionless form; spawning the `.cmd` would need `shell: true`, which breaks on paths
|
|
596
|
+
// containing spaces. Resolving through `createRequire` reads oxlint's own `bin` field, so
|
|
597
|
+
// the entry survives hoisting, a nested `node_modules` layout, and a future rename.
|
|
598
|
+
const manifestPath = createRequire(join(root, 'package.json')).resolve('oxlint/package.json')
|
|
599
|
+
const manifest: unknown = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
|
600
|
+
if (typeof manifest !== 'object' || manifest === null) {
|
|
601
|
+
throw new Error('The oxlint package manifest is not an object')
|
|
602
|
+
}
|
|
603
|
+
const bin: unknown = Object.getOwnPropertyDescriptor(manifest, 'bin')?.value
|
|
604
|
+
const entry: unknown =
|
|
605
|
+
typeof bin === 'string'
|
|
606
|
+
? bin
|
|
607
|
+
: typeof bin === 'object' && bin !== null
|
|
608
|
+
? Object.getOwnPropertyDescriptor(bin, 'oxlint')?.value
|
|
609
|
+
: undefined
|
|
610
|
+
if (typeof entry !== 'string') {
|
|
611
|
+
throw new Error('The oxlint package declares no bin.oxlint entry')
|
|
612
|
+
}
|
|
613
|
+
const binary = resolve(dirname(manifestPath), entry)
|
|
592
614
|
const config = resolve(root, '.oxlintrc.json')
|
|
593
615
|
const violations = spawnSync(
|
|
594
|
-
|
|
595
|
-
['--config', config, '--format', 'json', resolve(scratch.path, 'violations')],
|
|
616
|
+
process.execPath,
|
|
617
|
+
[binary, '--config', config, '--format', 'json', resolve(scratch.path, 'violations')],
|
|
596
618
|
{ cwd: root, encoding: 'utf8', timeout: 15_000 },
|
|
597
619
|
)
|
|
598
620
|
const clean = spawnSync(
|
|
599
|
-
|
|
600
|
-
['--config', config, '--format', 'json', resolve(scratch.path, 'clean')],
|
|
621
|
+
process.execPath,
|
|
622
|
+
[binary, '--config', config, '--format', 'json', resolve(scratch.path, 'clean')],
|
|
601
623
|
{ cwd: root, encoding: 'utf8', timeout: 15_000 },
|
|
602
624
|
)
|
|
603
625
|
const reports: string[][] = []
|
package/dist/src/core/index.cjs
CHANGED
|
@@ -235,16 +235,16 @@ var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
|
235
235
|
*/
|
|
236
236
|
var DEPENDENCY_NAME_PATTERN = /^@orkestrel\/[a-z][a-z0-9-]*$/;
|
|
237
237
|
/**
|
|
238
|
-
* The
|
|
238
|
+
* The package name syntax for a dependency this package does not publish.
|
|
239
239
|
*
|
|
240
240
|
* @remarks
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
241
|
+
* A foreign package is one this package does not publish, so its name reaches
|
|
242
|
+
* no path. It may carry any scope or no scope at all. Each name segment begins
|
|
243
|
+
* with an alphanumeric character after an optional leading `@`, and the name
|
|
244
|
+
* carries at most one `/`. No segment can therefore be `..`, and no backslash
|
|
245
|
+
* is admitted, so the shape cannot express a traversal.
|
|
246
246
|
*/
|
|
247
|
-
var
|
|
247
|
+
var FOREIGN_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
248
248
|
/** The exact three-component version syntax a blueprint declares. */
|
|
249
249
|
var VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
250
250
|
/**
|
|
@@ -259,6 +259,15 @@ var VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
|
259
259
|
var ORKESTREL_RANGE_PATTERN = /^\^0\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
260
260
|
/** The registry-only semver subset accepted for a development extra's range. */
|
|
261
261
|
var EXTRA_RANGE_PATTERN = /^(?:\^|~)?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?$/;
|
|
262
|
+
/**
|
|
263
|
+
* The exact three-component floor accepted for a foreign peer's range.
|
|
264
|
+
*
|
|
265
|
+
* @remarks
|
|
266
|
+
* This is independent from {@link ENGINES_PATTERN}. An engine floors the Node
|
|
267
|
+
* runtime a workspace supports, while a peer floors a tool the consumer
|
|
268
|
+
* supplies. Either obligation may change without changing the other.
|
|
269
|
+
*/
|
|
270
|
+
var FLOOR_RANGE_PATTERN = /^>=(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
262
271
|
/** The minimum-Node engine syntax a blueprint declares. */
|
|
263
272
|
var ENGINES_PATTERN = /^>=(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
|
|
264
273
|
/** Exact lowercase hexadecimal bytes: two digits per byte, and empty content is valid. */
|
|
@@ -3017,7 +3026,10 @@ function srcToExports(src) {
|
|
|
3017
3026
|
* each declared axis adds the set its host needs. A declared extra or peer is
|
|
3018
3027
|
* applied after those, so a workspace that pins a range for a package the
|
|
3019
3028
|
* conditional sets also name gets the range it declared. An extra that restates
|
|
3020
|
-
* a shared toolchain pin never reaches here, because the gate refuses it.
|
|
3029
|
+
* a shared toolchain pin never reaches here, because the gate refuses it. A peer
|
|
3030
|
+
* that names a development tool already selected keeps that tool's pin, because
|
|
3031
|
+
* the peer's floor states what consumers may supply rather than what this workspace
|
|
3032
|
+
* develops against.
|
|
3021
3033
|
*
|
|
3022
3034
|
* A peer is declared here as well as under `peerDependencies`, because a peer is
|
|
3023
3035
|
* not installed by the workspace that declares it and developing against one
|
|
@@ -3050,7 +3062,7 @@ function blueprintToDevDependencies(blueprint) {
|
|
|
3050
3062
|
...blueprint.app.includes("server") ? APP_SERVER_DEV_DEPENDENCIES : {}
|
|
3051
3063
|
};
|
|
3052
3064
|
for (const extra of blueprint.extras) merged[extra.name] = extra.range;
|
|
3053
|
-
for (const peer of blueprint.peers) merged[peer.name] = peer.range;
|
|
3065
|
+
for (const peer of blueprint.peers) if (!Object.hasOwn(merged, peer.name)) merged[peer.name] = peer.range;
|
|
3054
3066
|
const own = blueprint.src.length > 0 ? `@orkestrel/${blueprint.name}` : blueprint.name;
|
|
3055
3067
|
const runtime = new Set(blueprint.dependencies.map((dependency) => dependency.name));
|
|
3056
3068
|
return Object.fromEntries(Object.entries(merged).filter(([name]) => name !== own && !runtime.has(name)).sort(([left], [right]) => (0, _orkestrel_contract.compareValues)(left, right)));
|
|
@@ -4139,11 +4151,11 @@ function planToFindings(plan, current) {
|
|
|
4139
4151
|
* range, in list order.
|
|
4140
4152
|
*
|
|
4141
4153
|
* @remarks
|
|
4142
|
-
* The
|
|
4143
|
-
* rules live here once and each caller supplies its own patterns.
|
|
4144
|
-
* dependency name reaches a path through its guide mirror and is
|
|
4145
|
-
* `@orkestrel` scope
|
|
4146
|
-
* valid npm name.
|
|
4154
|
+
* The declared lists and peer partitions differ only in the two syntaxes they
|
|
4155
|
+
* accept, so the rules live here once and each caller supplies its own patterns.
|
|
4156
|
+
* A runtime dependency name reaches a path through its guide mirror and is
|
|
4157
|
+
* fixed to the `@orkestrel` scope. A foreign peer or development extra reaches
|
|
4158
|
+
* no path and admits any valid npm name.
|
|
4147
4159
|
*
|
|
4148
4160
|
* Both patterns must be stateless. A global or sticky pattern carries a
|
|
4149
4161
|
* `lastIndex` between calls, so it would answer differently for the same input
|
|
@@ -4301,7 +4313,7 @@ function blueprintToQuestions(blueprint) {
|
|
|
4301
4313
|
message: "showcase projects a browser app, and this workspace declares none, so it emits nothing.",
|
|
4302
4314
|
blocking: false
|
|
4303
4315
|
});
|
|
4304
|
-
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",
|
|
4316
|
+
questions.push(...dependenciesToQuestions(blueprint.dependencies, "dependencies", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers.filter((peer) => peer.name.startsWith("@orkestrel/")), "peers", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers.filter((peer) => !peer.name.startsWith("@orkestrel/")), "peers", FOREIGN_NAME_PATTERN, FLOOR_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.extras, "extras", FOREIGN_NAME_PATTERN, EXTRA_RANGE_PATTERN));
|
|
4305
4317
|
const lists = [
|
|
4306
4318
|
["dependencies", blueprint.dependencies],
|
|
4307
4319
|
["peers", blueprint.peers],
|
|
@@ -4857,8 +4869,9 @@ exports.DISTRIBUTION_TEST_PATH = DISTRIBUTION_TEST_PATH;
|
|
|
4857
4869
|
exports.ENGINES_PATTERN = ENGINES_PATTERN;
|
|
4858
4870
|
exports.ENVIRONMENTS = ENVIRONMENTS;
|
|
4859
4871
|
exports.EXECUTABLE_PATHS = EXECUTABLE_PATHS;
|
|
4860
|
-
exports.EXTRA_NAME_PATTERN = EXTRA_NAME_PATTERN;
|
|
4861
4872
|
exports.EXTRA_RANGE_PATTERN = EXTRA_RANGE_PATTERN;
|
|
4873
|
+
exports.FLOOR_RANGE_PATTERN = FLOOR_RANGE_PATTERN;
|
|
4874
|
+
exports.FOREIGN_NAME_PATTERN = FOREIGN_NAME_PATTERN;
|
|
4862
4875
|
exports.GLOBAL_SETUP_PATH = GLOBAL_SETUP_PATH;
|
|
4863
4876
|
exports.GROUPS = GROUPS;
|
|
4864
4877
|
exports.GUIDES_TEST_PATH = GUIDES_TEST_PATH;
|