@esmx/core 3.0.0-rc.117 → 3.0.0-rc.118
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 +17 -3
- package/README.zh-CN.md +20 -6
- package/dist/app.mjs +4 -2
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.mjs +28 -1
- package/dist/cli/validate.d.ts +15 -0
- package/dist/cli/validate.mjs +139 -0
- package/dist/cli/validate.test.d.ts +1 -0
- package/dist/cli/validate.test.mjs +216 -0
- package/dist/core.d.ts +31 -0
- package/dist/core.mjs +71 -5
- package/dist/declaration/index.d.ts +47 -0
- package/dist/declaration/index.mjs +63 -0
- package/dist/declaration/index.test.d.ts +1 -0
- package/dist/declaration/index.test.mjs +202 -0
- package/dist/declaration/lower.d.ts +11 -0
- package/dist/declaration/lower.mjs +78 -0
- package/dist/declaration/lower.test.d.ts +1 -0
- package/dist/declaration/lower.test.mjs +333 -0
- package/dist/declaration/reader.d.ts +28 -0
- package/dist/declaration/reader.mjs +55 -0
- package/dist/declaration/reinit.e2e.test.d.ts +1 -0
- package/dist/declaration/reinit.e2e.test.mjs +117 -0
- package/dist/declaration/resolver.d.ts +59 -0
- package/dist/declaration/resolver.mjs +430 -0
- package/dist/declaration/resolver.test.d.ts +1 -0
- package/dist/declaration/resolver.test.mjs +1005 -0
- package/dist/declaration/schema.d.ts +89 -0
- package/dist/declaration/schema.mjs +282 -0
- package/dist/declaration/schema.test.d.ts +1 -0
- package/dist/declaration/schema.test.mjs +101 -0
- package/dist/declaration/semver.d.ts +22 -0
- package/dist/declaration/semver.mjs +229 -0
- package/dist/declaration/semver.test.d.ts +1 -0
- package/dist/declaration/semver.test.mjs +87 -0
- package/dist/declaration/test-fixtures.d.ts +18 -0
- package/dist/declaration/test-fixtures.mjs +69 -0
- package/dist/declaration/types.d.ts +58 -0
- package/dist/declaration/types.mjs +21 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.mjs +10 -0
- package/dist/manifest-json.d.ts +61 -0
- package/dist/manifest-json.mjs +68 -5
- package/dist/manifest-json.test.d.ts +1 -0
- package/dist/manifest-json.test.mjs +196 -0
- package/dist/module-config.d.ts +45 -5
- package/dist/module-config.mjs +60 -49
- package/dist/module-config.test.mjs +227 -91
- package/dist/pack-config.d.ts +2 -9
- package/dist/render-context.mjs +22 -5
- package/dist/utils/import-map.d.ts +23 -3
- package/dist/utils/import-map.mjs +38 -1
- package/dist/utils/import-map.test.mjs +228 -0
- package/package.json +9 -6
- package/src/app.ts +5 -2
- package/src/cli/cli.ts +44 -1
- package/src/cli/validate.test.ts +251 -0
- package/src/cli/validate.ts +196 -0
- package/src/core.ts +84 -5
- package/src/declaration/index.test.ts +223 -0
- package/src/declaration/index.ts +135 -0
- package/src/declaration/lower.test.ts +372 -0
- package/src/declaration/lower.ts +135 -0
- package/src/declaration/reader.ts +93 -0
- package/src/declaration/reinit.e2e.test.ts +148 -0
- package/src/declaration/resolver.test.ts +1111 -0
- package/src/declaration/resolver.ts +638 -0
- package/src/declaration/schema.test.ts +118 -0
- package/src/declaration/schema.ts +339 -0
- package/src/declaration/semver.test.ts +101 -0
- package/src/declaration/semver.ts +278 -0
- package/src/declaration/test-fixtures.ts +96 -0
- package/src/declaration/types.ts +71 -0
- package/src/index.ts +28 -1
- package/src/manifest-json.test.ts +236 -0
- package/src/manifest-json.ts +166 -5
- package/src/module-config.test.ts +266 -105
- package/src/module-config.ts +130 -58
- package/src/pack-config.ts +2 -9
- package/src/render-context.ts +34 -6
- package/src/utils/import-map.test.ts +261 -0
- package/src/utils/import-map.ts +92 -6
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal semver-range satisfaction used by the declaration resolver.
|
|
3
|
+
*
|
|
4
|
+
* Supports the subset the RFC validation needs: exact versions, `^`, `~`,
|
|
5
|
+
* comparators (`>=`, `>`, `<=`, `<`, `=`), `*`, x-ranges (`1.x`, `1.2.x`,
|
|
6
|
+
* `1`, `1.2`), space-separated AND clauses and `||` OR clauses. Anything
|
|
7
|
+
* else (workspace:, file:, link:, npm aliases, hyphen ranges) is reported
|
|
8
|
+
* as unparsable so callers can skip the gate per RFC §11.
|
|
9
|
+
*/
|
|
10
|
+
export interface SemverVersion {
|
|
11
|
+
major: number;
|
|
12
|
+
minor: number;
|
|
13
|
+
patch: number;
|
|
14
|
+
prerelease: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const VERSION_RE =
|
|
18
|
+
/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
19
|
+
|
|
20
|
+
export function parseSemver(input: string): SemverVersion | null {
|
|
21
|
+
const match = VERSION_RE.exec(input.trim());
|
|
22
|
+
if (!match) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
major: Number(match[1]),
|
|
27
|
+
minor: Number(match[2]),
|
|
28
|
+
patch: Number(match[3]),
|
|
29
|
+
prerelease: match[4] ? match[4].split('.') : []
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function comparePrerelease(a: string[], b: string[]): number {
|
|
34
|
+
if (a.length === 0 && b.length === 0) {
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
// A version without prerelease is greater than the same triple with one.
|
|
38
|
+
if (a.length === 0) {
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
if (b.length === 0) {
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
44
|
+
const length = Math.max(a.length, b.length);
|
|
45
|
+
for (let i = 0; i < length; i++) {
|
|
46
|
+
const idA = a[i];
|
|
47
|
+
const idB = b[i];
|
|
48
|
+
if (idA === undefined) {
|
|
49
|
+
return -1;
|
|
50
|
+
}
|
|
51
|
+
if (idB === undefined) {
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
const numA = /^\d+$/.test(idA) ? Number(idA) : null;
|
|
55
|
+
const numB = /^\d+$/.test(idB) ? Number(idB) : null;
|
|
56
|
+
if (numA !== null && numB !== null) {
|
|
57
|
+
if (numA !== numB) {
|
|
58
|
+
return numA < numB ? -1 : 1;
|
|
59
|
+
}
|
|
60
|
+
} else if (numA !== null) {
|
|
61
|
+
// Numeric identifiers sort before alphanumeric ones.
|
|
62
|
+
return -1;
|
|
63
|
+
} else if (numB !== null) {
|
|
64
|
+
return 1;
|
|
65
|
+
} else if (idA !== idB) {
|
|
66
|
+
return idA < idB ? -1 : 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function compareSemver(a: SemverVersion, b: SemverVersion): number {
|
|
73
|
+
if (a.major !== b.major) {
|
|
74
|
+
return a.major < b.major ? -1 : 1;
|
|
75
|
+
}
|
|
76
|
+
if (a.minor !== b.minor) {
|
|
77
|
+
return a.minor < b.minor ? -1 : 1;
|
|
78
|
+
}
|
|
79
|
+
if (a.patch !== b.patch) {
|
|
80
|
+
return a.patch < b.patch ? -1 : 1;
|
|
81
|
+
}
|
|
82
|
+
return comparePrerelease(a.prerelease, b.prerelease);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface PartialVersion {
|
|
86
|
+
major: number | null;
|
|
87
|
+
minor: number | null;
|
|
88
|
+
patch: number | null;
|
|
89
|
+
prerelease: string[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function parsePartial(input: string): PartialVersion | null {
|
|
93
|
+
const trimmed = input.trim().replace(/^v/, '');
|
|
94
|
+
if (trimmed === '' || trimmed === '*' || /^x$/i.test(trimmed)) {
|
|
95
|
+
return { major: null, minor: null, patch: null, prerelease: [] };
|
|
96
|
+
}
|
|
97
|
+
const exact = parseSemver(trimmed);
|
|
98
|
+
if (exact) {
|
|
99
|
+
return exact;
|
|
100
|
+
}
|
|
101
|
+
const segments = trimmed.split('.');
|
|
102
|
+
if (segments.length > 3) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const parsed: Array<number | null> = [];
|
|
106
|
+
for (const segment of segments) {
|
|
107
|
+
if (segment === '*' || /^x$/i.test(segment)) {
|
|
108
|
+
parsed.push(null);
|
|
109
|
+
} else if (/^\d+$/.test(segment)) {
|
|
110
|
+
parsed.push(Number(segment));
|
|
111
|
+
} else {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
major: parsed[0] ?? null,
|
|
117
|
+
minor: parsed[1] ?? null,
|
|
118
|
+
patch: parsed[2] ?? null,
|
|
119
|
+
prerelease: []
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function lowerBound(partial: PartialVersion): SemverVersion {
|
|
124
|
+
return {
|
|
125
|
+
major: partial.major ?? 0,
|
|
126
|
+
minor: partial.minor ?? 0,
|
|
127
|
+
patch: partial.patch ?? 0,
|
|
128
|
+
prerelease: partial.prerelease
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Exclusive upper bound for an x-range, or null when unbounded. */
|
|
133
|
+
function xRangeUpperBound(partial: PartialVersion): SemverVersion | null {
|
|
134
|
+
if (partial.major === null) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if (partial.minor === null) {
|
|
138
|
+
return { major: partial.major + 1, minor: 0, patch: 0, prerelease: [] };
|
|
139
|
+
}
|
|
140
|
+
if (partial.patch === null) {
|
|
141
|
+
return {
|
|
142
|
+
major: partial.major,
|
|
143
|
+
minor: partial.minor + 1,
|
|
144
|
+
patch: 0,
|
|
145
|
+
prerelease: []
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function caretUpperBound(partial: PartialVersion): SemverVersion | null {
|
|
152
|
+
if (partial.major === null) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
if (partial.major > 0) {
|
|
156
|
+
return { major: partial.major + 1, minor: 0, patch: 0, prerelease: [] };
|
|
157
|
+
}
|
|
158
|
+
if (partial.minor === null) {
|
|
159
|
+
return { major: 1, minor: 0, patch: 0, prerelease: [] };
|
|
160
|
+
}
|
|
161
|
+
if (partial.minor > 0) {
|
|
162
|
+
return { major: 0, minor: partial.minor + 1, patch: 0, prerelease: [] };
|
|
163
|
+
}
|
|
164
|
+
if (partial.patch === null) {
|
|
165
|
+
return { major: 0, minor: partial.minor + 1, patch: 0, prerelease: [] };
|
|
166
|
+
}
|
|
167
|
+
return { major: 0, minor: 0, patch: partial.patch + 1, prerelease: [] };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function tildeUpperBound(partial: PartialVersion): SemverVersion | null {
|
|
171
|
+
if (partial.major === null) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
if (partial.minor === null) {
|
|
175
|
+
return { major: partial.major + 1, minor: 0, patch: 0, prerelease: [] };
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
major: partial.major,
|
|
179
|
+
minor: partial.minor + 1,
|
|
180
|
+
patch: 0,
|
|
181
|
+
prerelease: []
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function satisfiesComparator(
|
|
186
|
+
version: SemverVersion,
|
|
187
|
+
comparator: string
|
|
188
|
+
): boolean | null {
|
|
189
|
+
const match = /^(\^|~|>=|<=|>|<|=)?\s*(.*)$/.exec(comparator.trim());
|
|
190
|
+
if (!match) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
const operator = match[1] ?? '';
|
|
194
|
+
const partial = parsePartial(match[2]);
|
|
195
|
+
if (!partial) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const lower = lowerBound(partial);
|
|
199
|
+
switch (operator) {
|
|
200
|
+
case '>=':
|
|
201
|
+
return compareSemver(version, lower) >= 0;
|
|
202
|
+
case '>':
|
|
203
|
+
return compareSemver(version, lower) > 0;
|
|
204
|
+
case '<=':
|
|
205
|
+
return compareSemver(version, lower) <= 0;
|
|
206
|
+
case '<':
|
|
207
|
+
return compareSemver(version, lower) < 0;
|
|
208
|
+
case '^': {
|
|
209
|
+
if (compareSemver(version, lower) < 0) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
const upper = caretUpperBound(partial);
|
|
213
|
+
return upper === null || compareSemver(version, upper) < 0;
|
|
214
|
+
}
|
|
215
|
+
case '~': {
|
|
216
|
+
if (compareSemver(version, lower) < 0) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
const upper = tildeUpperBound(partial);
|
|
220
|
+
return upper === null || compareSemver(version, upper) < 0;
|
|
221
|
+
}
|
|
222
|
+
default: {
|
|
223
|
+
// '=' or bare version / x-range.
|
|
224
|
+
if (
|
|
225
|
+
partial.major !== null &&
|
|
226
|
+
partial.minor !== null &&
|
|
227
|
+
partial.patch !== null
|
|
228
|
+
) {
|
|
229
|
+
return compareSemver(version, lower) === 0;
|
|
230
|
+
}
|
|
231
|
+
if (compareSemver(version, lower) < 0) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
const upper = xRangeUpperBound(partial);
|
|
235
|
+
return upper === null || compareSemver(version, upper) < 0;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Returns true/false when both version and range are understood,
|
|
242
|
+
* null when either is unparsable (caller skips the gate, RFC §11).
|
|
243
|
+
*/
|
|
244
|
+
export function satisfiesRange(version: string, range: string): boolean | null {
|
|
245
|
+
const parsedVersion = parseSemver(version);
|
|
246
|
+
if (!parsedVersion) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
const trimmed = range.trim();
|
|
250
|
+
if (trimmed === '' || trimmed === '*' || /^x$/i.test(trimmed)) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
for (const clause of trimmed.split('||')) {
|
|
254
|
+
const comparators = clause.trim().split(/\s+/).filter(Boolean);
|
|
255
|
+
if (comparators.length === 0) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
let clauseResult: boolean | null = true;
|
|
259
|
+
for (const comparator of comparators) {
|
|
260
|
+
const result = satisfiesComparator(parsedVersion, comparator);
|
|
261
|
+
if (result === null) {
|
|
262
|
+
clauseResult = null;
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
if (!result) {
|
|
266
|
+
clauseResult = false;
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (clauseResult === null) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
if (clauseResult) {
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import fsp from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
/** Test-only helpers building fake package trees in temp directories. */
|
|
7
|
+
export interface FixturePackage {
|
|
8
|
+
/** Directory relative to the fixture root. */
|
|
9
|
+
dir: string;
|
|
10
|
+
packageJson: Record<string, unknown>;
|
|
11
|
+
/** Write a dist/client/manifest.json stub (marks the module as built). */
|
|
12
|
+
built?: boolean;
|
|
13
|
+
/** Manifest content for the stub; implies `built`. */
|
|
14
|
+
manifest?: Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Skip auto-creating the empty source files for declared
|
|
17
|
+
* `esmx.entry`/`esmx.exports` targets — use to trigger E_TARGET_MISSING.
|
|
18
|
+
*/
|
|
19
|
+
noSources?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Relative source paths an `esmx` declaration points at (entry + exports). */
|
|
23
|
+
function declaredTargets(esmx: unknown): string[] {
|
|
24
|
+
if (typeof esmx !== 'object' || esmx === null) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const out: string[] = [];
|
|
28
|
+
const decl = esmx as Record<string, unknown>;
|
|
29
|
+
const entry = decl.entry;
|
|
30
|
+
if (typeof entry === 'object' && entry !== null) {
|
|
31
|
+
for (const side of Object.values(entry as Record<string, unknown>)) {
|
|
32
|
+
if (typeof side === 'string') {
|
|
33
|
+
out.push(side);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const exports = decl.exports;
|
|
38
|
+
if (typeof exports === 'object' && exports !== null) {
|
|
39
|
+
for (const value of Object.values(exports as Record<string, unknown>)) {
|
|
40
|
+
if (typeof value === 'string') {
|
|
41
|
+
out.push(value);
|
|
42
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
43
|
+
for (const side of Object.values(
|
|
44
|
+
value as Record<string, unknown>
|
|
45
|
+
)) {
|
|
46
|
+
if (typeof side === 'string') {
|
|
47
|
+
out.push(side);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function createFixtureRoot(): Promise<string> {
|
|
57
|
+
const dir = await fsp.mkdtemp(path.join(os.tmpdir(), 'esmx-declaration-'));
|
|
58
|
+
// realpath once: macOS tmpdirs are symlinked (/var → /private/var).
|
|
59
|
+
return fs.realpathSync(dir);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function writeFixturePackage(
|
|
63
|
+
rootDir: string,
|
|
64
|
+
pkg: FixturePackage
|
|
65
|
+
): string {
|
|
66
|
+
const dir = path.join(rootDir, pkg.dir);
|
|
67
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
68
|
+
fs.writeFileSync(
|
|
69
|
+
path.join(dir, 'package.json'),
|
|
70
|
+
JSON.stringify(pkg.packageJson, null, 4)
|
|
71
|
+
);
|
|
72
|
+
if (pkg.built || pkg.manifest) {
|
|
73
|
+
const clientDir = path.join(dir, 'dist/client');
|
|
74
|
+
fs.mkdirSync(clientDir, { recursive: true });
|
|
75
|
+
fs.writeFileSync(
|
|
76
|
+
path.join(clientDir, 'manifest.json'),
|
|
77
|
+
JSON.stringify(pkg.manifest ?? {})
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
// Auto-create empty source files for every declared entry/exports target
|
|
81
|
+
// so fixtures satisfy the E_TARGET_MISSING existence check by default.
|
|
82
|
+
if (!pkg.noSources) {
|
|
83
|
+
for (const target of declaredTargets(pkg.packageJson.esmx)) {
|
|
84
|
+
const file = path.resolve(dir, target);
|
|
85
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
86
|
+
if (!fs.existsSync(file)) {
|
|
87
|
+
fs.writeFileSync(file, '');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return dir;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function removeFixtureRoot(rootDir: string): Promise<void> {
|
|
95
|
+
await fsp.rm(rootDir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 0001 declaration layer types.
|
|
3
|
+
*
|
|
4
|
+
* The `esmx` field of package.json carries strictly local protocol facts:
|
|
5
|
+
* a module declares only facts about itself (RFC P2).
|
|
6
|
+
*/
|
|
7
|
+
export interface EsmxDeclarationEntry {
|
|
8
|
+
client?: string;
|
|
9
|
+
server?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface EsmxDeclarationExportFork {
|
|
13
|
+
client?: string | false;
|
|
14
|
+
server?: string | false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type EsmxDeclarationExportValue = string | EsmxDeclarationExportFork;
|
|
18
|
+
|
|
19
|
+
export interface EsmxDeclaration {
|
|
20
|
+
entry?: EsmxDeclarationEntry;
|
|
21
|
+
exports?: Record<string, EsmxDeclarationExportValue>;
|
|
22
|
+
provides?: string[];
|
|
23
|
+
uses?: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Complete diagnostic taxonomy from RFC 0001 §7, plus E_SCHEMA for
|
|
28
|
+
* declaration shape violations (the RFC ships a JSON Schema but assigns
|
|
29
|
+
* no code to schema failures; one code is needed so agents can detect them).
|
|
30
|
+
*/
|
|
31
|
+
export const DiagnosticCode = {
|
|
32
|
+
E_NOT_LINKED: 'E_NOT_LINKED',
|
|
33
|
+
E_NOT_BUILT: 'E_NOT_BUILT',
|
|
34
|
+
E_CYCLE: 'E_CYCLE',
|
|
35
|
+
E_VERSION: 'E_VERSION',
|
|
36
|
+
E_DUP_PROVIDER: 'E_DUP_PROVIDER',
|
|
37
|
+
/** A declared entry/exports target file does not exist on disk. */
|
|
38
|
+
E_TARGET_MISSING: 'E_TARGET_MISSING',
|
|
39
|
+
// Build-time (phase 3) codes: emitted by the bundler during its
|
|
40
|
+
// per-specifier traversal, NOT by the build-free `esmx validate` (which
|
|
41
|
+
// never lexes source). Reserved here so the bundler emits them with the
|
|
42
|
+
// same envelope; do not wire emit paths into the resolver.
|
|
43
|
+
E_NOT_USED: 'E_NOT_USED',
|
|
44
|
+
E_NO_EXPORT: 'E_NO_EXPORT',
|
|
45
|
+
E_PROTOCOL: 'E_PROTOCOL',
|
|
46
|
+
E_PROTOCOL_IN_BEHAVIOR: 'E_PROTOCOL_IN_BEHAVIOR',
|
|
47
|
+
E_SCHEMA: 'E_SCHEMA',
|
|
48
|
+
W_MULTI_MAJOR: 'W_MULTI_MAJOR',
|
|
49
|
+
W_NO_RANGE: 'W_NO_RANGE',
|
|
50
|
+
W_TYPE_DRIFT: 'W_TYPE_DRIFT'
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
export type DiagnosticCodeValue =
|
|
54
|
+
(typeof DiagnosticCode)[keyof typeof DiagnosticCode];
|
|
55
|
+
|
|
56
|
+
export type DiagnosticSeverity = 'error' | 'warning';
|
|
57
|
+
|
|
58
|
+
export type DiagnosticCheck = 'intent';
|
|
59
|
+
|
|
60
|
+
/** Structured diagnostic matching the RFC `esmx validate --json` envelope. */
|
|
61
|
+
export interface Diagnostic {
|
|
62
|
+
code: string;
|
|
63
|
+
severity: DiagnosticSeverity;
|
|
64
|
+
module: string;
|
|
65
|
+
package?: string;
|
|
66
|
+
check?: DiagnosticCheck;
|
|
67
|
+
found?: string;
|
|
68
|
+
required?: string;
|
|
69
|
+
message: string;
|
|
70
|
+
fix: string;
|
|
71
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -8,12 +8,39 @@ export {
|
|
|
8
8
|
type ScopesMap,
|
|
9
9
|
type SpecifierMap
|
|
10
10
|
} from './core';
|
|
11
|
+
export type {
|
|
12
|
+
Diagnostic,
|
|
13
|
+
DiagnosticCheck,
|
|
14
|
+
DiagnosticCodeValue,
|
|
15
|
+
DiagnosticSeverity,
|
|
16
|
+
EsmxDeclaration,
|
|
17
|
+
EsmxDeclarationEntry,
|
|
18
|
+
EsmxDeclarationExportFork,
|
|
19
|
+
EsmxDeclarationExportValue,
|
|
20
|
+
ReadDeclarationResult,
|
|
21
|
+
ResolveDeclarationOptions,
|
|
22
|
+
ResolveDeclarationResult,
|
|
23
|
+
SupplyEntry,
|
|
24
|
+
SupplyGroup
|
|
25
|
+
} from './declaration';
|
|
26
|
+
export {
|
|
27
|
+
DiagnosticCode,
|
|
28
|
+
esmxDeclarationSchema,
|
|
29
|
+
readDeclaration,
|
|
30
|
+
resolveDeclaration
|
|
31
|
+
} from './declaration';
|
|
11
32
|
export type {
|
|
12
33
|
ManifestJson,
|
|
13
34
|
ManifestJsonChunk,
|
|
14
35
|
ManifestJsonChunks,
|
|
15
36
|
ManifestJsonExport,
|
|
16
|
-
ManifestJsonExports
|
|
37
|
+
ManifestJsonExports,
|
|
38
|
+
ManifestJsonProvide,
|
|
39
|
+
ManifestProtocolFields
|
|
40
|
+
} from './manifest-json';
|
|
41
|
+
export {
|
|
42
|
+
buildManifestProtocolFields,
|
|
43
|
+
MANIFEST_PROTOCOL_VERSION
|
|
17
44
|
} from './manifest-json';
|
|
18
45
|
export type {
|
|
19
46
|
ModuleConfig,
|