@micacms/runtime 0.4.0 → 0.5.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +2 -2
  2. package/dist/app.d.ts +8 -37
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +7 -42
  5. package/dist/app.js.map +1 -1
  6. package/dist/config.d.ts +12 -82
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +14 -82
  9. package/dist/config.js.map +1 -1
  10. package/dist/context.d.ts +37 -66
  11. package/dist/context.d.ts.map +1 -1
  12. package/dist/context.js +24 -75
  13. package/dist/context.js.map +1 -1
  14. package/dist/http.d.ts +8 -16
  15. package/dist/http.d.ts.map +1 -1
  16. package/dist/http.js +6 -13
  17. package/dist/http.js.map +1 -1
  18. package/dist/index.d.ts +13 -14
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +12 -14
  21. package/dist/index.js.map +1 -1
  22. package/dist/routes/admin-content.d.ts +4 -17
  23. package/dist/routes/admin-content.d.ts.map +1 -1
  24. package/dist/routes/admin-content.js +11 -51
  25. package/dist/routes/admin-content.js.map +1 -1
  26. package/dist/routes/admin-media.d.ts +3 -14
  27. package/dist/routes/admin-media.d.ts.map +1 -1
  28. package/dist/routes/admin-media.js +7 -29
  29. package/dist/routes/admin-media.js.map +1 -1
  30. package/dist/routes/admin-staging.d.ts +4 -9
  31. package/dist/routes/admin-staging.d.ts.map +1 -1
  32. package/dist/routes/admin-staging.js +31 -18
  33. package/dist/routes/admin-staging.js.map +1 -1
  34. package/dist/routes/admin-system.d.ts +2 -8
  35. package/dist/routes/admin-system.d.ts.map +1 -1
  36. package/dist/routes/admin-system.js +9 -44
  37. package/dist/routes/admin-system.js.map +1 -1
  38. package/dist/routes/health.d.ts +3 -10
  39. package/dist/routes/health.d.ts.map +1 -1
  40. package/dist/routes/health.js +9 -26
  41. package/dist/routes/health.js.map +1 -1
  42. package/dist/schema.d.ts +10 -38
  43. package/dist/schema.d.ts.map +1 -1
  44. package/dist/schema.js +14 -65
  45. package/dist/schema.js.map +1 -1
  46. package/dist/server.d.ts +2 -10
  47. package/dist/server.d.ts.map +1 -1
  48. package/dist/server.js +3 -9
  49. package/dist/server.js.map +1 -1
  50. package/dist/services/changes.d.ts +150 -0
  51. package/dist/services/changes.d.ts.map +1 -0
  52. package/dist/services/changes.js +339 -0
  53. package/dist/services/changes.js.map +1 -0
  54. package/dist/services/content-store.d.ts +61 -0
  55. package/dist/services/content-store.d.ts.map +1 -0
  56. package/dist/services/content-store.js +330 -0
  57. package/dist/services/content-store.js.map +1 -0
  58. package/dist/services/media.d.ts +9 -29
  59. package/dist/services/media.d.ts.map +1 -1
  60. package/dist/services/media.js +17 -57
  61. package/dist/services/media.js.map +1 -1
  62. package/dist/services/staging.d.ts +35 -167
  63. package/dist/services/staging.d.ts.map +1 -1
  64. package/dist/services/staging.js +195 -458
  65. package/dist/services/staging.js.map +1 -1
  66. package/dist/workspace/developer.d.ts +14 -0
  67. package/dist/workspace/developer.d.ts.map +1 -0
  68. package/dist/workspace/developer.js +31 -0
  69. package/dist/workspace/developer.js.map +1 -0
  70. package/dist/workspace/files.d.ts +70 -0
  71. package/dist/workspace/files.d.ts.map +1 -0
  72. package/dist/workspace/files.js +176 -0
  73. package/dist/workspace/files.js.map +1 -0
  74. package/dist/workspace/git.d.ts +45 -0
  75. package/dist/workspace/git.d.ts.map +1 -0
  76. package/dist/workspace/git.js +68 -0
  77. package/dist/workspace/git.js.map +1 -0
  78. package/dist/workspace/locks.d.ts +33 -0
  79. package/dist/workspace/locks.d.ts.map +1 -0
  80. package/dist/workspace/locks.js +76 -0
  81. package/dist/workspace/locks.js.map +1 -0
  82. package/dist/workspace/policy.d.ts +92 -0
  83. package/dist/workspace/policy.d.ts.map +1 -0
  84. package/dist/workspace/policy.js +7 -0
  85. package/dist/workspace/policy.js.map +1 -0
  86. package/dist/workspace/tree.d.ts +73 -0
  87. package/dist/workspace/tree.d.ts.map +1 -0
  88. package/dist/workspace/tree.js +229 -0
  89. package/dist/workspace/tree.js.map +1 -0
  90. package/package.json +2 -3
  91. package/dist/db/driver.d.ts +0 -35
  92. package/dist/db/driver.d.ts.map +0 -1
  93. package/dist/db/driver.js +0 -95
  94. package/dist/db/driver.js.map +0 -1
  95. package/dist/lib/git.d.ts +0 -29
  96. package/dist/lib/git.d.ts.map +0 -1
  97. package/dist/lib/git.js +0 -62
  98. package/dist/lib/git.js.map +0 -1
  99. package/dist/services/staging-local.d.ts +0 -58
  100. package/dist/services/staging-local.d.ts.map +0 -1
  101. package/dist/services/staging-local.js +0 -391
  102. package/dist/services/staging-local.js.map +0 -1
