@telorun/analyzer 0.61.0 → 0.62.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/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +130 -9
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +69 -12
- package/dist/cel-bindings.d.ts +0 -6
- package/dist/cel-bindings.d.ts.map +1 -1
- package/dist/cel-bindings.js +3 -28
- package/dist/definition-registry.d.ts +17 -0
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +31 -2
- package/dist/identifier-name.d.ts +114 -0
- package/dist/identifier-name.d.ts.map +1 -0
- package/dist/identifier-name.js +183 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/manifest-schemas.d.ts +81 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +208 -6
- package/dist/release/payload-digest.d.ts +7 -3
- package/dist/release/payload-digest.d.ts.map +1 -1
- package/dist/release/payload-digest.js +7 -3
- package/dist/requires-block.d.ts +125 -0
- package/dist/requires-block.d.ts.map +1 -0
- package/dist/requires-block.js +182 -0
- package/dist/schema-keywords.d.ts +68 -0
- package/dist/schema-keywords.d.ts.map +1 -0
- package/dist/schema-keywords.js +324 -0
- package/dist/schema-region.d.ts +12 -1
- package/dist/schema-region.d.ts.map +1 -1
- package/dist/schema-region.js +12 -1
- package/dist/telo-version.d.ts +3 -0
- package/dist/telo-version.d.ts.map +1 -0
- package/dist/telo-version.js +8 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-identifier-names.d.ts +31 -0
- package/dist/validate-identifier-names.d.ts.map +1 -0
- package/dist/validate-identifier-names.js +144 -0
- package/dist/validate-observed-state.d.ts +9 -2
- package/dist/validate-observed-state.d.ts.map +1 -1
- package/dist/validate-observed-state.js +9 -2
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +5 -26
- package/dist/validate-requires.d.ts +49 -0
- package/dist/validate-requires.d.ts.map +1 -0
- package/dist/validate-requires.js +99 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +1 -0
- package/dist/version-range.d.ts +88 -0
- package/dist/version-range.d.ts.map +1 -0
- package/dist/version-range.js +173 -0
- package/package.json +2 -2
- package/src/analyzer.ts +146 -10
- package/src/builtins.ts +73 -12
- package/src/cel-bindings.ts +3 -28
- package/src/definition-registry.ts +30 -2
- package/src/identifier-name.ts +228 -0
- package/src/index.ts +34 -0
- package/src/manifest-schemas.ts +223 -4
- package/src/release/payload-digest.ts +7 -3
- package/src/requires-block.ts +253 -0
- package/src/schema-keywords.ts +359 -0
- package/src/schema-region.ts +12 -1
- package/src/telo-version.ts +9 -0
- package/src/types.ts +32 -0
- package/src/validate-identifier-names.ts +173 -0
- package/src/validate-observed-state.ts +9 -2
- package/src/validate-references.ts +5 -26
- package/src/validate-requires.ts +129 -0
- package/src/value-type-keyword.ts +1 -0
- package/src/version-range.ts +238 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-observed-state.d.ts","sourceRoot":"","sources":["../src/validate-observed-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAgBjD
|
|
1
|
+
{"version":3,"file":"validate-observed-state.d.ts","sourceRoot":"","sources":["../src/validate-observed-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAgBjD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB;;;CAGjC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,SAAS,gBAAgB,EAAE,GACrC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB3E;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC;+CAC2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,GAAG,SAAS,CAOzF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAQtE;AAGD;;4EAE4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,gBAAgB,EAAE,EACtC,IAAI,EAAE;IAAE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAAA;CAAE,EAC/D,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAAC,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,EAC/G,MAAM,CAAC,EAAE,YAAY,GACpB,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAsC/B;AAyDD;;;gDAGgD;AAChD,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC5C,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CASrB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,IAAI,CAmBN"}
|
|
@@ -16,8 +16,15 @@ const SYSTEM_KINDS = new Set([
|
|
|
16
16
|
* {@link validateObservedStateDeclarations} rather than here, so the author gets
|
|
17
17
|
* a message naming the rule and the fix instead of AJV's "must NOT be valid".
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* THE KERNEL'S SHAPE CHECK, not the analyzer's. The analyzer's builtins point
|
|
20
|
+
* their `status:` slot at the `JsonSchema7` fragment, which describes the same
|
|
21
|
+
* block far more precisely; the kernel keeps this permissive one, and the two do
|
|
22
|
+
* not drift into disagreement because the fragment only ever NARROWS what this
|
|
23
|
+
* accepts. That split is the same one the `required:` rule above draws: the
|
|
24
|
+
* loader answers "is this the right shape at all", and the check that can name
|
|
25
|
+
* the offending keyword and its line stays with `telo check`. Wiring the fragment
|
|
26
|
+
* into the kernel too would turn a check-time diagnostic into a boot failure for
|
|
27
|
+
* every already-published manifest carrying a sloppy keyword.
|
|
21
28
|
*/
|
|
22
29
|
export const OBSERVED_STATE_SCHEMA = {
|
|
23
30
|
type: "object",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAuD/F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAuD/F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,CA8ctB"}
|
|
@@ -188,32 +188,11 @@ export function validateReferences(resources, context) {
|
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
//
|
|
192
|
-
// the
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
for (const [name, list] of byNameAll) {
|
|
197
|
-
if (!name.includes("."))
|
|
198
|
-
continue;
|
|
199
|
-
for (const r of list) {
|
|
200
|
-
const m = r.metadata;
|
|
201
|
-
const range = typeof m?.sourceLine === "number"
|
|
202
|
-
? {
|
|
203
|
-
start: { line: m.sourceLine, character: 0 },
|
|
204
|
-
end: { line: m.sourceLine, character: Number.MAX_SAFE_INTEGER },
|
|
205
|
-
}
|
|
206
|
-
: undefined;
|
|
207
|
-
diagnostics.push({
|
|
208
|
-
severity: DiagnosticSeverity.Error,
|
|
209
|
-
code: "INVALID_RESOURCE_NAME",
|
|
210
|
-
source: SOURCE,
|
|
211
|
-
message: `${r.kind}/${name}: resource name must not contain '.' — in a '!ref' the '.' separates an import alias from the resource name`,
|
|
212
|
-
...(range ? { range } : {}),
|
|
213
|
-
data: { resource: { kind: r.kind, name }, filePath: m?.source, path: "metadata.name" },
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
191
|
+
// The dot rule that used to live here is now the strictest special case of
|
|
192
|
+
// the identifier grammar in `validate-identifier-names.ts` — a dot is one of
|
|
193
|
+
// several characters that make a name unreferenceable, and checking one of
|
|
194
|
+
// them here while the rest went unchecked is what let a hyphenated name
|
|
195
|
+
// through to silently evaluate as arithmetic.
|
|
217
196
|
// Single-resource map for the resolution / scope lookups below — when a
|
|
218
197
|
// collision exists, falling back to the first occurrence keeps the rest
|
|
219
198
|
// of the pass behaving the same as before the duplicate diagnostic was
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The strict half of `requires-block.ts` — the accessor/validator split
|
|
3
|
+
* `zone-slot.ts` / `validate-zone-slots.ts` established, and for the same reason:
|
|
4
|
+
* the reader must not throw on a malformed block (every consumer would have to
|
|
5
|
+
* guard), while a malformed block must not pass silently either.
|
|
6
|
+
*
|
|
7
|
+
* Two distinct outputs, and conflating them was the whole failure this mechanism
|
|
8
|
+
* addresses:
|
|
9
|
+
*
|
|
10
|
+
* - **`MODULE_REQUIRES_NEWER_RUNTIME`** — the module is fine and *this runtime*
|
|
11
|
+
* is too old. Raised per module before that module's own validation, so the
|
|
12
|
+
* version message wins over the vocabulary errors it would otherwise be buried
|
|
13
|
+
* in (`ZONE_ANNOTATION_INVALID`, an `additionalProperties` violation against a
|
|
14
|
+
* kernel-owned schema, an unknown `use` token). Those errors are true but
|
|
15
|
+
* blame the module author for a version skew.
|
|
16
|
+
* - **`REQUIRES_INVALID`** — the declaration itself is malformed. Severity turns
|
|
17
|
+
* on ownership rather than presence: an ERROR on the entry's own modules,
|
|
18
|
+
* whose author can fix it, and a WARNING on a dependency, whose author is the
|
|
19
|
+
* only one who can. It is not silent on a dependency, because `readRequires`
|
|
20
|
+
* drops an unparseable range and the gate then reads the module as satisfied —
|
|
21
|
+
* so it loads while stating a requirement it failed to state, and `telo
|
|
22
|
+
* upgrade` (which refuses such a version) would be holding it back for a
|
|
23
|
+
* reason the load path never mentions.
|
|
24
|
+
*
|
|
25
|
+
* **Unknown axes are suppressed while the `telo` requirement is unmet.** An older
|
|
26
|
+
* runtime not recognising a newer host axis is a *consequence* of the version
|
|
27
|
+
* skew — the axis exists, this runtime is simply too old to know it — so
|
|
28
|
+
* reporting it beside the gate diagnostic would manufacture a second defect from
|
|
29
|
+
* one cause. Once `telo` is satisfied, an unrecognized axis is a real error: a
|
|
30
|
+
* runtime at or above the declared generation is expected to know every axis that
|
|
31
|
+
* generation defines.
|
|
32
|
+
*/
|
|
33
|
+
import type { ResourceManifest } from "@telorun/sdk";
|
|
34
|
+
import { type HostVersions } from "./requires-block.js";
|
|
35
|
+
import { type AnalysisDiagnostic } from "./types.js";
|
|
36
|
+
export interface ValidateRequiresOptions {
|
|
37
|
+
/** The surface generation the analyzing runtime implements. Defaults to this
|
|
38
|
+
* build's own — see `AnalysisOptions.teloVersion`. */
|
|
39
|
+
teloVersion?: string;
|
|
40
|
+
/** Versions the running host can speak for. Absent in a browser, where there
|
|
41
|
+
* is no host to report; supplied by the kernel and CLI. */
|
|
42
|
+
hostVersions?: HostVersions;
|
|
43
|
+
/** Module names owned by the entry, when the caller can distinguish them.
|
|
44
|
+
* `REQUIRES_INVALID` is limited to these; the gate is not, because a
|
|
45
|
+
* dependency this runtime cannot read still stops the consumer dead. */
|
|
46
|
+
entryModules?: ReadonlySet<string>;
|
|
47
|
+
}
|
|
48
|
+
export declare function validateRequires(manifests: ResourceManifest[], options?: ValidateRequiresOptions): AnalysisDiagnostic[];
|
|
49
|
+
//# sourceMappingURL=validate-requires.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-requires.d.ts","sourceRoot":"","sources":["../src/validate-requires.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE,MAAM,WAAW,uBAAuB;IACtC;2DACuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gEAC4D;IAC5D,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;6EAEyE;IACzE,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,GAAE,uBAA4B,GACpC,kBAAkB,EAAE,CAuEtB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The strict half of `requires-block.ts` — the accessor/validator split
|
|
3
|
+
* `zone-slot.ts` / `validate-zone-slots.ts` established, and for the same reason:
|
|
4
|
+
* the reader must not throw on a malformed block (every consumer would have to
|
|
5
|
+
* guard), while a malformed block must not pass silently either.
|
|
6
|
+
*
|
|
7
|
+
* Two distinct outputs, and conflating them was the whole failure this mechanism
|
|
8
|
+
* addresses:
|
|
9
|
+
*
|
|
10
|
+
* - **`MODULE_REQUIRES_NEWER_RUNTIME`** — the module is fine and *this runtime*
|
|
11
|
+
* is too old. Raised per module before that module's own validation, so the
|
|
12
|
+
* version message wins over the vocabulary errors it would otherwise be buried
|
|
13
|
+
* in (`ZONE_ANNOTATION_INVALID`, an `additionalProperties` violation against a
|
|
14
|
+
* kernel-owned schema, an unknown `use` token). Those errors are true but
|
|
15
|
+
* blame the module author for a version skew.
|
|
16
|
+
* - **`REQUIRES_INVALID`** — the declaration itself is malformed. Severity turns
|
|
17
|
+
* on ownership rather than presence: an ERROR on the entry's own modules,
|
|
18
|
+
* whose author can fix it, and a WARNING on a dependency, whose author is the
|
|
19
|
+
* only one who can. It is not silent on a dependency, because `readRequires`
|
|
20
|
+
* drops an unparseable range and the gate then reads the module as satisfied —
|
|
21
|
+
* so it loads while stating a requirement it failed to state, and `telo
|
|
22
|
+
* upgrade` (which refuses such a version) would be holding it back for a
|
|
23
|
+
* reason the load path never mentions.
|
|
24
|
+
*
|
|
25
|
+
* **Unknown axes are suppressed while the `telo` requirement is unmet.** An older
|
|
26
|
+
* runtime not recognising a newer host axis is a *consequence* of the version
|
|
27
|
+
* skew — the axis exists, this runtime is simply too old to know it — so
|
|
28
|
+
* reporting it beside the gate diagnostic would manufacture a second defect from
|
|
29
|
+
* one cause. Once `telo` is satisfied, an unrecognized axis is a real error: a
|
|
30
|
+
* runtime at or above the declared generation is expected to know every axis that
|
|
31
|
+
* generation defines.
|
|
32
|
+
*/
|
|
33
|
+
import { evaluateRequires, readRequires } from "./requires-block.js";
|
|
34
|
+
import { TELO_SURFACE_VERSION } from "./telo-version.js";
|
|
35
|
+
import { DiagnosticSeverity } from "./types.js";
|
|
36
|
+
const SOURCE = "telo-analyzer";
|
|
37
|
+
export function validateRequires(manifests, options = {}) {
|
|
38
|
+
const running = options.teloVersion ?? TELO_SURFACE_VERSION;
|
|
39
|
+
const out = [];
|
|
40
|
+
for (const manifest of manifests) {
|
|
41
|
+
if (manifest.kind !== "Telo.Application" && manifest.kind !== "Telo.Library")
|
|
42
|
+
continue;
|
|
43
|
+
const doc = manifest;
|
|
44
|
+
const { declared, block, issues } = readRequires(doc);
|
|
45
|
+
if (!declared)
|
|
46
|
+
continue;
|
|
47
|
+
const metadata = (manifest.metadata ?? {});
|
|
48
|
+
const name = typeof metadata.name === "string" ? metadata.name : undefined;
|
|
49
|
+
const filePath = typeof metadata.source === "string" ? metadata.source : undefined;
|
|
50
|
+
const label = `${manifest.kind}/${name ?? "(unnamed)"}`;
|
|
51
|
+
const resource = { kind: manifest.kind, name };
|
|
52
|
+
const verdict = evaluateRequires(block, running, options.hostVersions);
|
|
53
|
+
if (!verdict.satisfied) {
|
|
54
|
+
const axis = verdict.axis === "telo" ? "telo" : `host.${verdict.axis}`;
|
|
55
|
+
const remedy = verdict.axis === "telo"
|
|
56
|
+
? `Upgrade telo, or pin ${name ?? "this module"} to a version whose range accepts ` +
|
|
57
|
+
`${verdict.running}.`
|
|
58
|
+
: `Upgrade ${verdict.axis}, or pin ${name ?? "this module"} to a version whose range ` +
|
|
59
|
+
`accepts ${verdict.running}.`;
|
|
60
|
+
out.push({
|
|
61
|
+
severity: DiagnosticSeverity.Error,
|
|
62
|
+
code: "MODULE_REQUIRES_NEWER_RUNTIME",
|
|
63
|
+
source: SOURCE,
|
|
64
|
+
message: `${label} requires ${axis} '${verdict.declared.raw}'; this runtime reports ` +
|
|
65
|
+
`${verdict.running}. ${remedy}`,
|
|
66
|
+
data: { resource, filePath, path: `requires.${axis}` },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const owned = options.entryModules === undefined ||
|
|
70
|
+
(typeof metadata.module === "string"
|
|
71
|
+
? options.entryModules.has(metadata.module)
|
|
72
|
+
: name === undefined || options.entryModules.has(name));
|
|
73
|
+
for (const issue of issues) {
|
|
74
|
+
// See the header: an unknown axis is a symptom while the gate is failing.
|
|
75
|
+
if (issue.unknownAxis && !verdict.satisfied)
|
|
76
|
+
continue;
|
|
77
|
+
// A DEPENDENCY's malformed block is not the consumer's to fix, but it must
|
|
78
|
+
// not be silent either. `readRequires` drops an unparseable range from the
|
|
79
|
+
// block, so the gate reads it as satisfied and the module loads while
|
|
80
|
+
// stating a requirement it failed to state — and `telo upgrade`, which
|
|
81
|
+
// refuses to select such a version, would then be holding a version back
|
|
82
|
+
// for a reason nothing on the load path ever mentions. A warning is what
|
|
83
|
+
// makes those two halves agree about the manifest without handing the
|
|
84
|
+
// consumer an error only its publisher can fix.
|
|
85
|
+
out.push({
|
|
86
|
+
severity: owned ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning,
|
|
87
|
+
code: "REQUIRES_INVALID",
|
|
88
|
+
source: SOURCE,
|
|
89
|
+
message: owned
|
|
90
|
+
? `${label}: ${issue.message}` + (issue.hint ? ` Write '${issue.hint}' instead.` : "")
|
|
91
|
+
: `${label}: ${issue.message} Its declared requirement cannot be read, so it is not ` +
|
|
92
|
+
`enforced here and \`telo upgrade\` will not select this version. Only the module's ` +
|
|
93
|
+
`publisher can fix it.`,
|
|
94
|
+
data: { resource, filePath, path: issue.path },
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
@@ -28,7 +28,7 @@ import type { KeywordDefinition } from "ajv";
|
|
|
28
28
|
*
|
|
29
29
|
* `x-telo-type` is deliberately absent — it is the one that emits code.
|
|
30
30
|
*/
|
|
31
|
-
export declare const ANNOTATION_KEYWORDS: readonly ["x-telo-bindings-from", "x-telo-catches-for", "x-telo-context", "x-telo-context-element-from", "x-telo-context-from", "x-telo-context-from-ref-kind", "x-telo-context-from-root", "x-telo-context-ref-from", "x-telo-error-context", "x-telo-eval", "x-telo-inline", "x-telo-outcome-list", "x-telo-provides-zone", "x-telo-ref", "x-telo-requires-zone", "x-telo-schema-from", "x-telo-scope", "x-telo-step-context", "x-telo-topology-role", "x-telo-value-schema-from", "x-telo-widget"];
|
|
31
|
+
export declare const ANNOTATION_KEYWORDS: readonly ["x-telo-bindings-from", "x-telo-catches-for", "x-telo-context", "x-telo-context-collection-from", "x-telo-context-element-from", "x-telo-context-from", "x-telo-context-from-ref-kind", "x-telo-context-from-root", "x-telo-context-ref-from", "x-telo-error-context", "x-telo-eval", "x-telo-inline", "x-telo-outcome-list", "x-telo-provides-zone", "x-telo-ref", "x-telo-requires-zone", "x-telo-schema-from", "x-telo-scope", "x-telo-step-context", "x-telo-topology-role", "x-telo-value-schema-from", "x-telo-widget"];
|
|
32
32
|
/**
|
|
33
33
|
* The `x-telo-type` keyword.
|
|
34
34
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-type-keyword.d.ts","sourceRoot":"","sources":["../src/value-type-keyword.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;+EAqB+E;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAC;AAiB7C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"value-type-keyword.d.ts","sourceRoot":"","sources":["../src/value-type-keyword.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;+EAqB+E;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAC;AAiB7C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,ygBAuBtB,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CA+BpD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IACxC,UAAU,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;CACzD,GAAG,IAAI,CAGP"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The version-range grammar `requires:` declares, and the only one Telo reads.
|
|
3
|
+
*
|
|
4
|
+
* Built on `module-version-order.ts`'s precedence rather than the `semver`
|
|
5
|
+
* package, for that file's reason: the analyzer is browser-safe, so the editor
|
|
6
|
+
* reaches the identical rule the kernel does. A second implementation of "does
|
|
7
|
+
* this version satisfy this range" would eventually disagree about what a
|
|
8
|
+
* manifest means, which is the whole failure this mechanism exists to prevent.
|
|
9
|
+
*
|
|
10
|
+
* **A range is a CONJUNCTION of explicit comparators** — `>=0.80.0`,
|
|
11
|
+
* `>=0.40.0 <0.50.0`, `>=0.40.0,<0.50.0`. That is deliberately narrower than
|
|
12
|
+
* npm's grammar, and every exclusion pays for itself:
|
|
13
|
+
*
|
|
14
|
+
* - **`^` and `~` are rejected**, not reinterpreted. On a `0.x` version both
|
|
15
|
+
* mean a single minor (`^0.40.0` is `>=0.40.0 <0.41.0`, identical to
|
|
16
|
+
* `~0.40.0`), and Telo ships breaking changes as minor bumps deliberately. So
|
|
17
|
+
* the caret reading is *correct* and therefore useless — every module would
|
|
18
|
+
* pin to one breaking-change generation and nobody could move telo without
|
|
19
|
+
* the whole standard library republishing. It is also the spelling semver
|
|
20
|
+
* intuition reaches for first, so accepting it would make the failure both
|
|
21
|
+
* common and silent.
|
|
22
|
+
* - **A bare version is rejected.** npm reads `0.80.0` as an exact pin, which is
|
|
23
|
+
* the same trap in a different costume; reading it as `>=` would contradict
|
|
24
|
+
* every other semver consumer. Refusing it and naming the two spellings is
|
|
25
|
+
* the only answer that cannot be misread.
|
|
26
|
+
* - **`||`, hyphen ranges, `*` and `x` are rejected.** A disjunction has no
|
|
27
|
+
* single low or high edge, and the edges are load-bearing: verification runs
|
|
28
|
+
* the CLI *at* them, and a declared upper bound must be checked for existence.
|
|
29
|
+
* A grammar whose edges are undefined cannot be verified, and an unverifiable
|
|
30
|
+
* bound is what this design forbids everywhere else.
|
|
31
|
+
*
|
|
32
|
+
* **Prereleases compare by plain precedence**, with no equivalent of npm's rule
|
|
33
|
+
* that a prerelease only satisfies a range mentioning one at the same
|
|
34
|
+
* `[major, minor, patch]`. That rule exists to stop a caret range dragging a
|
|
35
|
+
* consumer onto an `-rc` build; here the version being tested is *the runtime the
|
|
36
|
+
* user is already running*, not a candidate being selected for them, so the
|
|
37
|
+
* honest answer is the precedence one — a developer on `0.81.0-rc.1` satisfies
|
|
38
|
+
* `>=0.80.0` because they genuinely are past it.
|
|
39
|
+
*/
|
|
40
|
+
import { type ParsedModuleVersion } from "./module-version-order.js";
|
|
41
|
+
/** The comparison a single term applies. */
|
|
42
|
+
export type ComparatorOperator = ">=" | ">" | "<=" | "<";
|
|
43
|
+
export interface VersionComparator {
|
|
44
|
+
operator: ComparatorOperator;
|
|
45
|
+
/** The version as authored, for diagnostics and for the existence check. */
|
|
46
|
+
raw: string;
|
|
47
|
+
parsed: ParsedModuleVersion;
|
|
48
|
+
}
|
|
49
|
+
/** A parsed range: every comparator must hold. Never empty. */
|
|
50
|
+
export interface VersionRange {
|
|
51
|
+
/** The range exactly as authored, quoted verbatim in diagnostics. */
|
|
52
|
+
raw: string;
|
|
53
|
+
comparators: VersionComparator[];
|
|
54
|
+
}
|
|
55
|
+
/** Why a range string was refused. `hint` is the spelling to use instead, when
|
|
56
|
+
* there is an unambiguous one — a rejection that cannot say what to write
|
|
57
|
+
* instead is a worse diagnostic than the value it rejects. */
|
|
58
|
+
export interface VersionRangeError {
|
|
59
|
+
message: string;
|
|
60
|
+
hint?: string;
|
|
61
|
+
}
|
|
62
|
+
export type VersionRangeResult = {
|
|
63
|
+
ok: true;
|
|
64
|
+
range: VersionRange;
|
|
65
|
+
} | {
|
|
66
|
+
ok: false;
|
|
67
|
+
error: VersionRangeError;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Parse a range, or explain why it cannot be one. Never throws and never
|
|
71
|
+
* degrades to a permissive reading: a range this refuses is reported, not
|
|
72
|
+
* silently treated as "no requirement".
|
|
73
|
+
*/
|
|
74
|
+
export declare function parseVersionRange(raw: unknown): VersionRangeResult;
|
|
75
|
+
/** True when `version` satisfies every comparator. An unparseable `version` is
|
|
76
|
+
* `false` — never a pass, since the caller is asking whether a real runtime is
|
|
77
|
+
* admitted and "cannot tell" must not read as "yes". */
|
|
78
|
+
export declare function rangeAccepts(range: VersionRange, version: string): boolean;
|
|
79
|
+
/** The lower-bound comparator, or `undefined` when the range is open below.
|
|
80
|
+
* This is the version verification installs and runs as the low edge. */
|
|
81
|
+
export declare function lowerBound(range: VersionRange): VersionComparator | undefined;
|
|
82
|
+
/** The upper-bound comparator, or `undefined` when the range is open above —
|
|
83
|
+
* the normal case, where the high edge is HEAD and normal CI already covers it. */
|
|
84
|
+
export declare function upperBound(range: VersionRange): VersionComparator | undefined;
|
|
85
|
+
/** True when no version can satisfy the range — `>=0.90.0 <0.80.0`. Reported
|
|
86
|
+
* rather than left to fail mysteriously at every consumer. */
|
|
87
|
+
export declare function isUnsatisfiable(range: VersionRange): boolean;
|
|
88
|
+
//# sourceMappingURL=version-range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-range.d.ts","sourceRoot":"","sources":["../src/version-range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AAEnC,4CAA4C;AAC5C,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED;;+DAE+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAuB5C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAkElE;AAED;;yDAEyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAgB1E;AAED;0EAC0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,GAAG,SAAS,CAE7E;AAED;oFACoF;AACpF,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,GAAG,SAAS,CAE7E;AAoBD;+DAC+D;AAC/D,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAS5D"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The version-range grammar `requires:` declares, and the only one Telo reads.
|
|
3
|
+
*
|
|
4
|
+
* Built on `module-version-order.ts`'s precedence rather than the `semver`
|
|
5
|
+
* package, for that file's reason: the analyzer is browser-safe, so the editor
|
|
6
|
+
* reaches the identical rule the kernel does. A second implementation of "does
|
|
7
|
+
* this version satisfy this range" would eventually disagree about what a
|
|
8
|
+
* manifest means, which is the whole failure this mechanism exists to prevent.
|
|
9
|
+
*
|
|
10
|
+
* **A range is a CONJUNCTION of explicit comparators** — `>=0.80.0`,
|
|
11
|
+
* `>=0.40.0 <0.50.0`, `>=0.40.0,<0.50.0`. That is deliberately narrower than
|
|
12
|
+
* npm's grammar, and every exclusion pays for itself:
|
|
13
|
+
*
|
|
14
|
+
* - **`^` and `~` are rejected**, not reinterpreted. On a `0.x` version both
|
|
15
|
+
* mean a single minor (`^0.40.0` is `>=0.40.0 <0.41.0`, identical to
|
|
16
|
+
* `~0.40.0`), and Telo ships breaking changes as minor bumps deliberately. So
|
|
17
|
+
* the caret reading is *correct* and therefore useless — every module would
|
|
18
|
+
* pin to one breaking-change generation and nobody could move telo without
|
|
19
|
+
* the whole standard library republishing. It is also the spelling semver
|
|
20
|
+
* intuition reaches for first, so accepting it would make the failure both
|
|
21
|
+
* common and silent.
|
|
22
|
+
* - **A bare version is rejected.** npm reads `0.80.0` as an exact pin, which is
|
|
23
|
+
* the same trap in a different costume; reading it as `>=` would contradict
|
|
24
|
+
* every other semver consumer. Refusing it and naming the two spellings is
|
|
25
|
+
* the only answer that cannot be misread.
|
|
26
|
+
* - **`||`, hyphen ranges, `*` and `x` are rejected.** A disjunction has no
|
|
27
|
+
* single low or high edge, and the edges are load-bearing: verification runs
|
|
28
|
+
* the CLI *at* them, and a declared upper bound must be checked for existence.
|
|
29
|
+
* A grammar whose edges are undefined cannot be verified, and an unverifiable
|
|
30
|
+
* bound is what this design forbids everywhere else.
|
|
31
|
+
*
|
|
32
|
+
* **Prereleases compare by plain precedence**, with no equivalent of npm's rule
|
|
33
|
+
* that a prerelease only satisfies a range mentioning one at the same
|
|
34
|
+
* `[major, minor, patch]`. That rule exists to stop a caret range dragging a
|
|
35
|
+
* consumer onto an `-rc` build; here the version being tested is *the runtime the
|
|
36
|
+
* user is already running*, not a candidate being selected for them, so the
|
|
37
|
+
* honest answer is the precedence one — a developer on `0.81.0-rc.1` satisfies
|
|
38
|
+
* `>=0.80.0` because they genuinely are past it.
|
|
39
|
+
*/
|
|
40
|
+
import { compareParsedModuleVersions, parseModuleVersion, } from "./module-version-order.js";
|
|
41
|
+
/** Operators longest-first, so `>=` is matched before `>`. */
|
|
42
|
+
const OPERATORS = [">=", "<=", ">", "<"];
|
|
43
|
+
function refuse(message, hint) {
|
|
44
|
+
return { ok: false, error: hint === undefined ? { message } : { message, hint } };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Refuse with `>=<version>` as the hint — but only when that hint would itself
|
|
48
|
+
* parse.
|
|
49
|
+
*
|
|
50
|
+
* A hint is a repair the author is meant to paste, so one this parser would
|
|
51
|
+
* reject on the next run is worse than no hint at all: it converts a diagnostic
|
|
52
|
+
* the author can act on into a loop. Everything unparseable (a two-segment
|
|
53
|
+
* version, a date, a leftover placeholder) falls back to the message alone,
|
|
54
|
+
* which still names what is wrong.
|
|
55
|
+
*/
|
|
56
|
+
function hintedRefusal(message, version) {
|
|
57
|
+
return parseModuleVersion(version) ? refuse(message, `>=${version}`) : refuse(message);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse a range, or explain why it cannot be one. Never throws and never
|
|
61
|
+
* degrades to a permissive reading: a range this refuses is reported, not
|
|
62
|
+
* silently treated as "no requirement".
|
|
63
|
+
*/
|
|
64
|
+
export function parseVersionRange(raw) {
|
|
65
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
66
|
+
return refuse(`expected a version range string, got ${describe(raw)}`);
|
|
67
|
+
}
|
|
68
|
+
const text = raw.trim();
|
|
69
|
+
if (text.includes("||")) {
|
|
70
|
+
return refuse(`'${text}' is a disjunction. A range must be a conjunction of comparators, because ` +
|
|
71
|
+
`verification runs the CLI at its lowest and highest bound and a disjunction has neither`);
|
|
72
|
+
}
|
|
73
|
+
if (/\s-\s/.test(text)) {
|
|
74
|
+
return refuse(`'${text}' is a hyphen range`, `${text.split(/\s-\s/)[0]?.trim() ?? ""} rewritten as '>=' and '<=' comparators`);
|
|
75
|
+
}
|
|
76
|
+
const terms = text.split(/[\s,]+/).filter((t) => t !== "");
|
|
77
|
+
const comparators = [];
|
|
78
|
+
for (const term of terms) {
|
|
79
|
+
if (term.startsWith("^") || term.startsWith("~")) {
|
|
80
|
+
const version = term.slice(1);
|
|
81
|
+
const parsed = parseModuleVersion(version);
|
|
82
|
+
const upper = parsed && parsed.major === 0 ? `0.${parsed.minor + 1}.0` : `${(parsed?.major ?? 0) + 1}.0.0`;
|
|
83
|
+
return refuse(`'${term}' is not accepted. Pre-1.0, '${term[0]}' allows only ${version} up to ` +
|
|
84
|
+
`${upper}, and Telo ships breaking changes as minor bumps — so it pins this module to ` +
|
|
85
|
+
`a single release generation, which is almost never what is meant`, `>=${version}`);
|
|
86
|
+
}
|
|
87
|
+
// Any `x`/`*` placeholder, at any position — `*`, `x`, `1.x`, `1.2.x`,
|
|
88
|
+
// `1.2.*`. Catching only some of them sent the rest to the no-comparator
|
|
89
|
+
// branch below, which suggested `>=1.2.*` — a hint this very parser rejects,
|
|
90
|
+
// which is worse than the value it was rejecting.
|
|
91
|
+
if (/(^|\.)[x*]$/i.test(term) || /(^|\.)[x*]\./i.test(term)) {
|
|
92
|
+
return refuse(`'${term}' is a wildcard range; write explicit comparators instead`);
|
|
93
|
+
}
|
|
94
|
+
if (term.startsWith("=")) {
|
|
95
|
+
return hintedRefusal(`'${term}' pins one exact version`, term.replace(/^=+/, ""));
|
|
96
|
+
}
|
|
97
|
+
const operator = OPERATORS.find((op) => term.startsWith(op));
|
|
98
|
+
if (!operator) {
|
|
99
|
+
return hintedRefusal(`'${term}' has no comparator. A bare version reads as an exact pin in semver, which is ` +
|
|
100
|
+
`almost never meant here`, term);
|
|
101
|
+
}
|
|
102
|
+
const version = term.slice(operator.length).trim();
|
|
103
|
+
const parsed = parseModuleVersion(version);
|
|
104
|
+
if (!parsed) {
|
|
105
|
+
return refuse(`'${version}' in '${term}' is not a three-part version (X.Y.Z, optionally -prerelease)`);
|
|
106
|
+
}
|
|
107
|
+
comparators.push({ operator, raw: version, parsed });
|
|
108
|
+
}
|
|
109
|
+
if (comparators.length === 0)
|
|
110
|
+
return refuse(`'${text}' declares no comparator`);
|
|
111
|
+
return { ok: true, range: { raw: text, comparators } };
|
|
112
|
+
}
|
|
113
|
+
/** True when `version` satisfies every comparator. An unparseable `version` is
|
|
114
|
+
* `false` — never a pass, since the caller is asking whether a real runtime is
|
|
115
|
+
* admitted and "cannot tell" must not read as "yes". */
|
|
116
|
+
export function rangeAccepts(range, version) {
|
|
117
|
+
const parsed = parseModuleVersion(version);
|
|
118
|
+
if (!parsed)
|
|
119
|
+
return false;
|
|
120
|
+
return range.comparators.every((c) => {
|
|
121
|
+
const cmp = compareParsedModuleVersions(parsed, c.parsed);
|
|
122
|
+
switch (c.operator) {
|
|
123
|
+
case ">=":
|
|
124
|
+
return cmp >= 0;
|
|
125
|
+
case ">":
|
|
126
|
+
return cmp > 0;
|
|
127
|
+
case "<=":
|
|
128
|
+
return cmp <= 0;
|
|
129
|
+
case "<":
|
|
130
|
+
return cmp < 0;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** The lower-bound comparator, or `undefined` when the range is open below.
|
|
135
|
+
* This is the version verification installs and runs as the low edge. */
|
|
136
|
+
export function lowerBound(range) {
|
|
137
|
+
return highest(range.comparators.filter((c) => c.operator === ">=" || c.operator === ">"));
|
|
138
|
+
}
|
|
139
|
+
/** The upper-bound comparator, or `undefined` when the range is open above —
|
|
140
|
+
* the normal case, where the high edge is HEAD and normal CI already covers it. */
|
|
141
|
+
export function upperBound(range) {
|
|
142
|
+
return lowest(range.comparators.filter((c) => c.operator === "<=" || c.operator === "<"));
|
|
143
|
+
}
|
|
144
|
+
/** The tightest of several same-direction bounds wins; a range may legitimately
|
|
145
|
+
* state more than one, and only the binding bound is an edge worth testing. */
|
|
146
|
+
function highest(list) {
|
|
147
|
+
return list.reduce((best, c) => best === undefined || compareParsedModuleVersions(c.parsed, best.parsed) > 0 ? c : best, undefined);
|
|
148
|
+
}
|
|
149
|
+
function lowest(list) {
|
|
150
|
+
return list.reduce((best, c) => best === undefined || compareParsedModuleVersions(c.parsed, best.parsed) < 0 ? c : best, undefined);
|
|
151
|
+
}
|
|
152
|
+
/** True when no version can satisfy the range — `>=0.90.0 <0.80.0`. Reported
|
|
153
|
+
* rather than left to fail mysteriously at every consumer. */
|
|
154
|
+
export function isUnsatisfiable(range) {
|
|
155
|
+
const low = lowerBound(range);
|
|
156
|
+
const high = upperBound(range);
|
|
157
|
+
if (!low || !high)
|
|
158
|
+
return false;
|
|
159
|
+
const cmp = compareParsedModuleVersions(low.parsed, high.parsed);
|
|
160
|
+
if (cmp > 0)
|
|
161
|
+
return true;
|
|
162
|
+
// `>=X <X` and `>X <=X` admit nothing; `>=X <=X` admits exactly X.
|
|
163
|
+
if (cmp === 0)
|
|
164
|
+
return low.operator === ">" || high.operator === "<";
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
function describe(value) {
|
|
168
|
+
if (value === null)
|
|
169
|
+
return "null";
|
|
170
|
+
if (Array.isArray(value))
|
|
171
|
+
return "an array";
|
|
172
|
+
return typeof value;
|
|
173
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/analyzer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.1",
|
|
4
4
|
"description": "Telo Analyzer - Static manifest validator for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@types/node": "^20.0.0",
|
|
50
50
|
"typescript": "^5.0.0",
|
|
51
51
|
"vitest": "^2.1.8",
|
|
52
|
-
"@telorun/sdk": "0.
|
|
52
|
+
"@telorun/sdk": "0.77.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@telorun/sdk": "*"
|