@superbee/core 0.2.0-pre.15 → 0.2.0-pre.16
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 +213 -0
- package/dist/backend.d.ts +3 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +7 -0
- package/dist/backend.js.map +1 -1
- package/dist/blob-contract.d.ts +80 -0
- package/dist/blob-contract.d.ts.map +1 -0
- package/dist/blob-contract.js +131 -0
- package/dist/blob-contract.js.map +1 -0
- package/dist/blob-journal.d.ts +117 -0
- package/dist/blob-journal.d.ts.map +1 -0
- package/dist/blob-journal.js +168 -0
- package/dist/blob-journal.js.map +1 -0
- package/dist/engine.d.ts +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js.map +1 -1
- package/dist/file-journaled-backend-internal.d.ts +2 -0
- package/dist/file-journaled-backend-internal.d.ts.map +1 -1
- package/dist/file-journaled-backend-internal.js +2 -0
- package/dist/file-journaled-backend-internal.js.map +1 -1
- package/dist/file-journaled-backend.d.ts +14 -2
- package/dist/file-journaled-backend.d.ts.map +1 -1
- package/dist/file-journaled-backend.js +245 -37
- package/dist/file-journaled-backend.js.map +1 -1
- package/dist/hosted-client/binding.d.ts +7 -0
- package/dist/hosted-client/binding.d.ts.map +1 -0
- package/dist/hosted-client/binding.js +10 -0
- package/dist/hosted-client/binding.js.map +1 -0
- package/dist/hosted-client/blob-delivery.d.ts +61 -0
- package/dist/hosted-client/blob-delivery.d.ts.map +1 -0
- package/dist/hosted-client/blob-delivery.js +147 -0
- package/dist/hosted-client/blob-delivery.js.map +1 -0
- package/dist/hosted-client/bundle-listing.d.ts +46 -0
- package/dist/hosted-client/bundle-listing.d.ts.map +1 -0
- package/dist/hosted-client/bundle-listing.js +36 -0
- package/dist/hosted-client/bundle-listing.js.map +1 -0
- package/dist/hosted-client/client.d.ts +155 -0
- package/dist/hosted-client/client.d.ts.map +1 -0
- package/dist/hosted-client/client.js +278 -0
- package/dist/hosted-client/client.js.map +1 -0
- package/dist/hosted-client/errors.d.ts +16 -0
- package/dist/hosted-client/errors.d.ts.map +1 -0
- package/dist/hosted-client/errors.js +22 -0
- package/dist/hosted-client/errors.js.map +1 -0
- package/dist/hosted-client/index.d.ts +23 -0
- package/dist/hosted-client/index.d.ts.map +1 -0
- package/dist/hosted-client/index.js +25 -0
- package/dist/hosted-client/index.js.map +1 -0
- package/dist/hosted-client/node.d.ts +70 -0
- package/dist/hosted-client/node.d.ts.map +1 -0
- package/dist/hosted-client/node.js +214 -0
- package/dist/hosted-client/node.js.map +1 -0
- package/dist/hosted-client/reference.d.ts +12 -0
- package/dist/hosted-client/reference.d.ts.map +1 -0
- package/dist/hosted-client/reference.js +29 -0
- package/dist/hosted-client/reference.js.map +1 -0
- package/dist/hosted-client/write.d.ts +191 -0
- package/dist/hosted-client/write.d.ts.map +1 -0
- package/dist/hosted-client/write.js +396 -0
- package/dist/hosted-client/write.js.map +1 -0
- package/dist/hosted-transport/answer-rows.d.ts +26 -0
- package/dist/hosted-transport/answer-rows.d.ts.map +1 -1
- package/dist/hosted-transport/answer-rows.js +59 -1
- package/dist/hosted-transport/answer-rows.js.map +1 -1
- package/dist/hosted-transport/blob-reads.d.ts +35 -0
- package/dist/hosted-transport/blob-reads.d.ts.map +1 -0
- package/dist/hosted-transport/blob-reads.js +179 -0
- package/dist/hosted-transport/blob-reads.js.map +1 -0
- package/dist/hosted-transport/blob-write.d.ts +34 -0
- package/dist/hosted-transport/blob-write.d.ts.map +1 -0
- package/dist/hosted-transport/blob-write.js +115 -0
- package/dist/hosted-transport/blob-write.js.map +1 -0
- package/dist/hosted-transport/carrier.d.ts +8 -9
- package/dist/hosted-transport/carrier.d.ts.map +1 -1
- package/dist/hosted-transport/carrier.js +40 -41
- package/dist/hosted-transport/carrier.js.map +1 -1
- package/dist/hosted-transport/index.d.ts +4 -4
- package/dist/hosted-transport/index.d.ts.map +1 -1
- package/dist/hosted-transport/index.js +4 -4
- package/dist/hosted-transport/index.js.map +1 -1
- package/dist/hosted-transport/read-adapter.d.ts +6 -0
- package/dist/hosted-transport/read-adapter.d.ts.map +1 -1
- package/dist/hosted-transport/read-adapter.js +11 -0
- package/dist/hosted-transport/read-adapter.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/journaled-backend.d.ts +10 -2
- package/dist/journaled-backend.d.ts.map +1 -1
- package/dist/journaled-backend.js +3 -3
- package/dist/journaled-backend.js.map +1 -1
- package/dist/link-types.d.ts +26 -0
- package/dist/link-types.d.ts.map +1 -0
- package/dist/link-types.js +57 -0
- package/dist/link-types.js.map +1 -0
- package/dist/platform.d.ts +4 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +16 -0
- package/dist/platform.js.map +1 -1
- package/dist/recipe-lifecycle/errors.d.ts +77 -0
- package/dist/recipe-lifecycle/errors.d.ts.map +1 -0
- package/dist/recipe-lifecycle/errors.js +96 -0
- package/dist/recipe-lifecycle/errors.js.map +1 -0
- package/dist/recipe-lifecycle/evolution.d.ts +71 -0
- package/dist/recipe-lifecycle/evolution.d.ts.map +1 -0
- package/dist/recipe-lifecycle/evolution.js +659 -0
- package/dist/recipe-lifecycle/evolution.js.map +1 -0
- package/dist/recipe-lifecycle/index.d.ts +23 -0
- package/dist/recipe-lifecycle/index.d.ts.map +1 -0
- package/dist/recipe-lifecycle/index.js +19 -0
- package/dist/recipe-lifecycle/index.js.map +1 -0
- package/dist/recipe-lifecycle/install.d.ts +111 -0
- package/dist/recipe-lifecycle/install.d.ts.map +1 -0
- package/dist/recipe-lifecycle/install.js +412 -0
- package/dist/recipe-lifecycle/install.js.map +1 -0
- package/dist/recipe-lifecycle/legacy-aliases.d.ts +16 -0
- package/dist/recipe-lifecycle/legacy-aliases.d.ts.map +1 -0
- package/dist/recipe-lifecycle/legacy-aliases.js +51 -0
- package/dist/recipe-lifecycle/legacy-aliases.js.map +1 -0
- package/dist/recipe-lifecycle/stamp.d.ts +98 -0
- package/dist/recipe-lifecycle/stamp.d.ts.map +1 -0
- package/dist/recipe-lifecycle/stamp.js +260 -0
- package/dist/recipe-lifecycle/stamp.js.map +1 -0
- package/dist/recipes.d.ts +5 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +5 -0
- package/dist/recipes.js.map +1 -1
- package/dist/storage.d.ts +3 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +3 -0
- package/dist/storage.js.map +1 -1
- package/dist/uncertain-write.d.ts +70 -2
- package/dist/uncertain-write.d.ts.map +1 -1
- package/dist/uncertain-write.js +45 -32
- package/dist/uncertain-write.js.map +1 -1
- package/dist/write-identity.d.ts +5 -0
- package/dist/write-identity.d.ts.map +1 -0
- package/dist/write-identity.js +9 -0
- package/dist/write-identity.js.map +1 -0
- package/package.json +13 -1
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
// Recipe installation: create-only, expect-absent CAS per artifact through the shared document
|
|
2
|
+
// mutation boundary, so a built-in and an external recipe install through the same function and
|
|
3
|
+
// an existing document is never overwritten. Storage-neutral: no Node globals or builtins.
|
|
4
|
+
import { query, readBlob, readBundleOkfVersion, readDoc, writeBlob } from "../bundle-ops.js";
|
|
5
|
+
import { resolveContentType } from "../content-type.js";
|
|
6
|
+
import { mutateDocument } from "../document-mutation.js";
|
|
7
|
+
import { CONVENTIONS_PREFIX, PROGRESS_STATUS_FIELD, progressStatusStorageField } from "../kinds.js";
|
|
8
|
+
import { okfValuesEqual } from "../okf-authored-values.js";
|
|
9
|
+
import { PAGE_REGISTRY_PREFIX, parseRegistration, VIEW_REGISTRY_PREFIX } from "../page.js";
|
|
10
|
+
import { RECIPE_PROGRESS_STATUS_TOKEN } from "../recipes.js";
|
|
11
|
+
import { VersionConflict } from "../versioning.js";
|
|
12
|
+
import { RecipeAssetConflict, RecipeEditionChanged, RecipeInputError } from "./errors.js";
|
|
13
|
+
import { RECIPE_STAMP_KEY, recipeStampIdentity, recipeStampState, withRecipeStamp, worstRecipeStampState, } from "./stamp.js";
|
|
14
|
+
import { findLegacyViewConvention, governsKind, legacyEntryAlias, legacyRegistryAlias, VIEW_KIND_NAME, } from "./legacy-aliases.js";
|
|
15
|
+
function materializeRecipeBody(body, storageField) {
|
|
16
|
+
return body.replaceAll(RECIPE_PROGRESS_STATUS_TOKEN, storageField);
|
|
17
|
+
}
|
|
18
|
+
const RECIPE_WRITE_REGISTRY = { kinds: new Map(), warnings: [] };
|
|
19
|
+
function plainRecord(value) {
|
|
20
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
21
|
+
? value
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
function renameLogicalFieldMap(value, storageField, recipeId, docId) {
|
|
25
|
+
const record = plainRecord(value);
|
|
26
|
+
if (!record || !Object.prototype.hasOwnProperty.call(record, PROGRESS_STATUS_FIELD))
|
|
27
|
+
return value;
|
|
28
|
+
if (storageField !== PROGRESS_STATUS_FIELD
|
|
29
|
+
&& Object.prototype.hasOwnProperty.call(record, storageField)) {
|
|
30
|
+
throw new RecipeInputError(`recipe '${recipeId}' convention '${docId}' declares both logical '${PROGRESS_STATUS_FIELD}' and storage field '${storageField}'`);
|
|
31
|
+
}
|
|
32
|
+
return Object.fromEntries(Object.entries(record).map(([field, fieldValue]) => [
|
|
33
|
+
field === PROGRESS_STATUS_FIELD ? storageField : field,
|
|
34
|
+
fieldValue,
|
|
35
|
+
]));
|
|
36
|
+
}
|
|
37
|
+
/** Materialize explicit logical recipe fields into the target edition's physical convention keys. */
|
|
38
|
+
export function materializeRecipeForEdition(recipe, okfVersion) {
|
|
39
|
+
const storageField = progressStatusStorageField(okfVersion);
|
|
40
|
+
if (!storageField) {
|
|
41
|
+
throw new RecipeInputError(`recipe '${recipe.id}' cannot target unsupported OKF mutation version '${okfVersion}'`);
|
|
42
|
+
}
|
|
43
|
+
const docs = recipe.docs.map((doc) => {
|
|
44
|
+
const fields = plainRecord(doc.frontmatter.fields);
|
|
45
|
+
if (!fields)
|
|
46
|
+
return doc;
|
|
47
|
+
const listField = (value) => {
|
|
48
|
+
if (!Array.isArray(value) || !value.includes(PROGRESS_STATUS_FIELD))
|
|
49
|
+
return value;
|
|
50
|
+
if (value.includes(storageField)) {
|
|
51
|
+
throw new RecipeInputError(`recipe '${recipe.id}' convention '${doc.id}' declares both logical '${PROGRESS_STATUS_FIELD}' and storage field '${storageField}'`);
|
|
52
|
+
}
|
|
53
|
+
return value.map((field) => field === PROGRESS_STATUS_FIELD ? storageField : field);
|
|
54
|
+
};
|
|
55
|
+
const materializedFields = { ...fields };
|
|
56
|
+
for (const key of ["required", "optional"]) {
|
|
57
|
+
if (Object.prototype.hasOwnProperty.call(fields, key)) {
|
|
58
|
+
materializedFields[key] = listField(fields[key]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const key of ["values", "value_descriptions", "terminal", "descriptions", "types"]) {
|
|
62
|
+
if (Object.prototype.hasOwnProperty.call(fields, key)) {
|
|
63
|
+
materializedFields[key] = renameLogicalFieldMap(fields[key], storageField, recipe.id, doc.id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
...doc,
|
|
68
|
+
frontmatter: { ...doc.frontmatter, fields: materializedFields },
|
|
69
|
+
body: materializeRecipeBody(doc.body, storageField),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
return { ...recipe, docs };
|
|
73
|
+
}
|
|
74
|
+
export function recipeDocumentForApply(doc, okfVersion, now) {
|
|
75
|
+
return okfVersion === "0.1"
|
|
76
|
+
? { ...doc, frontmatter: { ...doc.frontmatter, timestamp: now } }
|
|
77
|
+
: { ...doc, frontmatter: { ...doc.frontmatter } };
|
|
78
|
+
}
|
|
79
|
+
async function createRecipeDocument(bundle, doc, okfVersion, now) {
|
|
80
|
+
const result = await mutateDocument({
|
|
81
|
+
bundle,
|
|
82
|
+
id: doc.id,
|
|
83
|
+
mode: "create-only",
|
|
84
|
+
registry: RECIPE_WRITE_REGISTRY,
|
|
85
|
+
strict: false,
|
|
86
|
+
// Installed definitions must stay byte-comparable to their recipe source (sameInstalledDoc
|
|
87
|
+
// strips generated.at but not an engine-seeded generated.by), so never seed a clock here.
|
|
88
|
+
seedGenerationClock: false,
|
|
89
|
+
now: () => now,
|
|
90
|
+
buildCandidate: (_existing, context) => {
|
|
91
|
+
if (context.okfVersion !== okfVersion) {
|
|
92
|
+
throw new RecipeEditionChanged(okfVersion, context.okfVersion, "installation");
|
|
93
|
+
}
|
|
94
|
+
return { frontmatter: { ...doc.frontmatter }, body: doc.body };
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
return result.doc;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Install `recipe` through the shared document-mutation boundary using expect-absent CAS. Recipe
|
|
101
|
+
* conventions may declare Superbee's logical `progress_status`; this installer materializes the
|
|
102
|
+
* concrete field for the bundle edition before any write. V0.1 retains the historical install-time
|
|
103
|
+
* `timestamp` (`options.now`, default the current time); v0.2 preserves explicitly supplied legacy
|
|
104
|
+
* fields but does not invent them. A `VersionConflict` remains an idempotent existing-doc result,
|
|
105
|
+
* never a clobber.
|
|
106
|
+
*/
|
|
107
|
+
export async function installRecipe(bundle, recipe, options = {}) {
|
|
108
|
+
const now = options.now ?? new Date().toISOString();
|
|
109
|
+
const okfVersion = await readBundleOkfVersion(bundle) ?? "0.1";
|
|
110
|
+
const source = recipe;
|
|
111
|
+
recipe = materializeRecipeForEdition(recipe, okfVersion);
|
|
112
|
+
const identity = recipeStampIdentity(source, recipe);
|
|
113
|
+
await assertPortableTargetsCompatible(bundle, recipe, now, okfVersion);
|
|
114
|
+
// Legacy-alias probes (see the module comment above the alias helpers): resolved lazily, once.
|
|
115
|
+
const legacyConventionId = recipe.docs.some((d) => governsKind(d, VIEW_KIND_NAME))
|
|
116
|
+
? await findLegacyViewConvention(bundle)
|
|
117
|
+
: null;
|
|
118
|
+
let legacyRegistryDocs = null;
|
|
119
|
+
const legacyRegistryDoc = async (id) => {
|
|
120
|
+
legacyRegistryDocs ??= new Map((await query(bundle, { prefix: PAGE_REGISTRY_PREFIX })).map((doc) => [doc.id, doc]));
|
|
121
|
+
return legacyRegistryDocs.get(id);
|
|
122
|
+
};
|
|
123
|
+
const migrationWarnings = [];
|
|
124
|
+
const migrationHelp = "run `node scripts/migrate-legacy-view-names.mjs --dir <bundle-root>` from the Superbee repository root to migrate it in place";
|
|
125
|
+
const docs = [];
|
|
126
|
+
const stamps = [];
|
|
127
|
+
const restampIds = [];
|
|
128
|
+
const foreignIds = [];
|
|
129
|
+
for (const d of recipe.docs) {
|
|
130
|
+
if (legacyConventionId !== null && governsKind(d, VIEW_KIND_NAME)) {
|
|
131
|
+
// A convention still governing the RETIRED legacy name is unmigrated state: skip creating
|
|
132
|
+
// the current-name convention (never two conventions for one kind), but as an explicit
|
|
133
|
+
// NON-SUCCESS — not a satisfied-looking skip.
|
|
134
|
+
docs.push({ id: d.id, changed: false, migration_required: legacyConventionId });
|
|
135
|
+
stamps.push("missing");
|
|
136
|
+
migrationWarnings.push({
|
|
137
|
+
code: "MIGRATION_REQUIRED",
|
|
138
|
+
message: `'${legacyConventionId}' still governs the retired legacy 'Page' kind name — ` +
|
|
139
|
+
`'${d.id}' was not installed; ${migrationHelp}`,
|
|
140
|
+
severity: "warning",
|
|
141
|
+
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// The stamp lands in the convention's own create: it exists exactly when the convention does.
|
|
145
|
+
let doc = withRecipeStamp(recipeDocumentForApply(d, okfVersion, now), identity);
|
|
146
|
+
let changed = true;
|
|
147
|
+
let sourceDiffers = false;
|
|
148
|
+
try {
|
|
149
|
+
doc = await createRecipeDocument(bundle, doc, okfVersion, now);
|
|
150
|
+
stamps.push("current");
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err instanceof VersionConflict) {
|
|
154
|
+
const existing = await readDoc(bundle, doc.id);
|
|
155
|
+
const existingStamp = recipeStampState(existing, identity);
|
|
156
|
+
stamps.push(existingStamp);
|
|
157
|
+
if (existingStamp === "stale" || existingStamp === "missing")
|
|
158
|
+
restampIds.push(doc.id);
|
|
159
|
+
else if (existingStamp === "foreign")
|
|
160
|
+
foreignIds.push(doc.id);
|
|
161
|
+
if (!sameInstalledDoc(existing, doc, okfVersion)) {
|
|
162
|
+
sourceDiffers = true;
|
|
163
|
+
migrationWarnings.push({
|
|
164
|
+
code: "RECIPE_SOURCE_DIFFERS",
|
|
165
|
+
message: `recipe '${recipe.id}' source for '${doc.id}.md' differs from the existing convention; ` +
|
|
166
|
+
"the existing bundle content was left untouched — run 'recipe evolve <same-name-or-path>' to inspect a safe additive upgrade plan",
|
|
167
|
+
severity: "warning",
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
changed = false;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
docs.push({ id: doc.id, changed, ...(sourceDiffers ? { source_differs: true } : {}) });
|
|
177
|
+
}
|
|
178
|
+
const pages = [];
|
|
179
|
+
for (const page of recipe.pages) {
|
|
180
|
+
const registryAlias = legacyRegistryAlias(page.registry.id);
|
|
181
|
+
const entryAlias = legacyEntryAlias(page.entry);
|
|
182
|
+
const aliasDoc = registryAlias !== null && entryAlias !== null ? await legacyRegistryDoc(registryAlias) : undefined;
|
|
183
|
+
if (registryAlias !== null && entryAlias !== null && aliasDoc !== undefined) {
|
|
184
|
+
// Skip ONLY on a COMPLETE legacy pair: a partial legacy leftover (registry doc without its
|
|
185
|
+
// blob) must not suppress the new install — that would leave no working card at all.
|
|
186
|
+
// Creating under the new ids is always safe (expect-absent CAS; ids never collide across
|
|
187
|
+
// prefixes), and the leftover is the audit's business, not the installer's.
|
|
188
|
+
const legacyBlob = await readBlob(bundle, entryAlias);
|
|
189
|
+
if (legacyBlob !== null) {
|
|
190
|
+
// The counterpart's KIND decides the outcome: a registering View at the
|
|
191
|
+
// legacy location genuinely satisfies the artifact; a RETIRED-name (Page-typed or
|
|
192
|
+
// otherwise non-registering) counterpart holds the slot but no longer works — an
|
|
193
|
+
// explicit non-success naming the remedy, never a satisfied-looking skip.
|
|
194
|
+
const registers = parseRegistration(aliasDoc.id, aliasDoc.frontmatter) !== null;
|
|
195
|
+
if (registers) {
|
|
196
|
+
pages.push({
|
|
197
|
+
registry_id: page.registry.id,
|
|
198
|
+
entry: page.entry,
|
|
199
|
+
registry_changed: false,
|
|
200
|
+
entry_changed: false,
|
|
201
|
+
changed: false,
|
|
202
|
+
legacy_present: { registry: registryAlias, entry: entryAlias },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
pages.push({
|
|
207
|
+
registry_id: page.registry.id,
|
|
208
|
+
entry: page.entry,
|
|
209
|
+
registry_changed: false,
|
|
210
|
+
entry_changed: false,
|
|
211
|
+
changed: false,
|
|
212
|
+
migration_required: { registry: registryAlias, entry: entryAlias },
|
|
213
|
+
});
|
|
214
|
+
migrationWarnings.push({
|
|
215
|
+
code: "MIGRATION_REQUIRED",
|
|
216
|
+
message: `'${registryAlias}' holds this artifact's slot but still carries the retired legacy names ` +
|
|
217
|
+
`and does not register — '${page.registry.id}' was not installed; ${migrationHelp}`,
|
|
218
|
+
severity: "warning",
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const desiredBytes = new TextEncoder().encode(page.html);
|
|
225
|
+
let entryChanged = true;
|
|
226
|
+
try {
|
|
227
|
+
await writeBlob(bundle, page.entry, desiredBytes, undefined, { expectedVersion: null });
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
if (!(err instanceof VersionConflict))
|
|
231
|
+
throw err;
|
|
232
|
+
const existing = await readBlob(bundle, page.entry);
|
|
233
|
+
const bytesMatch = existing !== null && sameBytes(existing.bytes, desiredBytes);
|
|
234
|
+
const sameContentType = existing?.contentType === resolveContentType(page.entry);
|
|
235
|
+
if (!bytesMatch || !sameContentType)
|
|
236
|
+
throw new RecipeAssetConflict(recipe.id, page.entry);
|
|
237
|
+
entryChanged = false;
|
|
238
|
+
}
|
|
239
|
+
let registry = recipeDocumentForApply(page.registry, okfVersion, now);
|
|
240
|
+
let registryChanged = true;
|
|
241
|
+
try {
|
|
242
|
+
registry = await createRecipeDocument(bundle, registry, okfVersion, now);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
if (!(err instanceof VersionConflict))
|
|
246
|
+
throw err;
|
|
247
|
+
const existing = await readDoc(bundle, registry.id);
|
|
248
|
+
if (!sameInstalledDoc(existing, registry, okfVersion))
|
|
249
|
+
throw new RecipeAssetConflict(recipe.id, `${registry.id}.md`);
|
|
250
|
+
registryChanged = false;
|
|
251
|
+
}
|
|
252
|
+
pages.push({
|
|
253
|
+
registry_id: registry.id,
|
|
254
|
+
entry: page.entry,
|
|
255
|
+
registry_changed: registryChanged,
|
|
256
|
+
entry_changed: entryChanged,
|
|
257
|
+
changed: registryChanged || entryChanged,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const references = [];
|
|
261
|
+
for (const reference of recipe.references) {
|
|
262
|
+
let desired = recipeDocumentForApply(reference.doc, okfVersion, now);
|
|
263
|
+
let changed = true;
|
|
264
|
+
try {
|
|
265
|
+
desired = await createRecipeDocument(bundle, desired, okfVersion, now);
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
if (!(err instanceof VersionConflict))
|
|
269
|
+
throw err;
|
|
270
|
+
const existing = await readDoc(bundle, desired.id);
|
|
271
|
+
if (!sameInstalledDoc(existing, desired, okfVersion))
|
|
272
|
+
throw new RecipeAssetConflict(recipe.id, `${desired.id}.md`);
|
|
273
|
+
changed = false;
|
|
274
|
+
}
|
|
275
|
+
references.push({ id: desired.id, changed });
|
|
276
|
+
}
|
|
277
|
+
const artifacts = [
|
|
278
|
+
...docs,
|
|
279
|
+
...pages,
|
|
280
|
+
...references,
|
|
281
|
+
];
|
|
282
|
+
const sourceDiffers = docs.filter((doc) => doc.source_differs).length;
|
|
283
|
+
const counts = {
|
|
284
|
+
created: artifacts.filter((a) => a.changed).length,
|
|
285
|
+
existing: artifacts.filter((a) => !a.changed && a.legacy_present === undefined && a.migration_required === undefined &&
|
|
286
|
+
!("source_differs" in a && a.source_differs === true))
|
|
287
|
+
.length,
|
|
288
|
+
legacy_present: artifacts.filter((a) => a.legacy_present !== undefined).length,
|
|
289
|
+
migration_required: artifacts.filter((a) => a.migration_required !== undefined).length,
|
|
290
|
+
...(sourceDiffers > 0 ? { source_differs: sourceDiffers } : {}),
|
|
291
|
+
};
|
|
292
|
+
return {
|
|
293
|
+
id: recipe.id,
|
|
294
|
+
version: recipe.version,
|
|
295
|
+
source: recipe.source,
|
|
296
|
+
docs,
|
|
297
|
+
pages,
|
|
298
|
+
references,
|
|
299
|
+
counts,
|
|
300
|
+
changed: docs.some((d) => d.changed) ||
|
|
301
|
+
pages.some((page) => page.changed) ||
|
|
302
|
+
references.some((reference) => reference.changed),
|
|
303
|
+
stamp: worstRecipeStampState(stamps),
|
|
304
|
+
restamp_ids: restampIds.sort(),
|
|
305
|
+
foreign_ids: foreignIds.sort(),
|
|
306
|
+
warnings: [...recipe.warnings, ...migrationWarnings],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
async function assertPortableTargetsCompatible(bundle, recipe, now, okfVersion) {
|
|
310
|
+
const registries = new Map();
|
|
311
|
+
if (recipe.pages.length > 0) {
|
|
312
|
+
// Both accepted registry prefixes (views-registry/ current, pages-registry/ legacy) — the
|
|
313
|
+
// query takes ONE prefix, so run it per prefix and merge (ids never collide across prefixes).
|
|
314
|
+
for (const prefix of [PAGE_REGISTRY_PREFIX, VIEW_REGISTRY_PREFIX]) {
|
|
315
|
+
const registryDocs = await query(bundle, { prefix });
|
|
316
|
+
for (const doc of registryDocs)
|
|
317
|
+
registries.set(doc.id, doc);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
for (const page of recipe.pages) {
|
|
321
|
+
const existingBlob = await readBlob(bundle, page.entry);
|
|
322
|
+
if (existingBlob) {
|
|
323
|
+
const desiredBytes = new TextEncoder().encode(page.html);
|
|
324
|
+
const bytesMatch = sameBytes(existingBlob.bytes, desiredBytes);
|
|
325
|
+
const sameContentType = existingBlob.contentType === resolveContentType(page.entry);
|
|
326
|
+
if (!bytesMatch || !sameContentType)
|
|
327
|
+
throw new RecipeAssetConflict(recipe.id, page.entry);
|
|
328
|
+
}
|
|
329
|
+
const existingRegistry = registries.get(page.registry.id);
|
|
330
|
+
if (existingRegistry) {
|
|
331
|
+
const desiredRegistry = recipeDocumentForApply(page.registry, okfVersion, now);
|
|
332
|
+
if (!sameInstalledDoc(existingRegistry, desiredRegistry, okfVersion)) {
|
|
333
|
+
throw new RecipeAssetConflict(recipe.id, `${page.registry.id}.md`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const installedReferences = new Map();
|
|
338
|
+
if (recipe.references.length > 0) {
|
|
339
|
+
const referenceDocs = await query(bundle, { prefix: "references/" });
|
|
340
|
+
for (const doc of referenceDocs)
|
|
341
|
+
installedReferences.set(doc.id, doc);
|
|
342
|
+
}
|
|
343
|
+
for (const reference of recipe.references) {
|
|
344
|
+
const existing = installedReferences.get(reference.doc.id);
|
|
345
|
+
if (!existing)
|
|
346
|
+
continue;
|
|
347
|
+
const desired = recipeDocumentForApply(reference.doc, okfVersion, now);
|
|
348
|
+
if (!sameInstalledDoc(existing, desired, okfVersion)) {
|
|
349
|
+
throw new RecipeAssetConflict(recipe.id, `${reference.doc.id}.md`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/** Byte equality of two blob payloads. */
|
|
354
|
+
function sameBytes(a, b) {
|
|
355
|
+
if (a.length !== b.length)
|
|
356
|
+
return false;
|
|
357
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
358
|
+
if (a[index] !== b[index])
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
export function sameInstalledDoc(existing, desired, okfVersion) {
|
|
364
|
+
// The recipe stamp is install metadata, never definition content.
|
|
365
|
+
const { timestamp: _existingTimestamp, [RECIPE_STAMP_KEY]: _existingStamp, ...existingFrontmatter } = existing.frontmatter;
|
|
366
|
+
const { timestamp: _desiredTimestamp, [RECIPE_STAMP_KEY]: _desiredStamp, ...desiredFrontmatter } = desired.frontmatter;
|
|
367
|
+
// A reading-order placement the bundle added to an installed convention is not drift: the
|
|
368
|
+
// recipe declares none, and evolution keeps it (BUNDLE_LOCAL_PLACEMENT in evolution.ts).
|
|
369
|
+
if (desiredFrontmatter.order === undefined)
|
|
370
|
+
delete existingFrontmatter.order;
|
|
371
|
+
if (okfVersion === "0.2") {
|
|
372
|
+
for (const frontmatter of [existingFrontmatter, desiredFrontmatter]) {
|
|
373
|
+
const generated = plainRecord(frontmatter.generated);
|
|
374
|
+
if (!generated)
|
|
375
|
+
continue;
|
|
376
|
+
const { at: _at, ...rest } = generated;
|
|
377
|
+
frontmatter.generated = rest;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return okfValuesEqual(existingFrontmatter, desiredFrontmatter) && existing.body === desired.body;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* The convention docs currently present under `conventions/`, by id — ONE round-trip
|
|
384
|
+
* (backend-agnostic, works over `--remote`), used by `recipes` to report whether a built-in is
|
|
385
|
+
* already applied to `bundle` (every one of its docs' ids present) AND whether any installed
|
|
386
|
+
* doc's content differs from the recipe source (the listing's `drift` bit). The query was always
|
|
387
|
+
* a full read; returning the docs instead of discarding their content costs zero added I/O.
|
|
388
|
+
*/
|
|
389
|
+
export async function installedConventionDocs(bundle) {
|
|
390
|
+
const docs = await query(bundle, { prefix: CONVENTIONS_PREFIX });
|
|
391
|
+
return new Map(docs.map((d) => [d.id, d]));
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* True when at least one of `recipe`'s installed docs differs in content from the recipe source
|
|
395
|
+
* (the same `sameInstalledDoc` comparison `installRecipe` makes; timestamp-insensitive). Honest at
|
|
396
|
+
* the literal level only: drift can be DELIBERATE — a dismissal record occupying the canonical
|
|
397
|
+
* id, or a kind legitimately evolved via `kind field add` / `recipe evolve`. The listing pairs
|
|
398
|
+
* the bit with descriptive help and NO fixing command (design appendix O2): a proactive "fix"
|
|
399
|
+
* pointer here would re-propose exactly what a `kind dismiss` recorded declining.
|
|
400
|
+
*/
|
|
401
|
+
export function recipeDrifts(recipe, installed, okfVersion, now) {
|
|
402
|
+
const materialized = materializeRecipeForEdition(recipe, okfVersion);
|
|
403
|
+
return materialized.docs.some((doc) => {
|
|
404
|
+
const existing = installed.get(doc.id);
|
|
405
|
+
return existing !== undefined && !sameInstalledDoc(existing, recipeDocumentForApply(doc, okfVersion, now), okfVersion);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/** True when every convention doc `recipe` installs is already present in `appliedIds`. */
|
|
409
|
+
export function isRecipeApplied(recipe, appliedIds) {
|
|
410
|
+
return recipe.docs.every((doc) => appliedIds.has(doc.id));
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/recipe-lifecycle/install.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,gGAAgG;AAChG,2FAA2F;AAC3F,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,0BAA0B,EAAqB,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,4BAA4B,EAAqB,MAAM,eAAe,CAAC;AAGhF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,GAGtB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,SAAS,qBAAqB,CAAC,IAAY,EAAE,YAAoB;IAC/D,OAAO,IAAI,CAAC,UAAU,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;AACrE,CAAC;AAyED,MAAM,qBAAqB,GAAiB,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAE/E,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAC,KAAgC;QAClC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAc,EACd,YAAoB,EACpB,QAAgB,EAChB,KAAgB;IAEhB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,qBAAqB,CAAC;QAAE,OAAO,KAAK,CAAC;IAClG,IACE,YAAY,KAAK,qBAAqB;WACnC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7D,CAAC;QACD,MAAM,IAAI,gBAAgB,CACxB,WAAW,QAAQ,iBAAiB,KAAK,4BAA4B,qBAAqB,wBAAwB,YAAY,GAAG,CAClI,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;QAClD,KAAK,KAAK,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK;QACtD,UAAU;KACX,CAAC,CACH,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,2BAA2B,CACzC,MAAoB,EACpB,UAAkB;IAElB,MAAM,YAAY,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,gBAAgB,CACxB,WAAW,MAAM,CAAC,EAAE,qDAAqD,UAAU,GAAG,CACvF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC;QACxB,MAAM,SAAS,GAAG,CAAC,KAAc,EAAW,EAAE;YAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,qBAAqB,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClF,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,gBAAgB,CACxB,WAAW,MAAM,CAAC,EAAE,iBAAiB,GAAG,CAAC,EAAE,4BAA4B,qBAAqB,wBAAwB,YAAY,GAAG,CACpI,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACtF,CAAC,CAAC;QACF,MAAM,kBAAkB,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;QAClE,KAAK,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;gBACtD,kBAAkB,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,oBAAoB,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC;YACxF,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;gBACtD,kBAAkB,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAChG,CAAC;QACH,CAAC;QACD,OAAO;YACL,GAAG,GAAG;YACN,WAAW,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAC/D,IAAI,EAAE,qBAAqB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;SACpD,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,GAAgB,EAChB,UAAkB,EAClB,GAAW;IAEX,OAAO,UAAU,KAAK,KAAK;QACzB,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,WAAW,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE;QACjE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,WAAW,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;AACtD,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,MAAc,EACd,GAAgB,EAChB,UAAkB,EAClB,GAAW;IAEX,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,MAAM;QACN,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,qBAAqB;QAC/B,MAAM,EAAE,KAAK;QACb,2FAA2F;QAC3F,0FAA0F;QAC1F,mBAAmB,EAAE,KAAK;QAC1B,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG;QACd,cAAc,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;YACrC,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACtC,MAAM,IAAI,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YACjF,CAAC;YACD,OAAO,EAAE,WAAW,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACjE,CAAC;KACF,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,GAAG,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,MAAoB,EACpB,UAA4B,EAAE;IAE9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,GAAG,2BAA2B,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAwB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1E,MAAM,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAEvE,+FAA+F;IAC/F,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAChF,CAAC,CAAC,MAAM,wBAAwB,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,kBAAkB,GAAuC,IAAI,CAAC;IAClE,MAAM,iBAAiB,GAAG,KAAK,EAAE,EAAa,EAAoC,EAAE;QAClF,kBAAkB,KAAK,IAAI,GAAG,CAC5B,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CACpF,CAAC;QACF,OAAO,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC;IACF,MAAM,iBAAiB,GAAwB,EAAE,CAAC;IAClD,MAAM,aAAa,GACjB,+HAA+H,CAAC;IAElI,MAAM,IAAI,GAAsB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,kBAAkB,KAAK,IAAI,IAAI,WAAW,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC;YAClE,0FAA0F;YAC1F,uFAAuF;YACvF,8CAA8C;YAC9C,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAChF,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvB,iBAAiB,CAAC,IAAI,CAAC;gBACrB,IAAI,EAAE,oBAAoB;gBAC1B,OAAO,EACL,IAAI,kBAAkB,wDAAwD;oBAC9E,IAAI,CAAC,CAAC,EAAE,wBAAwB,aAAa,EAAE;gBACjD,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,8FAA8F;QAC9F,IAAI,GAAG,GAAG,eAAe,CAAC,sBAAsB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAChF,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,eAAe,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/C,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAC3D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC3B,IAAI,aAAa,KAAK,OAAO,IAAI,aAAa,KAAK,SAAS;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;qBACjF,IAAI,aAAa,KAAK,SAAS;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC9D,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC;oBACjD,aAAa,GAAG,IAAI,CAAC;oBACrB,iBAAiB,CAAC,IAAI,CAAC;wBACrB,IAAI,EAAE,uBAAuB;wBAC7B,OAAO,EACL,WAAW,MAAM,CAAC,EAAE,iBAAiB,GAAG,CAAC,EAAE,6CAA6C;4BACxF,kIAAkI;wBACpI,QAAQ,EAAE,SAAS;qBACpB,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,aAAa,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,aAAa,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpH,IAAI,aAAa,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5E,2FAA2F;YAC3F,qFAAqF;YACrF,yFAAyF;YACzF,4EAA4E;YAC5E,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACtD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,wEAAwE;gBACxE,kFAAkF;gBAClF,iFAAiF;gBACjF,0EAA0E;gBAC1E,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;gBAChF,IAAI,SAAS,EAAE,CAAC;oBACd,KAAK,CAAC,IAAI,CAAC;wBACT,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;wBAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,gBAAgB,EAAE,KAAK;wBACvB,aAAa,EAAE,KAAK;wBACpB,OAAO,EAAE,KAAK;wBACd,cAAc,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE;qBAC/D,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CAAC;wBACT,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;wBAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,gBAAgB,EAAE,KAAK;wBACvB,aAAa,EAAE,KAAK;wBACpB,OAAO,EAAE,KAAK;wBACd,kBAAkB,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE;qBACnE,CAAC,CAAC;oBACH,iBAAiB,CAAC,IAAI,CAAC;wBACrB,IAAI,EAAE,oBAAoB;wBAC1B,OAAO,EACL,IAAI,aAAa,0EAA0E;4BAC3F,4BAA4B,IAAI,CAAC,QAAQ,CAAC,EAAE,wBAAwB,aAAa,EAAE;wBACrF,QAAQ,EAAE,SAAS;qBACpB,CAAC,CAAC;gBACL,CAAC;gBACD,SAAS;YACX,CAAC;QACH,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,YAAY,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,eAAe,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,UAAU,GAAG,QAAQ,KAAK,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YAChF,MAAM,eAAe,GAAG,QAAQ,EAAE,WAAW,KAAK,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjF,IAAI,CAAC,UAAU,IAAI,CAAC,eAAe;gBAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1F,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;QAED,IAAI,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACtE,IAAI,eAAe,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,eAAe,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC;gBAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;YACrH,eAAe,GAAG,KAAK,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,IAAI,CAAC;YACT,WAAW,EAAE,QAAQ,CAAC,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,gBAAgB,EAAE,eAAe;YACjC,aAAa,EAAE,YAAY;YAC3B,OAAO,EAAE,eAAe,IAAI,YAAY;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1C,IAAI,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACrE,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,eAAe,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;gBAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;YACnH,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,SAAS,GAAwF;QACrG,GAAG,IAAI;QACP,GAAG,KAAK;QACR,GAAG,UAAU;KACd,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IACtE,MAAM,MAAM,GAAwB;QAClC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;QAClD,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,cAAc,KAAK,SAAS,IAAI,CAAC,CAAC,kBAAkB,KAAK,SAAS;YAClF,CAAC,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI,CAAC,CACtD;aACE,MAAM;QACT,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9E,kBAAkB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,MAAM;QACtF,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,CAAC;IAEF,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI;QACJ,KAAK;QACL,UAAU;QACV,MAAM;QACN,OAAO,EACL,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;QACnD,KAAK,EAAE,qBAAqB,CAAC,MAAM,CAAC;QACpC,WAAW,EAAE,UAAU,CAAC,IAAI,EAAE;QAC9B,WAAW,EAAE,UAAU,CAAC,IAAI,EAAE;QAC9B,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,iBAAiB,CAAC;KACrD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,+BAA+B,CAC5C,MAAc,EACd,MAAoB,EACpB,GAAW,EACX,UAAkB;IAElB,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;IACrD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,0FAA0F;QAC1F,8FAA8F;QAC9F,KAAK,MAAM,MAAM,IAAI,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,EAAE,CAAC;YAClE,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACrD,KAAK,MAAM,GAAG,IAAI,YAAY;gBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YAC/D,MAAM,eAAe,GAAG,YAAY,CAAC,WAAW,KAAK,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpF,IAAI,CAAC,UAAU,IAAI,CAAC,eAAe;gBAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5F,CAAC;QAED,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1D,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,eAAe,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC/E,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,CAAC;gBACrE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9D,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;QACrE,KAAK,MAAM,GAAG,IAAI,aAAa;YAAE,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACxE,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACvE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;AACH,CAAC;AAED,0CAA0C;AAC1C,SAAS,SAAS,CAAC,CAAa,EAAE,CAAa;IAC7C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAqB,EAAE,OAAoB,EAAE,UAAkB;IAC9F,kEAAkE;IAClE,MAAM,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,gBAAgB,CAAC,EAAE,cAAc,EAAE,GAAG,mBAAmB,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;IAC3H,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,gBAAgB,CAAC,EAAE,aAAa,EAAE,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IACvH,0FAA0F;IAC1F,yFAAyF;IACzF,IAAI,kBAAkB,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC;IAC7E,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,WAAW,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,EAAE,CAAC;YACpE,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,SAAS,CAAC;YACvC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,cAAc,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC;AACnG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAc;IAC1D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACjE,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAoB,EACpB,SAAsC,EACtC,UAAkB,EAClB,GAAW;IAEX,MAAM,YAAY,GAAG,2BAA2B,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrE,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QACpC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,QAAQ,KAAK,SAAS,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,sBAAsB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;IACzH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,MAAoB,EAAE,UAA0B;IAC9E,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Bundle, ConceptId, OkfDocument } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The retired legacy kind name, frozen as a historical fact. Internal to the recipe lifecycle and
|
|
4
|
+
* not part of its public API; the CLI's diagnostics keep their own frozen copy, and
|
|
5
|
+
* `legacy-constants-tripwire.test.ts` pins the two equal.
|
|
6
|
+
*/
|
|
7
|
+
export declare const RETIRED_PAGE_TYPE_NAME = "Page";
|
|
8
|
+
/** Core's one accepted kind name (`View`). */
|
|
9
|
+
export declare const VIEW_KIND_NAME: "View";
|
|
10
|
+
export declare function legacyRegistryAlias(id: ConceptId): ConceptId | null;
|
|
11
|
+
export declare function legacyEntryAlias(key: string): string | null;
|
|
12
|
+
export declare function governsKind(doc: OkfDocument, kindName: string): boolean;
|
|
13
|
+
/** The id of an existing convention doc governing the LEGACY kind name, or null. Called at most
|
|
14
|
+
* once per apply, and only when the recipe carries a convention governing the current name. */
|
|
15
|
+
export declare function findLegacyViewConvention(bundle: Bundle): Promise<ConceptId | null>;
|
|
16
|
+
//# sourceMappingURL=legacy-aliases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-aliases.d.ts","sourceRoot":"","sources":["../../src/recipe-lifecycle/legacy-aliases.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAE7C,8CAA8C;AAC9C,eAAO,MAAO,cAAc,QAAmB,CAAC;AAEhD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAInE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGvE;AAED;+FAC+F;AAC/F,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAMxF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ── Legacy-alias awareness (plans/rename-page-kind-to-view, Option C+) ────────────────────────
|
|
2
|
+
// A renamed recipe keeps its id/version but renames its artifact ids (views-registry//views/ over
|
|
3
|
+
// the legacy pages-registry//pages/). Idempotency here is per-artifact expect-absent CAS, so
|
|
4
|
+
// REAPPLYING the renamed recipe onto a bundle that installed the legacy edition would otherwise
|
|
5
|
+
// create a complete SECOND set — two identical launcher cards once that bundle is migrated in
|
|
6
|
+
// place (migration keeps legacy LOCATIONS; only names change). The legacy install SATISFIES the
|
|
7
|
+
// requirement: before creating an artifact, probe its legacy-alias counterpart — the location
|
|
8
|
+
// half derived from CORE's legacy prefix constants, the retired kind name from the frozen literal
|
|
9
|
+
// below (post-removal it is deliberately absent from the live grammar) — and skip
|
|
10
|
+
// creation when the counterpart exists, reporting `legacy_present` in the receipt. An UNMIGRATED
|
|
11
|
+
// legacy install also satisfies the probe: its docs no longer register, but the remedy is the
|
|
12
|
+
// migration script (which fixes them in place, flagged loudly by `status`), never a duplicate
|
|
13
|
+
// install. General by construction: any recipe whose artifacts ride the renamed prefixes or
|
|
14
|
+
// govern the View kind benefits; for every other recipe each probe derives null and nothing
|
|
15
|
+
// changes.
|
|
16
|
+
import { query } from "../bundle-ops.js";
|
|
17
|
+
import { CONVENTIONS_PREFIX } from "../kinds.js";
|
|
18
|
+
import { PAGE_ENTRY_PREFIX, PAGE_REGISTRY_PREFIX, PAGE_TYPE_NAMES, VIEW_ENTRY_PREFIX, VIEW_REGISTRY_PREFIX, } from "../page.js";
|
|
19
|
+
/**
|
|
20
|
+
* The retired legacy kind name, frozen as a historical fact. Internal to the recipe lifecycle and
|
|
21
|
+
* not part of its public API; the CLI's diagnostics keep their own frozen copy, and
|
|
22
|
+
* `legacy-constants-tripwire.test.ts` pins the two equal.
|
|
23
|
+
*/
|
|
24
|
+
export const RETIRED_PAGE_TYPE_NAME = "Page";
|
|
25
|
+
/** Core's one accepted kind name (`View`). */
|
|
26
|
+
export const [VIEW_KIND_NAME] = PAGE_TYPE_NAMES;
|
|
27
|
+
export function legacyRegistryAlias(id) {
|
|
28
|
+
return id.startsWith(VIEW_REGISTRY_PREFIX)
|
|
29
|
+
? `${PAGE_REGISTRY_PREFIX}${id.slice(VIEW_REGISTRY_PREFIX.length)}`
|
|
30
|
+
: null;
|
|
31
|
+
}
|
|
32
|
+
export function legacyEntryAlias(key) {
|
|
33
|
+
return key.startsWith(VIEW_ENTRY_PREFIX)
|
|
34
|
+
? `${PAGE_ENTRY_PREFIX}${key.slice(VIEW_ENTRY_PREFIX.length)}`
|
|
35
|
+
: null;
|
|
36
|
+
}
|
|
37
|
+
export function governsKind(doc, kindName) {
|
|
38
|
+
const governs = doc.frontmatter["governs"];
|
|
39
|
+
return typeof governs === "string" && governs.trim() === kindName;
|
|
40
|
+
}
|
|
41
|
+
/** The id of an existing convention doc governing the LEGACY kind name, or null. Called at most
|
|
42
|
+
* once per apply, and only when the recipe carries a convention governing the current name. */
|
|
43
|
+
export async function findLegacyViewConvention(bundle) {
|
|
44
|
+
const conventions = await query(bundle, { prefix: CONVENTIONS_PREFIX, type: "Convention" });
|
|
45
|
+
for (const doc of conventions) {
|
|
46
|
+
if (governsKind(doc, RETIRED_PAGE_TYPE_NAME))
|
|
47
|
+
return doc.id;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=legacy-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-aliases.js","sourceRoot":"","sources":["../../src/recipe-lifecycle/legacy-aliases.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,gGAAgG;AAChG,8FAA8F;AAC9F,gGAAgG;AAChG,8FAA8F;AAC9F,kGAAkG;AAClG,kFAAkF;AAClF,iGAAiG;AACjG,8FAA8F;AAC9F,8FAA8F;AAC9F,4FAA4F;AAC5F,4FAA4F;AAC5F,WAAW;AACX,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,eAAe,CAAC;AAEhD,MAAM,UAAU,mBAAmB,CAAC,EAAa;IAC/C,OAAO,EAAE,CAAC,UAAU,CAAC,oBAAoB,CAAC;QACxC,CAAC,CAAC,GAAG,oBAAoB,GAAG,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE;QACnE,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACtC,CAAC,CAAC,GAAG,iBAAiB,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE;QAC9D,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAgB,EAAE,QAAgB;IAC5D,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC3C,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED;+FAC+F;AAC/F,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAc;IAC3D,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IAC5F,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAI,WAAW,CAAC,GAAG,EAAE,sBAAsB,CAAC;YAAE,OAAO,GAAG,CAAC,EAAE,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { LoadedRecipe } from "../recipes.js";
|
|
2
|
+
import type { ConceptId, OkfDocument } from "../types.js";
|
|
3
|
+
/** The frontmatter key that carries a convention's recipe stamp. */
|
|
4
|
+
export declare const RECIPE_STAMP_KEY = "x_recipe";
|
|
5
|
+
/** The version of the digest rules this release writes and reads. */
|
|
6
|
+
export declare const DEFINITION_DIGEST_RULES = 1;
|
|
7
|
+
/** One convention's record of the recipe that last wrote it. */
|
|
8
|
+
export interface RecipeStamp {
|
|
9
|
+
id: string;
|
|
10
|
+
version: string;
|
|
11
|
+
/** How many conventions the recipe declares. */
|
|
12
|
+
of: number;
|
|
13
|
+
/** {@link recipeSourceDigest} of the recipe that wrote the convention. */
|
|
14
|
+
source_digest: string;
|
|
15
|
+
/** {@link definitionDigest} of the convention as that recipe wrote it. */
|
|
16
|
+
definition: string;
|
|
17
|
+
/** The rules version that produced `definition`. */
|
|
18
|
+
digest_rules: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* How an existing convention's stamp relates to a recipe: `current` (this recipe's id, version,
|
|
22
|
+
* declared count and source digest), `stale` (this recipe's id, anything else different),
|
|
23
|
+
* `foreign` (another recipe's id) or `missing` (no well-formed stamp, or no convention).
|
|
24
|
+
*/
|
|
25
|
+
export type RecipeStampState = "current" | "stale" | "foreign" | "missing";
|
|
26
|
+
/** One stamped convention: unchanged since its recipe wrote it, changed, or unreadable rules. */
|
|
27
|
+
export type ConventionStampState = "current" | "diverged" | "unknown";
|
|
28
|
+
/** One recipe's state across the conventions that carry its stamp. */
|
|
29
|
+
export type RecipeInstallState = "installed" | "partial" | "diverged" | "unknown";
|
|
30
|
+
export interface InstalledRecipeRow {
|
|
31
|
+
id: string;
|
|
32
|
+
state: RecipeInstallState;
|
|
33
|
+
version: string | null;
|
|
34
|
+
source_digest: string | null;
|
|
35
|
+
/** How many conventions carry this recipe's stamp. */
|
|
36
|
+
conventions: number;
|
|
37
|
+
of: number | null;
|
|
38
|
+
convention_ids: ConceptId[];
|
|
39
|
+
records?: Array<{
|
|
40
|
+
version: string;
|
|
41
|
+
source_digest: string;
|
|
42
|
+
conventions: number;
|
|
43
|
+
}>;
|
|
44
|
+
missing?: number;
|
|
45
|
+
missing_ids?: ConceptId[];
|
|
46
|
+
diverged?: ConceptId[];
|
|
47
|
+
unknown_rules?: ConceptId[];
|
|
48
|
+
}
|
|
49
|
+
/** The recipe-level facts every stamp a recipe writes shares; `definition` is per convention. */
|
|
50
|
+
export interface RecipeStampIdentity {
|
|
51
|
+
id: string;
|
|
52
|
+
version: string;
|
|
53
|
+
of: number;
|
|
54
|
+
source_digest: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Digest of a recipe's parsed content, taken before edition materialization: its id, version,
|
|
58
|
+
* conventions, View pairs and References, each sorted by id, bodies with CRLF read as LF. Equal
|
|
59
|
+
* across editions, independent of how the recipe was acquired, and blind to README files.
|
|
60
|
+
*/
|
|
61
|
+
export declare function recipeSourceDigest(recipe: LoadedRecipe): string;
|
|
62
|
+
/**
|
|
63
|
+
* Digest of a convention as written, rules version 1: its frontmatter without the stripped keys
|
|
64
|
+
* and its body with CRLF read as LF and the storage newline applied. The digest of a candidate
|
|
65
|
+
* before the write equals the digest of the document read back from any backend.
|
|
66
|
+
*/
|
|
67
|
+
export declare function definitionDigest(doc: Pick<OkfDocument, "frontmatter" | "body">): string;
|
|
68
|
+
/** The convention's stamp, or null unless it is a mapping whose every field has its type. */
|
|
69
|
+
export declare function readRecipeStamp(doc: Pick<OkfDocument, "frontmatter">): RecipeStamp | null;
|
|
70
|
+
/** The recipe-level stamp facts for `recipe`; `materialized` supplies the declared count. */
|
|
71
|
+
export declare function recipeStampIdentity(recipe: LoadedRecipe, materialized: LoadedRecipe): RecipeStampIdentity;
|
|
72
|
+
/** `doc` with its stamp replaced by this recipe's, whose `definition` is the digest of `doc`. */
|
|
73
|
+
export declare function withRecipeStamp<T extends Pick<OkfDocument, "frontmatter" | "body">>(doc: T, identity: RecipeStampIdentity): T;
|
|
74
|
+
/** How the stamp on `doc` (null: no convention) relates to the recipe `identity` describes. */
|
|
75
|
+
export declare function recipeStampState(doc: Pick<OkfDocument, "frontmatter"> | null, identity: RecipeStampIdentity): RecipeStampState;
|
|
76
|
+
/** The worst of `states` in the order current, stale, foreign, missing; `current` when empty. */
|
|
77
|
+
export declare function worstRecipeStampState(states: Iterable<RecipeStampState>): RecipeStampState;
|
|
78
|
+
/** One stamped convention's state: rules this release reads, and whether its digest still matches. */
|
|
79
|
+
export declare function conventionStampState(doc: Pick<OkfDocument, "frontmatter" | "body">): ConventionStampState;
|
|
80
|
+
/**
|
|
81
|
+
* Each recipe's install state, derived from the stamps on `conventions` (documents of any other
|
|
82
|
+
* type are ignored), and the conventions no recipe stamped. `known` recipes (their declared ids
|
|
83
|
+
* are visible to the caller) also report a declared id that does not carry their stamp, and get
|
|
84
|
+
* a row when an unstamped convention that declares something sits at one of their ids: a bundle
|
|
85
|
+
* written before stamps. A declined Kind (a declaration-free record) or another recipe's stamp
|
|
86
|
+
* at their ids alone is no evidence they were installed.
|
|
87
|
+
*
|
|
88
|
+
* States, the first match winning: `unknown` when no convention carries the recipe's stamp;
|
|
89
|
+
* `partial` when the stamps record more than one version or source digest, disagree on the
|
|
90
|
+
* declared count, fall short of it, or (known recipes) a declared id is present without this
|
|
91
|
+
* recipe's stamp; `diverged` when a stamped convention changed since the recipe wrote it;
|
|
92
|
+
* `unknown` when a stamp uses digest rules this release does not read; otherwise `installed`.
|
|
93
|
+
*/
|
|
94
|
+
export declare function installedRecipes(conventions: Iterable<OkfDocument>, known?: readonly LoadedRecipe[]): {
|
|
95
|
+
rows: InstalledRecipeRow[];
|
|
96
|
+
unstamped: ConceptId[];
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=stamp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stamp.d.ts","sourceRoot":"","sources":["../../src/recipe-lifecycle/stamp.ts"],"names":[],"mappings":"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"}
|