@vertekum/schema-builder 0.2.1 → 0.3.1
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/CHANGELOG.md +6 -5
- package/docs/modules.md +2 -2
- package/package.json +4 -4
- package/src/build.ts +33 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# @vertekum/schema-builder
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.3.1
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- [`7f9db48`](https://github.com/moros-oxus/vertekum/commit/7f9db48344c672b90a97f3f4608bf7de893799bf) Thanks [@tschemmer](https://github.com/tschemmer)! - `<@name>` resolution gains key precedence: an import keyed `name` wins outright — its root, else its own `name` production — so sibling imports' public productions can no longer shadow or collide with a keyed module. The cross-import production search remains as the fallback when no key matches.
|
|
7
8
|
- Updated dependencies []:
|
|
8
|
-
- @vertekum/core@0.
|
|
9
|
+
- @vertekum/core@0.3.1
|
|
9
10
|
|
|
10
|
-
## 0.
|
|
11
|
+
## 0.3.0
|
|
11
12
|
|
|
12
13
|
### Minor Changes
|
|
13
14
|
|
|
@@ -26,8 +27,8 @@
|
|
|
26
27
|
- [`ef1ca4a`](https://github.com/moros-oxus/vertekum/commit/ef1ca4a0b696b799275c0f0acf7fde9414793f8d) Thanks [@tschemmer](https://github.com/tschemmer)! - Pick/omit lists take references as members — set algebra with sets as operands: `<@fullcolors ![<@fullcolors/saturated>, white]>` omits every saturated name plus white. Operands resolve with normal scope and privacy rules, keep member-by-member validation, and an open member reference is refused.
|
|
27
28
|
|
|
28
29
|
- [`1de5e76`](https://github.com/moros-oxus/vertekum/commit/1de5e76929f9a1e17e6625cb3bfd36a3fd86ceec) Thanks [@tschemmer](https://github.com/tschemmer)! - The input/output pair is configurable on the extension — `schemaBuilderExtension({ source: './src/dfn', out: './src/schemas' })`. `source` becomes the default sweep for `schema build`, `lint`, and `fmt`; `out` redirects built schemas, mirroring `source`'s directory structure. `schema build` also takes a positional `[out]` for one invocation: a directory argument mirrors into it, a file argument lands directly in it.
|
|
29
|
-
- Updated dependencies [[`84172d2`](https://github.com/moros-oxus/vertekum/commit/84172d2ca90320b60ec4c42730a69c056631a81c)
|
|
30
|
-
- @vertekum/core@0.
|
|
30
|
+
- Updated dependencies [[`84172d2`](https://github.com/moros-oxus/vertekum/commit/84172d2ca90320b60ec4c42730a69c056631a81c)]:
|
|
31
|
+
- @vertekum/core@0.3.0
|
|
31
32
|
|
|
32
33
|
## 0.1.7
|
|
33
34
|
|
package/docs/modules.md
CHANGED
|
@@ -38,8 +38,8 @@ use "./system/color.dfn" as system-color
|
|
|
38
38
|
|
|
39
39
|
| Reference | Means |
|
|
40
40
|
| -------------------- | ---------------------------------------------------------------------------- |
|
|
41
|
-
| `<@key>` |
|
|
42
|
-
| `<@name>` | the production `name`, searched across every import; unambiguous or an error. |
|
|
41
|
+
| `<@key>` | an import KEYED `key` **wins outright**: its root — else its own `key` production (the fragment idiom) — sibling imports' productions can never shadow or collide with it. |
|
|
42
|
+
| `<@name>` | no key matches: the production `name`, searched across every import; unambiguous or an error. |
|
|
43
43
|
| `<@key/name>` | qualified: that import's production alone — the collision resolver. |
|
|
44
44
|
|
|
45
45
|
When two imports both declare `<accent>`, the unqualified `<@accent>` refuses with the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertekum/schema-builder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Declare token vocabularies as grammar; build them into JSON Schema files",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"./cli": "./src/cli.ts"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@vertekum/core": "0.
|
|
40
|
+
"@vertekum/core": "0.3.1"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"zod": "^3.25.76"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@vertekum/core": "0.
|
|
47
|
-
"@vertekum/schema-vocabulary": "0.
|
|
46
|
+
"@vertekum/core": "0.3.1",
|
|
47
|
+
"@vertekum/schema-vocabulary": "0.3.0"
|
|
48
48
|
}
|
|
49
49
|
}
|
package/src/build.ts
CHANGED
|
@@ -125,41 +125,51 @@ function target(
|
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
// 1. A module KEY match wins outright — a keyed module cannot be shadowed by (or
|
|
129
|
+
// collide with) sibling imports' productions. Its root; else its OWN production of
|
|
130
|
+
// the same name (the fragment-declares-its-own-name idiom); else the fragment hint.
|
|
131
|
+
const keyed = scope.module.imports.get(ref.name);
|
|
132
|
+
if (keyed) {
|
|
133
|
+
const keyedScope: Scope = {
|
|
134
|
+
module: keyed,
|
|
135
|
+
expanding: new Set(),
|
|
136
|
+
warn: scope.warn,
|
|
137
|
+
};
|
|
138
|
+
if (keyed.module.root) {
|
|
139
|
+
return {
|
|
140
|
+
node: keyed.module.root,
|
|
141
|
+
scope: keyedScope,
|
|
142
|
+
importedRoot: keyed,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const own = keyed.module.productions.get(ref.name);
|
|
146
|
+
if (own && !keyed.module.private.has(ref.name)) {
|
|
147
|
+
return { node: own, scope: keyedScope };
|
|
148
|
+
}
|
|
149
|
+
throw new DfnError(
|
|
150
|
+
`'${ref.name}' is imported, but it declares no root (a fragment) — reference one of its productions: ${productionsOf(ref.name, keyed)}`,
|
|
151
|
+
ref.line,
|
|
152
|
+
ref.column,
|
|
153
|
+
file,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 2. No key match: the production searched across every import — unambiguous or say so.
|
|
128
158
|
const hits: Array<{
|
|
129
159
|
node: Node;
|
|
130
160
|
scope: Scope;
|
|
131
161
|
importedRoot?: ResolvedModule;
|
|
132
162
|
}> = [];
|
|
133
|
-
for (const
|
|
134
|
-
const importedScope: Scope = {
|
|
135
|
-
module: imported,
|
|
136
|
-
expanding: new Set(),
|
|
137
|
-
warn: scope.warn,
|
|
138
|
-
};
|
|
163
|
+
for (const imported of scope.module.imports.values()) {
|
|
139
164
|
const production = imported.module.productions.get(ref.name);
|
|
140
165
|
if (production && !imported.module.private.has(ref.name)) {
|
|
141
|
-
hits.push({ node: production, scope: importedScope });
|
|
142
|
-
}
|
|
143
|
-
if (key === ref.name && imported.module.root) {
|
|
144
166
|
hits.push({
|
|
145
|
-
node:
|
|
146
|
-
scope:
|
|
147
|
-
importedRoot: imported,
|
|
167
|
+
node: production,
|
|
168
|
+
scope: { module: imported, expanding: new Set(), warn: scope.warn },
|
|
148
169
|
});
|
|
149
170
|
}
|
|
150
171
|
}
|
|
151
172
|
if (hits.length === 0) {
|
|
152
|
-
// The near-miss that reads as a missing `use`: the import EXISTS under this key, but
|
|
153
|
-
// `<@key>` means its root and a fragment has none. Say so, and name the real forms.
|
|
154
|
-
const fragment = scope.module.imports.get(ref.name);
|
|
155
|
-
if (fragment) {
|
|
156
|
-
throw new DfnError(
|
|
157
|
-
`'${ref.name}' is imported, but it declares no root (a fragment) — reference one of its productions: ${productionsOf(ref.name, fragment)}`,
|
|
158
|
-
ref.line,
|
|
159
|
-
ref.column,
|
|
160
|
-
file,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
173
|
throw new DfnError(
|
|
164
174
|
`no import provides '<@${ref.name}>'`,
|
|
165
175
|
ref.line,
|