@@ -0,0 +1,339 @@
1
+ /** The staging API types, the before/after comparison and the analysis of a pending change set. */
2
+ import { ORDER_FILE, collectionEntryPath, entryLayout, entryTitle, isValidSlug, readCollection, readCollectionEntry, readSingleton, relativizeMedia, resolveSlugField, singletonPath, validateFields, } from "@micacms/core";
3
+ import { badRequest } from "../lib/errors.js";
4
+ /**
5
+ * Reads one document from `published` and from `staged`. An order target
6
+ * becomes `{ order: [{ slug, title }] }` on each side, in position order.
7
+ */
8
+ export async function compareSources(model, published, staged, target) {
9
+ if (target.kind === "singleton") {
10
+ const def = model.singletons[target.name];
11
+ if (!def)
12
+ throw badRequest(`There is no singleton called "${target.name}".`);
13
+ return {
14
+ before: await readSingleton(published, def, target.name),
15
+ after: await readSingleton(staged, def, target.name),
16
+ };
17
+ }
18
+ const def = model.collections[target.collection];
19
+ if (!def)
20
+ throw badRequest(`There is no collection called "${target.collection}".`);
21
+ if (target.kind === "entry") {
22
+ const from = target.from ?? target.slug;
23
+ for (const slug of [target.slug, from]) {
24
+ if (!isValidSlug(slug))
25
+ throw badRequest(`"${slug}" is not a slug.`);
26
+ }
27
+ const before = await readCollectionEntry(published, def, target.collection, from);
28
+ const after = await readCollectionEntry(staged, def, target.collection, target.slug);
29
+ if (from === target.slug)
30
+ return { before, after };
31
+ // A rename: compare the on-disk form, where colocated media paths do not
32
+ // name the entry's folder.
33
+ return {
34
+ before: before && onDisk(def, target.collection, from, before),
35
+ after: after && onDisk(def, target.collection, target.slug, after),
36
+ };
37
+ }
38
+ const ordering = async (source) => {
39
+ const entries = await readCollection(source, def, target.collection);
40
+ if (entries.length === 0)
41
+ return null;
42
+ return {
43
+ order: entries.map((entry) => ({ slug: entry.slug, title: entryTitle(def, entry.data) })),
44
+ };
45
+ };
46
+ return { before: await ordering(published), after: await ordering(staged) };
47
+ }
48
+ /**
49
+ * Annotates a change set with owners and validates the entries it touches, in
50
+ * one read of the affected collections. Only changed documents are validated: a
51
+ * broken entry committed earlier must not block an unrelated publication.
52
+ */
53
+ export async function analyseChanges(model, source, changes,
54
+ /** The repository's side. When given, renamed entries are detected. */
55
+ published) {
56
+ const owners = changes.map((change) => classifyPath(model, change.path));
57
+ const collectionsToRead = new Set();
58
+ for (const owner of owners) {
59
+ if (owner.kind === "entry" || owner.kind === "order")
60
+ collectionsToRead.add(owner.collection);
61
+ }
62
+ const problems = [];
63
+ const titles = new Map();
64
+ const entriesByCollection = new Map();
65
+ for (const name of collectionsToRead) {
66
+ const def = model.collections[name];
67
+ try {
68
+ const entries = await readCollection(source, def, name);
69
+ const bySlug = new Map(entries.map((entry) => [entry.slug, entry.data]));
70
+ entriesByCollection.set(name, bySlug);
71
+ for (const [slug, data] of bySlug)
72
+ titles.set(`${name}/${slug}`, entryTitle(def, data));
73
+ }
74
+ catch (error) {
75
+ // An unreadable collection, possibly from an untouched file, is a problem
76
+ // at the path it names.
77
+ const path = error.path ?? name;
78
+ problems.push({
79
+ path,
80
+ label: def.label,
81
+ issues: [{ path: "", message: error.message }],
82
+ });
83
+ }
84
+ }
85
+ if (published) {
86
+ await detectRenames(model, published, source, changes, owners, entriesByCollection);
87
+ }
88
+ const validated = new Set();
89
+ for (const owner of owners) {
90
+ if (owner.kind === "entry") {
91
+ const key = `${owner.collection}/${owner.slug}`;
92
+ if (validated.has(key))
93
+ continue;
94
+ validated.add(key);
95
+ const def = model.collections[owner.collection];
96
+ // Absent means the change set deletes this entry.
97
+ const data = entriesByCollection.get(owner.collection)?.get(owner.slug);
98
+ if (!data)
99
+ continue;
100
+ const result = validateFields(def.fields, data, "storage");
101
+ if (!result.ok) {
102
+ problems.push({
103
+ path: entryDataPath(def, owner.collection, owner.slug),
104
+ label: labelEntry(def, owner.slug, titles.get(key)),
105
+ issues: result.issues,
106
+ });
107
+ }
108
+ }
109
+ if (owner.kind === "singleton" && !validated.has(`singleton:${owner.name}`)) {
110
+ validated.add(`singleton:${owner.name}`);
111
+ const def = model.singletons[owner.name];
112
+ const dataPath = singletonPath(def.fields, owner.name);
113
+ try {
114
+ const data = await readSingleton(source, def, owner.name);
115
+ if (data === null)
116
+ continue;
117
+ const result = validateFields(def.fields, data, "storage");
118
+ if (!result.ok) {
119
+ problems.push({ path: dataPath, label: def.label, issues: result.issues });
120
+ }
121
+ }
122
+ catch (error) {
123
+ problems.push({
124
+ path: error.path ?? dataPath,
125
+ label: def.label,
126
+ issues: [{ path: "", message: error.message }],
127
+ });
128
+ }
129
+ }
130
+ }
131
+ const annotated = changes.map((change, index) => {
132
+ const owner = owners[index];
133
+ if (owner.kind === "entry") {
134
+ const def = model.collections[owner.collection];
135
+ return {
136
+ ...change,
137
+ owner: { ...owner, label: labelEntry(def, owner.slug, titles.get(`${owner.collection}/${owner.slug}`)) },
138
+ };
139
+ }
140
+ return { ...change, owner };
141
+ });
142
+ return {
143
+ changes: annotated,
144
+ validation: { ok: problems.length === 0, problems },
145
+ };
146
+ }
147
+ /** Which piece of content a file belongs to, read from the model's path layout. */
148
+ export function classifyPath(model, path) {
149
+ const segments = path.split("/");
150
+ const head = segments[0] ?? "";
151
+ const collection = model.collections[head];
152
+ if (collection && segments.length > 1) {
153
+ if (segments.length === 2 && segments[1] === ORDER_FILE) {
154
+ return { kind: "order", collection: head, label: `${collection.label}: order` };
155
+ }
156
+ if (entryLayout(collection.fields) === "directory") {
157
+ const slug = segments[1];
158
+ if (segments.length >= 3 && isValidSlug(slug)) {
159
+ return { kind: "entry", collection: head, slug, label: slug };
160
+ }
161
+ }
162
+ else if (segments.length === 2 && segments[1].endsWith(".json")) {
163
+ const slug = segments[1].slice(0, -".json".length);
164
+ if (isValidSlug(slug))
165
+ return { kind: "entry", collection: head, slug, label: slug };
166
+ }
167
+ }
168
+ const singletonDir = model.singletons[head];
169
+ if (singletonDir && segments.length > 1) {
170
+ return { kind: "singleton", name: head, label: singletonDir.label };
171
+ }
172
+ if (head.endsWith(".json")) {
173
+ const name = head.slice(0, -".json".length);
174
+ const singleton = model.singletons[name];
175
+ if (singleton && segments.length === 1) {
176
+ return { kind: "singleton", name, label: singleton.label };
177
+ }
178
+ }
179
+ if (head === "media")
180
+ return { kind: "media", label: "Shared media" };
181
+ return { kind: "other", label: path };
182
+ }
183
+ /** Content share that two versions of an entry need to count as one moved entry, as in Git. */
184
+ const RENAME_SIMILARITY = 0.5;
185
+ /**
186
+ * Marks renamed entries in place in `owners`. An entry has no identity but its
187
+ * slug, so deleted and created entries are paired by content, like Git's rename
188
+ * detection. An order file whose only change is the renamed slug joins the
189
+ * entry, so a discard cannot leave the order naming a slug that does not exist.
190
+ */
191
+ async function detectRenames(model, published, source, changes, owners, staged) {
192
+ const kinds = new Map();
193
+ owners.forEach((owner, index) => {
194
+ if (owner.kind !== "entry")
195
+ return;
196
+ const bySlug = kinds.get(owner.collection) ?? new Map();
197
+ kinds.set(owner.collection, bySlug);
198
+ const set = bySlug.get(owner.slug) ?? new Set();
199
+ bySlug.set(owner.slug, set);
200
+ set.add(changes[index].kind);
201
+ });
202
+ for (const [name, bySlug] of kinds) {
203
+ const after = staged.get(name);
204
+ if (!after)
205
+ continue;
206
+ const only = (kind) => [...bySlug].filter(([, set]) => set.size === 1 && set.has(kind)).map(([slug]) => slug);
207
+ const deleted = only("delete").filter((slug) => !after.has(slug));
208
+ const created = only("create").filter((slug) => after.has(slug));
209
+ if (deleted.length === 0 || created.length === 0)
210
+ continue;
211
+ const def = model.collections[name];
212
+ let before;
213
+ try {
214
+ const entries = await readCollection(published, def, name);
215
+ before = new Map(entries.map((entry) => [entry.slug, entry.data]));
216
+ }
217
+ catch {
218
+ continue;
219
+ }
220
+ const candidates = [];
221
+ for (const from of deleted) {
222
+ const old = before.get(from);
223
+ if (!old)
224
+ continue;
225
+ for (const to of created) {
226
+ if (before.has(to))
227
+ continue;
228
+ const score = similarity(def, onDisk(def, name, from, old), onDisk(def, name, to, after.get(to)));
229
+ if (score >= RENAME_SIMILARITY)
230
+ candidates.push({ from, to, score });
231
+ }
232
+ }
233
+ const renamedTo = new Map();
234
+ const paired = new Set();
235
+ for (const { from, to } of candidates.sort((a, b) => b.score - a.score)) {
236
+ if (renamedTo.has(from) || paired.has(to))
237
+ continue;
238
+ renamedTo.set(from, to);
239
+ paired.add(to);
240
+ }
241
+ if (renamedTo.size === 0)
242
+ continue;
243
+ const renamedFrom = new Map([...renamedTo].map(([from, to]) => [to, from]));
244
+ const orderMovesOnlySlugs = await onlyRenamedInOrder(published, source, name, renamedTo);
245
+ const [firstFrom, firstTo] = [...renamedTo][0];
246
+ owners.forEach((owner, index) => {
247
+ if (owner.kind === "order" && owner.collection === name && orderMovesOnlySlugs) {
248
+ owners[index] = {
249
+ kind: "entry",
250
+ collection: name,
251
+ slug: firstTo,
252
+ label: firstTo,
253
+ renamedFrom: firstFrom,
254
+ };
255
+ }
256
+ if (owner.kind !== "entry" || owner.collection !== name)
257
+ return;
258
+ const to = renamedTo.get(owner.slug);
259
+ if (to)
260
+ owners[index] = { ...owner, slug: to, label: to, renamedFrom: owner.slug };
261
+ const from = renamedFrom.get(owner.slug);
262
+ if (from)
263
+ owners[index] = { ...owner, renamedFrom: from };
264
+ });
265
+ }
266
+ }
267
+ /** True when a collection's staged order is the published one with the renamed slugs replaced. */
268
+ async function onlyRenamedInOrder(published, staged, name, renamedTo) {
269
+ const path = `${name}/${ORDER_FILE}`;
270
+ const parse = (raw) => {
271
+ try {
272
+ return raw === null ? null : JSON.parse(raw);
273
+ }
274
+ catch {
275
+ return null;
276
+ }
277
+ };
278
+ const before = parse(await published.read(path));
279
+ const after = parse(await staged.read(path));
280
+ if (!Array.isArray(before) || !Array.isArray(after))
281
+ return false;
282
+ const expected = before.map((slug) => typeof slug === "string" ? (renamedTo.get(slug) ?? slug) : slug);
283
+ return canonical(expected) === canonical(after);
284
+ }
285
+ /** The share of non-empty fields, the slug aside, that two versions of an entry agree on. */
286
+ function similarity(def, a, b) {
287
+ const slugKey = resolveSlugField(def);
288
+ let compared = 0;
289
+ let equal = 0;
290
+ for (const key of Object.keys(def.fields)) {
291
+ if (key === slugKey || (isEmpty(a[key]) && isEmpty(b[key])))
292
+ continue;
293
+ compared += 1;
294
+ if (canonical(a[key]) === canonical(b[key]))
295
+ equal += 1;
296
+ }
297
+ return compared === 0 ? 0 : equal / compared;
298
+ }
299
+ /**
300
+ * Entry data with media paths as the files store them: relative to the entry,
301
+ * where it has a folder.
302
+ */
303
+ function onDisk(def, collection, slug, data) {
304
+ return entryLayout(def.fields) === "directory"
305
+ ? relativizeMedia(def.fields, data, collectionEntryPath(def.fields, collection, slug))
306
+ : data;
307
+ }
308
+ function isEmpty(value) {
309
+ return value === undefined || value === null || value === "" || (Array.isArray(value) && value.length === 0);
310
+ }
311
+ /** JSON with sorted keys, so two equal objects compare equal. */
312
+ function canonical(value) {
313
+ return JSON.stringify(value ?? null, (_key, entry) => {
314
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry))
315
+ return entry;
316
+ const record = entry;
317
+ return Object.fromEntries(Object.keys(record).sort().map((key) => [key, record[key]]));
318
+ });
319
+ }
320
+ function labelEntry(def, slug, title) {
321
+ return `${def.labelSingular ?? def.label}: ${title ?? slug}`;
322
+ }
323
+ function entryDataPath(def, collection, slug) {
324
+ const base = collectionEntryPath(def.fields, collection, slug);
325
+ return entryLayout(def.fields) === "directory" ? `${base}/index.json` : base;
326
+ }
327
+ export function describeProblems(problems) {
328
+ const names = problems.map((problem) => problem.label);
329
+ const listed = names.slice(0, 3).join(", ") + (names.length > 3 ? ", …" : "");
330
+ return `The pending changes cannot be published until they are valid: ${listed}.`;
331
+ }
332
+ /** Field issues with the file path folded in, for the flat API envelope. */
333
+ export function flattenProblems(problems) {
334
+ return problems.flatMap((problem) => problem.issues.map((issue) => ({
335
+ path: issue.path ? `${problem.path}: ${issue.path}` : problem.path,
336
+ message: issue.message,
337
+ })));
338
+ }
339
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/services/changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Collections and singletons over the working tree's files: validation, slugs,
3
+ * entry files and `_order.json`. An entry is its slug and path, Git keeps the
4
+ * history, a save is a draft, and only Publish makes a commit.
5
+ */
6
+ import { type Collection, type ContentEntry, type FieldIssue, type Singleton, type Site } from "@micacms/core";
7
+ import { FilesError, type ContentFiles } from "../workspace/files.js";
8
+ export declare class ContentError extends FilesError {
9
+ name: string;
10
+ }
11
+ export declare class ValidationError extends ContentError {
12
+ readonly issues: FieldIssue[];
13
+ name: string;
14
+ constructor(message: string, issues: FieldIssue[]);
15
+ }
16
+ export interface SaveEntryInput {
17
+ data: Record<string, unknown>;
18
+ /** The entry being replaced. Absent when creating. */
19
+ slug?: string;
20
+ /** The revision `slug` had when the editor opened it. Absent writes unconditionally. */
21
+ expectedRevision?: string | null;
22
+ }
23
+ export interface SavedEntry {
24
+ slug: string;
25
+ title: string;
26
+ /** The entry's revision after this save, for the next save. A file revision, not a commit. */
27
+ revision: string;
28
+ /** True when the save moved the entry's files. */
29
+ renamed: boolean;
30
+ }
31
+ export declare function createContentStore(site: Site, workspace: ContentFiles): {
32
+ list(collectionName: string): Promise<ContentEntry[]>;
33
+ get(collectionName: string, slug: string): Promise<ContentEntry | null>;
34
+ /** The revision an editor must send back with a save of this entry. */
35
+ revisionOf(collectionName: string, slug: string): Promise<string | null>;
36
+ /** The revision an editor must send back with a save of this singleton. */
37
+ revisionOfSingleton(name: string): Promise<string | null>;
38
+ getSingleton(name: string): Promise<Record<string, unknown>>;
39
+ save(collectionName: string, input: SaveEntryInput): Promise<SavedEntry>;
40
+ remove(collectionName: string, slug: string, options?: {
41
+ expectedRevision?: string | null;
42
+ }): Promise<void>;
43
+ saveSingleton(name: string, payload: unknown, options?: {
44
+ expectedRevision?: string | null;
45
+ }): Promise<{
46
+ revision: string;
47
+ }>;
48
+ reorder(collectionName: string, slugs: string[]): Promise<void>;
49
+ requireCollection: (name: string) => Collection;
50
+ requireSingleton: (name: string) => Singleton;
51
+ /** Slug the server would assign, so the editor's URL preview matches it. */
52
+ suggestSlug(collectionName: string, source: string, except?: string): Promise<string>;
53
+ /** Entries pointing at `slug`, so the editor can warn before a delete. */
54
+ findReferences(collectionName: string, slug: string): Promise<{
55
+ collection: string;
56
+ slug: string;
57
+ title: string;
58
+ }[]>;
59
+ };
60
+ export type ContentStore = ReturnType<typeof createContentStore>;
61
+ //# sourceMappingURL=content-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-store.d.ts","sourceRoot":"","sources":["../../src/services/content-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAoBL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,UAAU,EAEf,KAAK,SAAS,EACd,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAiB,UAAU,EAAE,KAAK,YAAY,EAAmB,MAAM,uBAAuB,CAAC;AAEtG,qBAAa,YAAa,SAAQ,UAAU;IACjC,IAAI,SAAkB;CAChC;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAI7C,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE;IAHtB,IAAI,SAAqB;gBAEhC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,UAAU,EAAE;CAIhC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY;yBA6IvC,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;wBAIjC,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAK7E,uEAAuE;+BACtC,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQ9E,2EAA2E;8BAC3C,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;uBAKtC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;yBAOvC,MAAM,SAAS,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;2BA8D5D,MAAM,QAChB,MAAM,YACH;QAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAC5C,OAAO,CAAC,IAAI,CAAC;wBAuBR,MAAM,WACH,OAAO,YACP;QAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAC5C,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;4BAwBd,MAAM,SACf,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC;8BAhSe,MAAM,KAAG,UAAU;6BAMpB,MAAM,KAAG,SAAS;IA8ShD,4EAA4E;gCAC1C,MAAM,UAAU,MAAM,WAAW,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3F,0EAA0E;mCACrC,MAAM,QAAQ,MAAM;oBACpB,MAAM;cAAQ,MAAM;eAAS,MAAM;;EAuB3E;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC"}