@telorun/analyzer 0.59.0 → 0.61.0
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 +9 -2
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +38 -10
- package/dist/artifact-layer-index.d.ts +13 -5
- package/dist/artifact-layer-index.d.ts.map +1 -1
- package/dist/artifact-layer-index.js +37 -13
- package/dist/artifact-selector.d.ts +10 -3
- package/dist/artifact-selector.d.ts.map +1 -1
- package/dist/artifact-selector.js +10 -1
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +44 -43
- package/dist/cel-environment.d.ts.map +1 -1
- package/dist/cel-environment.js +35 -0
- package/dist/flatten-for-analyzer.d.ts +4 -0
- package/dist/flatten-for-analyzer.d.ts.map +1 -1
- package/dist/flatten-for-analyzer.js +8 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/kernel-globals.d.ts +1 -1
- package/dist/kernel-globals.d.ts.map +1 -1
- package/dist/kernel-globals.js +15 -1
- package/dist/manifest-schemas.d.ts +407 -0
- package/dist/manifest-schemas.d.ts.map +1 -0
- package/dist/manifest-schemas.js +396 -0
- package/dist/module-file-claims.d.ts +13 -0
- package/dist/module-file-claims.d.ts.map +1 -1
- package/dist/module-file-claims.js +26 -2
- package/dist/module-library.d.ts +97 -0
- package/dist/module-library.d.ts.map +1 -0
- package/dist/module-library.js +162 -0
- package/dist/module-metadata-scope.d.ts +44 -0
- package/dist/module-metadata-scope.d.ts.map +1 -0
- package/dist/module-metadata-scope.js +82 -0
- package/dist/parse-loaded-file.d.ts.map +1 -1
- package/dist/parse-loaded-file.js +16 -0
- package/dist/release/bump-level.d.ts +46 -0
- package/dist/release/bump-level.d.ts.map +1 -0
- package/dist/release/bump-level.js +80 -0
- package/dist/release/changelog.d.ts +36 -0
- package/dist/release/changelog.d.ts.map +1 -0
- package/dist/release/changelog.js +53 -0
- package/dist/release/fragment.d.ts +48 -0
- package/dist/release/fragment.d.ts.map +1 -0
- package/dist/release/fragment.js +84 -0
- package/dist/release/index.d.ts +26 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +18 -0
- package/dist/release/ledger.d.ts +53 -0
- package/dist/release/ledger.d.ts.map +1 -0
- package/dist/release/ledger.js +109 -0
- package/dist/release/payload-digest.d.ts +63 -0
- package/dist/release/payload-digest.d.ts.map +1 -0
- package/dist/release/payload-digest.js +65 -0
- package/dist/release/release-plan.d.ts +128 -0
- package/dist/release/release-plan.d.ts.map +1 -0
- package/dist/release/release-plan.js +277 -0
- package/dist/release/version-stamp.d.ts +50 -0
- package/dist/release/version-stamp.d.ts.map +1 -0
- package/dist/release/version-stamp.js +119 -0
- package/dist/release/workspace-config.d.ts +41 -0
- package/dist/release/workspace-config.d.ts.map +1 -0
- package/dist/release/workspace-config.js +60 -0
- package/dist/schema-compat.js +2 -1
- package/dist/validate-module-artifact.d.ts.map +1 -1
- package/dist/validate-module-artifact.js +53 -1
- package/dist/validate-step-inputs.d.ts +1 -1
- package/dist/validate-step-inputs.d.ts.map +1 -1
- package/dist/validate-step-inputs.js +99 -8
- package/package.json +3 -3
- package/src/analyzer.ts +41 -10
- package/src/artifact-layer-index.ts +47 -14
- package/src/artifact-selector.ts +15 -4
- package/src/builtins.ts +45 -43
- package/src/cel-environment.ts +37 -0
- package/src/flatten-for-analyzer.ts +12 -0
- package/src/index.ts +19 -2
- package/src/kernel-globals.ts +23 -1
- package/src/manifest-schemas.ts +408 -0
- package/src/module-file-claims.ts +42 -2
- package/src/module-library.ts +208 -0
- package/src/module-metadata-scope.ts +88 -0
- package/src/parse-loaded-file.ts +16 -0
- package/src/release/bump-level.ts +95 -0
- package/src/release/changelog.ts +62 -0
- package/src/release/fragment.ts +130 -0
- package/src/release/index.ts +66 -0
- package/src/release/ledger.ts +142 -0
- package/src/release/payload-digest.ts +83 -0
- package/src/release/release-plan.ts +392 -0
- package/src/release/version-stamp.ts +142 -0
- package/src/release/workspace-config.ts +81 -0
- package/src/schema-compat.ts +1 -1
- package/src/validate-module-artifact.ts +56 -0
- package/src/validate-step-inputs.ts +109 -9
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A module's **exported code** — the `exports.code:` block on a `Telo.Library`
|
|
3
|
+
* doc, which names the entry point a *sibling module's* controller bundle
|
|
4
|
+
* resolves this module's bare specifier to.
|
|
5
|
+
*
|
|
6
|
+
* ```yaml
|
|
7
|
+
* exports:
|
|
8
|
+
* kinds:
|
|
9
|
+
* - Store
|
|
10
|
+
* code:
|
|
11
|
+
* - specifier: "@telorun/kv-store"
|
|
12
|
+
* format: js
|
|
13
|
+
* path: ./nodejs/kv-store.mjs
|
|
14
|
+
* source: ./nodejs/src/index.ts
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* ## Why it sits under `exports:`
|
|
18
|
+
*
|
|
19
|
+
* A library already declares what crosses its boundary — the kinds importers may
|
|
20
|
+
* name, the resource instances they may `!ref`. This is the same statement about
|
|
21
|
+
* its *code*, and it gates the same way: a specifier nobody declares resolves to
|
|
22
|
+
* nothing. Putting it beside them keeps one block for "reachable from outside"
|
|
23
|
+
* rather than a second top-level key whose name (`library:` on a `Telo.Library`)
|
|
24
|
+
* meant a different thing from the kind one line above it.
|
|
25
|
+
*
|
|
26
|
+
* ## Why it is not a package URL
|
|
27
|
+
*
|
|
28
|
+
* `controllers:` names a PURL because it must be able to say `pkg:npm/…` or
|
|
29
|
+
* `pkg:cargo/…` — an ecosystem fetch. This entry never fetches: it names a file
|
|
30
|
+
* the module already ships, so `pkg:telo/local/` would be three constant segments
|
|
31
|
+
* before the first real datum. What is left after removing them is exactly these
|
|
32
|
+
* fields, and as data they are visually editable, where a query string is one
|
|
33
|
+
* opaque text box.
|
|
34
|
+
*
|
|
35
|
+
* The **model** is unchanged: `format` plus the optional platform axes build the
|
|
36
|
+
* same `ArtifactSelector` a controller candidate does, so layer matching, platform
|
|
37
|
+
* fallthrough and lazy materialization are inherited whole.
|
|
38
|
+
*
|
|
39
|
+
* ## Why the specifier is declared here
|
|
40
|
+
*
|
|
41
|
+
* A bundle imports the bare specifier `@telorun/sql`; the consumer's manifest
|
|
42
|
+
* declares the dependency as `Sql: ../sql`. Something has to connect the two, and
|
|
43
|
+
* it is the *library* that says so, once, rather than each of its consumers:
|
|
44
|
+
*
|
|
45
|
+
* - the specifier is a property of the library — its name in a host language's
|
|
46
|
+
* ecosystem — not of the relationship, so N consumers cannot disagree about it
|
|
47
|
+
* and adding a consumer restates nothing;
|
|
48
|
+
* - it sits beside the format, which keeps runtime **derived, never declared**:
|
|
49
|
+
* the entry says `format: js`, and a Rust entry carries `specifier:
|
|
50
|
+
* telorun-sql` with no runtime-keyed map anywhere.
|
|
51
|
+
*
|
|
52
|
+
* **One specifier, one entry point.** Subpaths are deliberately not
|
|
53
|
+
* representable: reproducing npm's `exports` map inside the artifact would pull a
|
|
54
|
+
* package manager's resolution semantics into Telo, which is what the "only
|
|
55
|
+
* workspace modules are de-inlined" rule refuses on `kysely`'s behalf.
|
|
56
|
+
*
|
|
57
|
+
* `Telo.Application` has no `exports:` block at all — an application is a root
|
|
58
|
+
* with no importer, so nothing could resolve a specifier to it.
|
|
59
|
+
*
|
|
60
|
+
* Browser-safe: string work only. Whether the named file EXISTS is a separate
|
|
61
|
+
* question, asked by the Node-side caller that has a directory.
|
|
62
|
+
*/
|
|
63
|
+
import { ArtifactSelectorError, PLATFORM_AXES, selectorFromQualifiers, } from "./artifact-selector.js";
|
|
64
|
+
/** Every key an entry may carry: the two locators, plus the selector axes. */
|
|
65
|
+
const KNOWN_KEYS = new Set(["specifier", "path", "source", "format", ...PLATFORM_AXES]);
|
|
66
|
+
/** Normalize a `path` / `source` value to the manifest-relative POSIX form the
|
|
67
|
+
* file selector returns, so membership is a string comparison. */
|
|
68
|
+
function normalizeRelative(value) {
|
|
69
|
+
return value.replace(/^\.\//, "").replace(/\\/g, "/");
|
|
70
|
+
}
|
|
71
|
+
function requiredString(entry, key) {
|
|
72
|
+
const raw = entry[key];
|
|
73
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
74
|
+
return { detail: `'${key}' is required and must be a non-empty string.` };
|
|
75
|
+
}
|
|
76
|
+
return { value: raw.trim() };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Read the `exports.code:` block off an owner document's JSON projection.
|
|
80
|
+
*
|
|
81
|
+
* Everything malformed is a problem rather than a silent skip: an entry that
|
|
82
|
+
* cannot be read names no entry point, so a consumer's bundle falls back to
|
|
83
|
+
* *inlining* the library — the duplicated module scope this whole mechanism
|
|
84
|
+
* exists to remove — and it does so on someone else's machine.
|
|
85
|
+
*/
|
|
86
|
+
export function readLibraryCandidates(ownerJson) {
|
|
87
|
+
const declared = ownerJson?.exports?.code;
|
|
88
|
+
const candidates = [];
|
|
89
|
+
const problems = [];
|
|
90
|
+
if (declared === undefined)
|
|
91
|
+
return { candidates, problems };
|
|
92
|
+
if (!Array.isArray(declared)) {
|
|
93
|
+
return {
|
|
94
|
+
candidates,
|
|
95
|
+
problems: [{ origin: "exports.code", detail: "expected a list of entries." }],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
declared.forEach((raw, index) => {
|
|
99
|
+
const origin = `exports.code[${index}]`;
|
|
100
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
101
|
+
problems.push({ origin, detail: "expected an object." });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const entry = raw;
|
|
105
|
+
const unknown = Object.keys(entry).filter((key) => !KNOWN_KEYS.has(key));
|
|
106
|
+
if (unknown.length > 0) {
|
|
107
|
+
// Reported, never ignored: an unrecognized platform axis would leave the
|
|
108
|
+
// entry platform-neutral and offer a single-platform file to every host.
|
|
109
|
+
problems.push({
|
|
110
|
+
origin,
|
|
111
|
+
detail: `unknown ${unknown.length === 1 ? "key" : "keys"} ${unknown.map((k) => `'${k}'`).join(", ")}. ` +
|
|
112
|
+
`Known: ${[...KNOWN_KEYS].join(", ")}.`,
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const specifier = requiredString(entry, "specifier");
|
|
117
|
+
if ("detail" in specifier) {
|
|
118
|
+
problems.push({ origin, detail: specifier.detail });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const file = requiredString(entry, "path");
|
|
122
|
+
if ("detail" in file) {
|
|
123
|
+
problems.push({ origin: `${origin} ('${specifier.value}')`, detail: file.detail });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Explicit rather than inferred from the file extension: a `.mjs` can be
|
|
127
|
+
// wasm glue, and an inference rule is something every other runtime's reader
|
|
128
|
+
// would have to copy exactly.
|
|
129
|
+
const format = requiredString(entry, "format");
|
|
130
|
+
if ("detail" in format) {
|
|
131
|
+
problems.push({ origin: `${origin} ('${specifier.value}')`, detail: format.detail });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
let selector;
|
|
135
|
+
try {
|
|
136
|
+
selector = selectorFromQualifiers(format.value, entry, `${origin} ('${specifier.value}')`);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
problems.push({
|
|
140
|
+
origin: `${origin} ('${specifier.value}')`,
|
|
141
|
+
detail: err instanceof ArtifactSelectorError ? err.message : String(err),
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const source = entry.source;
|
|
146
|
+
if (source !== undefined && (typeof source !== "string" || source.trim() === "")) {
|
|
147
|
+
problems.push({
|
|
148
|
+
origin: `${origin} ('${specifier.value}')`,
|
|
149
|
+
detail: "'source' must be a non-empty string when present.",
|
|
150
|
+
});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
candidates.push({
|
|
154
|
+
specifier: specifier.value,
|
|
155
|
+
path: normalizeRelative(file.value),
|
|
156
|
+
...(typeof source === "string" ? { localPath: normalizeRelative(source.trim()) } : {}),
|
|
157
|
+
selector,
|
|
158
|
+
origin: `${origin} ('${specifier.value}')`,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
return { candidates, problems };
|
|
162
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `module.<field>` may read: the metadata an AUTHOR wrote, never the
|
|
3
|
+
* loader's own stamps.
|
|
4
|
+
*
|
|
5
|
+
* A manifest reaching its own `metadata` is a small binding with one sharp edge.
|
|
6
|
+
* By the time analysis or the runtime sees a module doc, its `metadata` also
|
|
7
|
+
* carries fields nothing authored — `source` and `sourceLine` (the loader's
|
|
8
|
+
* provenance), `module`, `moduleGlobals`, `exportedKinds`, `reExportedKinds`,
|
|
9
|
+
* `forwardedExport` (derived indices the analyzer stamps). Exposing those would
|
|
10
|
+
* publish loader internals as a manifest surface, where they would be read,
|
|
11
|
+
* depended on, and then unchangeable.
|
|
12
|
+
*
|
|
13
|
+
* A DENYLIST rather than an allowlist, because the metadata vocabulary is
|
|
14
|
+
* deliberately open: a module may declare a field the standard library has never
|
|
15
|
+
* heard of, and an allowlist would silently hide it. The stamps, by contrast,
|
|
16
|
+
* are a closed set this repo controls — so the thing that can be enumerated is
|
|
17
|
+
* the thing enumerated.
|
|
18
|
+
*/
|
|
19
|
+
/** Fields written by the loader or the analyzer, not by the module's author. */
|
|
20
|
+
export declare const DERIVED_METADATA_FIELDS: ReadonlySet<string>;
|
|
21
|
+
/** The author-written half of a module doc's `metadata`. */
|
|
22
|
+
export declare function authoredModuleMetadata(metadata: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* The `module` namespace as a JSON Schema, or `undefined` when there is nothing
|
|
25
|
+
* to type it from.
|
|
26
|
+
*
|
|
27
|
+
* **One derivation, two consumers.** `cel-environment.ts` needs CEL type strings
|
|
28
|
+
* and `kernel-globals.ts` needs JSON Schema, and they used to reach the same
|
|
29
|
+
* conclusion through two hand-written ternary chains that had to agree forever
|
|
30
|
+
* about which values are open and which are closed. The schema is the richer of
|
|
31
|
+
* the two shapes, so it is what is derived; the CEL side converts with
|
|
32
|
+
* `jsonSchemaToCelType`, which every other namespace already goes through.
|
|
33
|
+
*
|
|
34
|
+
* Typed from the VALUES because a module doc's metadata is literals, not a
|
|
35
|
+
* schema map — the module a resource belongs to is fixed, so there is nothing to
|
|
36
|
+
* resolve.
|
|
37
|
+
*
|
|
38
|
+
* `undefined` means **open**, and the distinction matters in the rejecting
|
|
39
|
+
* direction: a set with no module doc must leave `module.*` unconstrained rather
|
|
40
|
+
* than close it over whatever metadata happened to be at hand, or a valid
|
|
41
|
+
* `module.version` becomes a hard error nobody can act on.
|
|
42
|
+
*/
|
|
43
|
+
export declare function moduleMetadataSchema(metadata: Record<string, unknown> | undefined | null): Record<string, any> | undefined;
|
|
44
|
+
//# sourceMappingURL=module-metadata-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-metadata-scope.d.ts","sourceRoot":"","sources":["../src/module-metadata-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAQtD,CAAC;AAEH,4DAA4D;AAC5D,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAsBjC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `module.<field>` may read: the metadata an AUTHOR wrote, never the
|
|
3
|
+
* loader's own stamps.
|
|
4
|
+
*
|
|
5
|
+
* A manifest reaching its own `metadata` is a small binding with one sharp edge.
|
|
6
|
+
* By the time analysis or the runtime sees a module doc, its `metadata` also
|
|
7
|
+
* carries fields nothing authored — `source` and `sourceLine` (the loader's
|
|
8
|
+
* provenance), `module`, `moduleGlobals`, `exportedKinds`, `reExportedKinds`,
|
|
9
|
+
* `forwardedExport` (derived indices the analyzer stamps). Exposing those would
|
|
10
|
+
* publish loader internals as a manifest surface, where they would be read,
|
|
11
|
+
* depended on, and then unchangeable.
|
|
12
|
+
*
|
|
13
|
+
* A DENYLIST rather than an allowlist, because the metadata vocabulary is
|
|
14
|
+
* deliberately open: a module may declare a field the standard library has never
|
|
15
|
+
* heard of, and an allowlist would silently hide it. The stamps, by contrast,
|
|
16
|
+
* are a closed set this repo controls — so the thing that can be enumerated is
|
|
17
|
+
* the thing enumerated.
|
|
18
|
+
*/
|
|
19
|
+
/** Fields written by the loader or the analyzer, not by the module's author. */
|
|
20
|
+
export const DERIVED_METADATA_FIELDS = new Set([
|
|
21
|
+
"source",
|
|
22
|
+
"sourceLine",
|
|
23
|
+
"module",
|
|
24
|
+
"moduleGlobals",
|
|
25
|
+
"exportedKinds",
|
|
26
|
+
"reExportedKinds",
|
|
27
|
+
"forwardedExport",
|
|
28
|
+
]);
|
|
29
|
+
/** The author-written half of a module doc's `metadata`. */
|
|
30
|
+
export function authoredModuleMetadata(metadata) {
|
|
31
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata))
|
|
32
|
+
return {};
|
|
33
|
+
const authored = {};
|
|
34
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
35
|
+
if (DERIVED_METADATA_FIELDS.has(key))
|
|
36
|
+
continue;
|
|
37
|
+
authored[key] = value;
|
|
38
|
+
}
|
|
39
|
+
return authored;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The `module` namespace as a JSON Schema, or `undefined` when there is nothing
|
|
43
|
+
* to type it from.
|
|
44
|
+
*
|
|
45
|
+
* **One derivation, two consumers.** `cel-environment.ts` needs CEL type strings
|
|
46
|
+
* and `kernel-globals.ts` needs JSON Schema, and they used to reach the same
|
|
47
|
+
* conclusion through two hand-written ternary chains that had to agree forever
|
|
48
|
+
* about which values are open and which are closed. The schema is the richer of
|
|
49
|
+
* the two shapes, so it is what is derived; the CEL side converts with
|
|
50
|
+
* `jsonSchemaToCelType`, which every other namespace already goes through.
|
|
51
|
+
*
|
|
52
|
+
* Typed from the VALUES because a module doc's metadata is literals, not a
|
|
53
|
+
* schema map — the module a resource belongs to is fixed, so there is nothing to
|
|
54
|
+
* resolve.
|
|
55
|
+
*
|
|
56
|
+
* `undefined` means **open**, and the distinction matters in the rejecting
|
|
57
|
+
* direction: a set with no module doc must leave `module.*` unconstrained rather
|
|
58
|
+
* than close it over whatever metadata happened to be at hand, or a valid
|
|
59
|
+
* `module.version` becomes a hard error nobody can act on.
|
|
60
|
+
*/
|
|
61
|
+
export function moduleMetadataSchema(metadata) {
|
|
62
|
+
const authored = authoredModuleMetadata(metadata);
|
|
63
|
+
const keys = Object.keys(authored);
|
|
64
|
+
if (keys.length === 0)
|
|
65
|
+
return undefined;
|
|
66
|
+
const properties = {};
|
|
67
|
+
for (const key of keys) {
|
|
68
|
+
const value = authored[key];
|
|
69
|
+
properties[key] = Array.isArray(value)
|
|
70
|
+
? { type: "array" }
|
|
71
|
+
: value !== null && typeof value === "object"
|
|
72
|
+
? { type: "object", additionalProperties: true }
|
|
73
|
+
: {
|
|
74
|
+
type: typeof value === "number"
|
|
75
|
+
? "number"
|
|
76
|
+
: typeof value === "boolean"
|
|
77
|
+
? "boolean"
|
|
78
|
+
: "string",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return { type: "object", properties, additionalProperties: false };
|
|
82
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-loaded-file.d.ts","sourceRoot":"","sources":["../src/parse-loaded-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,mBAAmB,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"parse-loaded-file.d.ts","sourceRoot":"","sources":["../src/parse-loaded-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,mBAAmB,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM5D,MAAM,WAAW,YAAY;IAC3B;4EACwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;0DAGsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,UAAU,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACxC;AA4BD,oEAAoE;AACpE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,YAAY,GACrB,UAAU,CA0EZ"}
|
|
@@ -3,6 +3,7 @@ import { parseAllDocuments } from "yaml";
|
|
|
3
3
|
import { buildCelEnvironment } from "./cel-environment.js";
|
|
4
4
|
import { migrateManifests, NO_MIGRATIONS } from "./migrations/driver.js";
|
|
5
5
|
import { buildDocumentPositions } from "./position-metadata.js";
|
|
6
|
+
import { expandManifestFragments } from "./manifest-schemas.js";
|
|
6
7
|
import { precompileDoc } from "./precompile.js";
|
|
7
8
|
import { documentToAst } from "./yaml-ast.js";
|
|
8
9
|
/** Append an actionable hint to raw yaml-parser messages that are otherwise
|
|
@@ -57,6 +58,21 @@ export function parseLoadedFile(source, requestedUrl, text, options) {
|
|
|
57
58
|
const migrations = options?.migrate
|
|
58
59
|
? migrateManifests({ source, manifests, entries: options.migrations })
|
|
59
60
|
: NO_MIGRATIONS;
|
|
61
|
+
// Shared structural fragments (`telo://manifest#/$defs/InvokeStep`) are
|
|
62
|
+
// expanded for EVERY consumer, deliberately ungated.
|
|
63
|
+
//
|
|
64
|
+
// They are not authoring sugar the way `imports:` or a `!ref` tag is — they are
|
|
65
|
+
// the analyzer's own closed set, and nothing downstream is equipped to meet one
|
|
66
|
+
// unresolved: the editor's schema resolver handles document-local `#/` refs
|
|
67
|
+
// only and THROWS on anything else, so a gated expansion took every canvas that
|
|
68
|
+
// renders a `Run` step down. Round-tripping is unaffected because a save writes
|
|
69
|
+
// the YAML documents the editor holds separately (`saveModuleFromDocuments`),
|
|
70
|
+
// never a manifest object — so unlike `migrate`, no expansion here can reach an
|
|
71
|
+
// author's file.
|
|
72
|
+
for (const manifest of manifests) {
|
|
73
|
+
if (manifest)
|
|
74
|
+
expandManifestFragments(manifest);
|
|
75
|
+
}
|
|
60
76
|
let env;
|
|
61
77
|
if (options?.compile) {
|
|
62
78
|
for (let i = 0; i < manifests.length; i++) {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two vocabularies a release speaks, and the arithmetic between them.
|
|
3
|
+
*
|
|
4
|
+
* A **kind** is what an author writes in a fragment (`Added`, `Fixed`, …). It is
|
|
5
|
+
* changie's vocabulary, kept because it drives two things at once: the semantic
|
|
6
|
+
* level of the bump, and the heading the entry lands under in the changelog. A
|
|
7
|
+
* **level** is what the version arithmetic consumes.
|
|
8
|
+
*
|
|
9
|
+
* The mapping is the only place the two meet, and it is deliberately total: an
|
|
10
|
+
* unrecognized kind is refused rather than defaulted, because a typo that
|
|
11
|
+
* degraded to `patch` would silently under-release a breaking change.
|
|
12
|
+
*/
|
|
13
|
+
/** Semantic level of a version move. */
|
|
14
|
+
export type BumpLevel = "major" | "minor" | "patch";
|
|
15
|
+
export declare function maxLevel(a: BumpLevel, b: BumpLevel): BumpLevel;
|
|
16
|
+
/**
|
|
17
|
+
* Fragment kinds, in changelog section order, each with the level it induces.
|
|
18
|
+
*
|
|
19
|
+
* `Changed` / `Removed` induce `major`, which the pre-1.0 guard then rejects —
|
|
20
|
+
* they are kept in the vocabulary rather than dropped so the rejection can name
|
|
21
|
+
* what was written and say why, instead of reporting an unknown kind.
|
|
22
|
+
*/
|
|
23
|
+
export declare const FRAGMENT_KINDS: {
|
|
24
|
+
readonly Added: "minor";
|
|
25
|
+
readonly Changed: "major";
|
|
26
|
+
readonly Deprecated: "minor";
|
|
27
|
+
readonly Removed: "major";
|
|
28
|
+
readonly Fixed: "patch";
|
|
29
|
+
readonly Security: "patch";
|
|
30
|
+
};
|
|
31
|
+
export type FragmentKind = keyof typeof FRAGMENT_KINDS;
|
|
32
|
+
/** Declaration order, which is also the order sections appear in a changelog
|
|
33
|
+
* release block. */
|
|
34
|
+
export declare const FRAGMENT_KIND_ORDER: readonly FragmentKind[];
|
|
35
|
+
export declare function isFragmentKind(value: unknown): value is FragmentKind;
|
|
36
|
+
export declare function levelOfKind(kind: FragmentKind): BumpLevel;
|
|
37
|
+
export declare function isReleaseVersion(value: unknown): value is string;
|
|
38
|
+
/** Apply `level` to `version`. Throws on a version this system cannot represent,
|
|
39
|
+
* rather than returning something plausible — every caller has already read the
|
|
40
|
+
* value out of a manifest it is about to rewrite. */
|
|
41
|
+
export declare function applyBump(version: string, level: BumpLevel): string;
|
|
42
|
+
/** Numeric comparison, so `0.10.0` sorts after `0.9.0`. Returns a negative
|
|
43
|
+
* number when `a` precedes `b`. An unparseable version sorts last rather than
|
|
44
|
+
* throwing — this is used for display ordering, not for decisions. */
|
|
45
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
46
|
+
//# sourceMappingURL=bump-level.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bump-level.d.ts","sourceRoot":"","sources":["../../src/release/bump-level.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wCAAwC;AACxC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAOpD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,CAE9D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;CAOmB,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,cAAc,CAAC;AAEvD;qBACqB;AACrB,eAAO,MAAM,mBAAmB,EAAE,SAAS,YAAY,EAEpC,CAAC;AAEpB,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAEzD;AAOD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED;;sDAEsD;AACtD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAWnE;AAED;;uEAEuE;AACvE,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS5D"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two vocabularies a release speaks, and the arithmetic between them.
|
|
3
|
+
*
|
|
4
|
+
* A **kind** is what an author writes in a fragment (`Added`, `Fixed`, …). It is
|
|
5
|
+
* changie's vocabulary, kept because it drives two things at once: the semantic
|
|
6
|
+
* level of the bump, and the heading the entry lands under in the changelog. A
|
|
7
|
+
* **level** is what the version arithmetic consumes.
|
|
8
|
+
*
|
|
9
|
+
* The mapping is the only place the two meet, and it is deliberately total: an
|
|
10
|
+
* unrecognized kind is refused rather than defaulted, because a typo that
|
|
11
|
+
* degraded to `patch` would silently under-release a breaking change.
|
|
12
|
+
*/
|
|
13
|
+
/** Ordering used whenever several levels reach one module — the maximum wins,
|
|
14
|
+
* because a module that inlines a breaking change is breaking for its own
|
|
15
|
+
* consumers. */
|
|
16
|
+
const LEVEL_RANK = { patch: 0, minor: 1, major: 2 };
|
|
17
|
+
export function maxLevel(a, b) {
|
|
18
|
+
return LEVEL_RANK[a] >= LEVEL_RANK[b] ? a : b;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Fragment kinds, in changelog section order, each with the level it induces.
|
|
22
|
+
*
|
|
23
|
+
* `Changed` / `Removed` induce `major`, which the pre-1.0 guard then rejects —
|
|
24
|
+
* they are kept in the vocabulary rather than dropped so the rejection can name
|
|
25
|
+
* what was written and say why, instead of reporting an unknown kind.
|
|
26
|
+
*/
|
|
27
|
+
export const FRAGMENT_KINDS = {
|
|
28
|
+
Added: "minor",
|
|
29
|
+
Changed: "major",
|
|
30
|
+
Deprecated: "minor",
|
|
31
|
+
Removed: "major",
|
|
32
|
+
Fixed: "patch",
|
|
33
|
+
Security: "patch",
|
|
34
|
+
};
|
|
35
|
+
/** Declaration order, which is also the order sections appear in a changelog
|
|
36
|
+
* release block. */
|
|
37
|
+
export const FRAGMENT_KIND_ORDER = Object.keys(FRAGMENT_KINDS);
|
|
38
|
+
export function isFragmentKind(value) {
|
|
39
|
+
return typeof value === "string" && value in FRAGMENT_KINDS;
|
|
40
|
+
}
|
|
41
|
+
export function levelOfKind(kind) {
|
|
42
|
+
return FRAGMENT_KINDS[kind];
|
|
43
|
+
}
|
|
44
|
+
/** A `major.minor.patch` triple. Pre-release and build metadata are not accepted:
|
|
45
|
+
* a module version is the tag an artifact publishes under and the value a pin
|
|
46
|
+
* resolves, and neither has a meaning for a suffix today. */
|
|
47
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)$/;
|
|
48
|
+
export function isReleaseVersion(value) {
|
|
49
|
+
return typeof value === "string" && VERSION.test(value);
|
|
50
|
+
}
|
|
51
|
+
/** Apply `level` to `version`. Throws on a version this system cannot represent,
|
|
52
|
+
* rather than returning something plausible — every caller has already read the
|
|
53
|
+
* value out of a manifest it is about to rewrite. */
|
|
54
|
+
export function applyBump(version, level) {
|
|
55
|
+
const match = VERSION.exec(version);
|
|
56
|
+
if (!match) {
|
|
57
|
+
throw new Error(`'${version}' is not a major.minor.patch version, so no ${level} bump can be derived from it.`);
|
|
58
|
+
}
|
|
59
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
60
|
+
if (level === "major")
|
|
61
|
+
return `${major + 1}.0.0`;
|
|
62
|
+
if (level === "minor")
|
|
63
|
+
return `${major}.${minor + 1}.0`;
|
|
64
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
65
|
+
}
|
|
66
|
+
/** Numeric comparison, so `0.10.0` sorts after `0.9.0`. Returns a negative
|
|
67
|
+
* number when `a` precedes `b`. An unparseable version sorts last rather than
|
|
68
|
+
* throwing — this is used for display ordering, not for decisions. */
|
|
69
|
+
export function compareVersions(a, b) {
|
|
70
|
+
const pa = VERSION.exec(a);
|
|
71
|
+
const pb = VERSION.exec(b);
|
|
72
|
+
if (!pa || !pb)
|
|
73
|
+
return pa ? -1 : pb ? 1 : a.localeCompare(b);
|
|
74
|
+
for (let i = 1; i <= 3; i++) {
|
|
75
|
+
const diff = Number(pa[i]) - Number(pb[i]);
|
|
76
|
+
if (diff !== 0)
|
|
77
|
+
return diff;
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering a module's `CHANGELOG.md` entry, and splicing it into the file.
|
|
3
|
+
*
|
|
4
|
+
* The output shape is the one changie was configured to emit — `## <version> -
|
|
5
|
+
* <date>`, `### <Kind>`, `* <body>` — so a module's history stays one document
|
|
6
|
+
* across the handover rather than changing format mid-file.
|
|
7
|
+
*
|
|
8
|
+
* Prepending rather than rewriting: a changelog is append-only history, and the
|
|
9
|
+
* only edit ever made to it is inserting the newest release above the previous
|
|
10
|
+
* one. Everything already written is untouched bytes.
|
|
11
|
+
*/
|
|
12
|
+
import { type FragmentKind } from "./bump-level.js";
|
|
13
|
+
export declare const CHANGELOG_HEADER = "# Changelog";
|
|
14
|
+
export interface ChangelogRelease {
|
|
15
|
+
readonly version: string;
|
|
16
|
+
/** `YYYY-MM-DD`. Passed in rather than read from a clock, so a plan renders
|
|
17
|
+
* identically whenever it is rendered and a test needs no clock control. */
|
|
18
|
+
readonly date: string;
|
|
19
|
+
readonly entries: readonly {
|
|
20
|
+
readonly kind: FragmentKind;
|
|
21
|
+
readonly body: string;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
/** One release block. Entries group under their kind, in the vocabulary's own
|
|
25
|
+
* order, so two releases never disagree about where `Fixed` sits. */
|
|
26
|
+
export declare function renderChangelogRelease(release: ChangelogRelease): string;
|
|
27
|
+
/**
|
|
28
|
+
* Insert a release block below the file's `# Changelog` header, creating the
|
|
29
|
+
* file's skeleton when it has none.
|
|
30
|
+
*
|
|
31
|
+
* A module with no changelog yet is the ordinary case for a new module, so this
|
|
32
|
+
* writes the header rather than failing — the alternative is a release that
|
|
33
|
+
* stops to ask for an empty file to be created by hand.
|
|
34
|
+
*/
|
|
35
|
+
export declare function prependChangelogRelease(existing: string | undefined, block: string): string;
|
|
36
|
+
//# sourceMappingURL=changelog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/release/changelog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEzE,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;iFAC6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrF;AAED;sEACsE;AACtE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAgBxE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAS3F"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering a module's `CHANGELOG.md` entry, and splicing it into the file.
|
|
3
|
+
*
|
|
4
|
+
* The output shape is the one changie was configured to emit — `## <version> -
|
|
5
|
+
* <date>`, `### <Kind>`, `* <body>` — so a module's history stays one document
|
|
6
|
+
* across the handover rather than changing format mid-file.
|
|
7
|
+
*
|
|
8
|
+
* Prepending rather than rewriting: a changelog is append-only history, and the
|
|
9
|
+
* only edit ever made to it is inserting the newest release above the previous
|
|
10
|
+
* one. Everything already written is untouched bytes.
|
|
11
|
+
*/
|
|
12
|
+
import { FRAGMENT_KIND_ORDER } from "./bump-level.js";
|
|
13
|
+
export const CHANGELOG_HEADER = "# Changelog";
|
|
14
|
+
/** One release block. Entries group under their kind, in the vocabulary's own
|
|
15
|
+
* order, so two releases never disagree about where `Fixed` sits. */
|
|
16
|
+
export function renderChangelogRelease(release) {
|
|
17
|
+
const byKind = new Map();
|
|
18
|
+
for (const entry of release.entries) {
|
|
19
|
+
const list = byKind.get(entry.kind);
|
|
20
|
+
if (list)
|
|
21
|
+
list.push(entry.body);
|
|
22
|
+
else
|
|
23
|
+
byKind.set(entry.kind, [entry.body]);
|
|
24
|
+
}
|
|
25
|
+
const lines = [`## ${release.version} - ${release.date}`];
|
|
26
|
+
for (const kind of FRAGMENT_KIND_ORDER) {
|
|
27
|
+
const bodies = byKind.get(kind);
|
|
28
|
+
if (!bodies)
|
|
29
|
+
continue;
|
|
30
|
+
lines.push(`### ${kind}`);
|
|
31
|
+
for (const body of bodies)
|
|
32
|
+
lines.push(`* ${body}`);
|
|
33
|
+
}
|
|
34
|
+
return lines.join("\n") + "\n";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Insert a release block below the file's `# Changelog` header, creating the
|
|
38
|
+
* file's skeleton when it has none.
|
|
39
|
+
*
|
|
40
|
+
* A module with no changelog yet is the ordinary case for a new module, so this
|
|
41
|
+
* writes the header rather than failing — the alternative is a release that
|
|
42
|
+
* stops to ask for an empty file to be created by hand.
|
|
43
|
+
*/
|
|
44
|
+
export function prependChangelogRelease(existing, block) {
|
|
45
|
+
const text = existing ?? "";
|
|
46
|
+
const header = text.match(/^#\s+Changelog[^\n]*\n/);
|
|
47
|
+
if (!header) {
|
|
48
|
+
const rest = text.trim();
|
|
49
|
+
return `${CHANGELOG_HEADER}\n\n${block}${rest ? `\n${rest}\n` : ""}`;
|
|
50
|
+
}
|
|
51
|
+
const after = text.slice(header[0].length).replace(/^\n+/, "");
|
|
52
|
+
return `${header[0]}\n${block}${after ? `\n${after}` : ""}`;
|
|
53
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A release fragment — one pending change, written by an author.
|
|
3
|
+
*
|
|
4
|
+
* The shape is changesets' (one file, several modules, one body) carrying
|
|
5
|
+
* changie's kind vocabulary, which is what lets one cross-cutting change be one
|
|
6
|
+
* file while the kind still drives both the level and the changelog section a
|
|
7
|
+
* line lands under. Changie's own file is the other arrangement — one module per
|
|
8
|
+
* file — so a change touching five modules meant five files repeating one
|
|
9
|
+
* sentence, and its key was the module's bare directory NAME, which two
|
|
10
|
+
* directories in different subtrees can share.
|
|
11
|
+
*
|
|
12
|
+
* A fragment names modules by **workspace-relative path**, the same key the
|
|
13
|
+
* ledger and every diagnostic use.
|
|
14
|
+
*
|
|
15
|
+
* They are plain YAML validated here, not a `Telo.*` kind: build-time repo state
|
|
16
|
+
* with no controller and no capability, which the runtime never loads.
|
|
17
|
+
*/
|
|
18
|
+
import { type FragmentKind } from "./bump-level.js";
|
|
19
|
+
/** A module's workspace-relative directory path — `modules/sql`, `apps/hub`. */
|
|
20
|
+
export type ModuleKey = string;
|
|
21
|
+
export interface ReleaseFragment {
|
|
22
|
+
/**
|
|
23
|
+
* Where this fragment was read from, workspace-relative. Carried so a
|
|
24
|
+
* diagnostic can name the file to fix and `apply` can delete the file it
|
|
25
|
+
* consumed.
|
|
26
|
+
*/
|
|
27
|
+
readonly source: string;
|
|
28
|
+
/** The directly-changed modules this fragment declares, each with its kind. */
|
|
29
|
+
readonly modules: ReadonlyMap<ModuleKey, FragmentKind>;
|
|
30
|
+
/** The changelog line. */
|
|
31
|
+
readonly body: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class FragmentError extends Error {
|
|
34
|
+
readonly source: string;
|
|
35
|
+
constructor(source: string, message: string);
|
|
36
|
+
}
|
|
37
|
+
export declare function parseFragment(text: string, source: string): ReleaseFragment;
|
|
38
|
+
/**
|
|
39
|
+
* Render a fragment, for `telo release add`.
|
|
40
|
+
*
|
|
41
|
+
* Serialized rather than templated so a long body folds the way the YAML writer
|
|
42
|
+
* folds it, and so a module path needing quotes gets them.
|
|
43
|
+
*/
|
|
44
|
+
export declare function serializeFragment(modules: ReadonlyMap<ModuleKey, FragmentKind>, body: string): string;
|
|
45
|
+
/** Module keys are POSIX-separated and carry no leading `./` or trailing slash,
|
|
46
|
+
* so the same directory written three ways is one key. */
|
|
47
|
+
export declare function normalizeModuleKey(key: string): ModuleKey;
|
|
48
|
+
//# sourceMappingURL=fragment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment.d.ts","sourceRoot":"","sources":["../../src/release/fragment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACvD,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,aAAc,SAAQ,KAAK;IAEpC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAIlB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CA4D3E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,EAC7C,IAAI,EAAE,MAAM,GACX,MAAM,CAMR;AAED;2DAC2D;AAC3D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAEzD"}
|