@peripheries/renderer 0.28.1 → 0.29.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.
@@ -0,0 +1,277 @@
1
+ import "./refs-Csgh6rXq.js";
2
+ import { READY_GLOBAL } from "@peripheries/runtime";
3
+ var NAME = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
4
+ var CHUNK_JS = /^chunks\/[A-Za-z0-9_.-]+\.js$/;
5
+ var CHUNK_CSS = /^chunks\/[A-Za-z0-9_.-]+\.css$/;
6
+ var ALIAS = /^e\/[A-Za-z_$][A-Za-z0-9_$]*\.js$/;
7
+ var SPECIFIER = /^@[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/;
8
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
9
+ var hasOnly = (o, keys) => Object.keys(o).every((k) => keys.includes(k));
10
+ var uniqueStrings = (v, pattern, minItems = 0) => Array.isArray(v) && v.length >= minItems && v.every((s) => typeof s === "string" && pattern.test(s)) && new Set(v).size === v.length;
11
+ function parseComponentManifest(value) {
12
+ if (!isRecord(value) || !hasOnly(value, [
13
+ "manifest",
14
+ "lineage",
15
+ "base",
16
+ "exports",
17
+ "components"
18
+ ])) return null;
19
+ if (value.manifest !== 1 || typeof value.lineage !== "string" || value.lineage.length < 1 || value.base !== "version" || !isRecord(value.components)) return null;
20
+ if (value.exports !== void 0) {
21
+ if (!isRecord(value.exports)) return null;
22
+ for (const [name, file] of Object.entries(value.exports)) if (!NAME.test(name) || typeof file !== "string" || !ALIAS.test(file)) return null;
23
+ }
24
+ for (const [name, c] of Object.entries(value.components)) {
25
+ if (!NAME.test(name) || !isRecord(c) || !hasOnly(c, [
26
+ "js",
27
+ "imports",
28
+ "css",
29
+ "requires"
30
+ ])) return null;
31
+ if (typeof c.js !== "string" || !CHUNK_JS.test(c.js)) return null;
32
+ if (c.imports !== void 0 && !uniqueStrings(c.imports, CHUNK_JS)) return null;
33
+ if (c.css !== void 0 && !uniqueStrings(c.css, CHUNK_CSS)) return null;
34
+ if (c.requires !== void 0) {
35
+ if (!isRecord(c.requires)) return null;
36
+ for (const [specifier, names] of Object.entries(c.requires)) if (!SPECIFIER.test(specifier) || !uniqueStrings(names, NAME, 1)) return null;
37
+ }
38
+ }
39
+ return value;
40
+ }
41
+ function chunkPlan(manifest, names, base) {
42
+ const entries = {};
43
+ const js = new Set();
44
+ const css = new Set();
45
+ for (const name of names) {
46
+ const c = Object.hasOwn(manifest.components, name) ? manifest.components[name] : void 0;
47
+ if (!c) continue;
48
+ entries[name] = c.js;
49
+ js.add(c.js);
50
+ for (const f of c.imports ?? []) js.add(f);
51
+ for (const f of c.css ?? []) css.add(f);
52
+ }
53
+ return {
54
+ base,
55
+ entries,
56
+ js: [...js],
57
+ css: [...css]
58
+ };
59
+ }
60
+ function parseChunkPlans(value) {
61
+ if (!isRecord(value)) return null;
62
+ const out = {};
63
+ for (const [specifier, p] of Object.entries(value)) {
64
+ if (!SPECIFIER.test(specifier) || !isRecord(p) || !hasOnly(p, [
65
+ "base",
66
+ "entries",
67
+ "js",
68
+ "css"
69
+ ])) return null;
70
+ if (typeof p.base !== "string" || !/^\/api\/public-remotes\/[A-Za-z0-9._/-]+\/$/.test(p.base) || p.base.includes("..")) return null;
71
+ if (!isRecord(p.entries) || !Object.entries(p.entries).every(([n, f]) => NAME.test(n) && typeof f === "string" && CHUNK_JS.test(f))) return null;
72
+ if (!uniqueStrings(p.js, CHUNK_JS) || !uniqueStrings(p.css, CHUNK_CSS)) return null;
73
+ out[specifier] = p;
74
+ }
75
+ return out;
76
+ }
77
+ function isComponentExport(value) {
78
+ if (typeof value === "function") return true;
79
+ if (!value || typeof value !== "object") return false;
80
+ const tag = value.$$typeof;
81
+ return tag === Symbol.for("react.forward_ref") || tag === Symbol.for("react.memo") || tag === Symbol.for("react.lazy");
82
+ }
83
+ function projectModule(row, mod, contracts = {}) {
84
+ const components = {};
85
+ for (const c of row.components) {
86
+ const exported = mod[c.exposed_export ?? c.component_name ?? ""];
87
+ if (c.component_name && isComponentExport(exported)) components[c.component_name] = exported;
88
+ }
89
+ return {
90
+ id: row.id,
91
+ label: row.bundle_name === "main" ? row.org_slug : `${row.org_slug}/${row.bundle_name}`,
92
+ ...row.specifier ? { specifier: row.specifier } : {},
93
+ components,
94
+ contracts,
95
+ documentProfiles: mod.documentProfiles,
96
+ paginatorBindings: mod.PAGINATOR_BINDINGS
97
+ };
98
+ }
99
+ function runtimeReady(g = globalThis) {
100
+ return g[READY_GLOBAL] ?? Promise.resolve();
101
+ }
102
+ var cache = new Map();
103
+ var browserImport = (url) => import(url);
104
+ function loadBundle(row, files, wanted = "all") {
105
+ const plan = row.specifier ? files.chunkPlan?.(row.specifier) : null;
106
+ if (plan) return loadChunked(row, files, plan, wanted);
107
+ let pending = cache.get(row.id);
108
+ if (!pending) {
109
+ pending = (async () => {
110
+ const url = files.url(row, "index.js");
111
+ if (!url) throw new Error(`[bundles] ${row.org_slug}/${row.bundle_name} has no storage path`);
112
+ await runtimeReady();
113
+ const contractsUrl = files.url(row, "contracts.json");
114
+ const get = files.fetch ?? ((u) => fetch(u));
115
+ const [mod, contracts] = await Promise.all([(files.import ?? browserImport)(row.specifier ?? url), get(contractsUrl).then((r) => r.ok ? r.json() : null, () => null)]);
116
+ return projectModule(row, mod, contracts?.components ?? {});
117
+ })();
118
+ pending.catch(() => cache.delete(row.id));
119
+ cache.set(row.id, pending);
120
+ }
121
+ return pending;
122
+ }
123
+ var importedChunks = new Map();
124
+ var chunkedBundles = new Map();
125
+ var manifests = new Map();
126
+ var contractsOf = new Map();
127
+ var BUNDLE_LEVEL_EXPORTS = ["documentProfiles", "PAGINATOR_BINDINGS"];
128
+ var exportOf = (c) => c.exposed_export ?? c.component_name ?? "";
129
+ function loadChunked(row, files, plan, wanted) {
130
+ const names = wanted === "all" ? "all" : [...wanted].sort().join(",");
131
+ const key = `${row.id}|${plan.base}|${names}`;
132
+ let pending = chunkedBundles.get(key);
133
+ if (!pending) {
134
+ pending = (async () => {
135
+ await runtimeReady();
136
+ const get = files.fetch ?? ((u) => fetch(u));
137
+ const doImport = files.import ?? browserImport;
138
+ const asked = row.components.filter((c) => c.component_name && (wanted === "all" || wanted.has(c.component_name)));
139
+ const inPlan = asked.every((c) => Object.hasOwn(plan.entries, exportOf(c)));
140
+ const manifestUrl = `${plan.base}manifest.json`;
141
+ let manifest = null;
142
+ if (wanted === "all" || !inPlan) {
143
+ let m = manifests.get(manifestUrl);
144
+ if (!m) {
145
+ m = get(manifestUrl).then(async (r) => {
146
+ const parsed = r.ok ? parseComponentManifest(await r.json().catch(() => null)) : null;
147
+ if (!parsed) throw new Error(`[bundles] ${row.org_slug}/${row.bundle_name}: manifest.json is not readable`);
148
+ return parsed;
149
+ });
150
+ m.catch(() => manifests.delete(manifestUrl));
151
+ manifests.set(manifestUrl, m);
152
+ }
153
+ manifest = await m;
154
+ }
155
+ const fileOf = (name) => plan.entries[name] ?? manifest?.components[name]?.js;
156
+ const exportsWanted = [...new Set([...asked.map(exportOf), ...wanted === "all" && manifest ? BUNDLE_LEVEL_EXPORTS.filter((n) => manifest.components[n]) : []])].filter((n) => fileOf(n));
157
+ const css = new Set();
158
+ for (const n of exportsWanted) for (const f of manifest?.components[n]?.css ?? (plan.entries[n] ? plan.css : [])) css.add(f);
159
+ const contractsUrl = `${plan.base}contracts.json`;
160
+ let contractsP = contractsOf.get(contractsUrl);
161
+ if (!contractsP) {
162
+ contractsP = get(contractsUrl).then((r) => r.ok ? r.json().then((j) => j?.components ?? {}) : {}, () => ({}));
163
+ contractsOf.set(contractsUrl, contractsP);
164
+ }
165
+ const imports = exportsWanted.map(async (n) => {
166
+ const url = `${plan.base}${fileOf(n)}`;
167
+ let m = importedChunks.get(url);
168
+ if (!m) {
169
+ m = doImport(url);
170
+ m.catch(() => importedChunks.delete(url));
171
+ importedChunks.set(url, m);
172
+ }
173
+ return [n, (await m)[n]];
174
+ });
175
+ const [loaded, contracts] = await Promise.all([Promise.all(imports), contractsP]);
176
+ if (css.size) files.linkStyles?.([...css].map((f) => `${plan.base}${f}`));
177
+ return projectModule(row, Object.fromEntries(loaded), contracts);
178
+ })();
179
+ pending.catch(() => chunkedBundles.delete(key));
180
+ chunkedBundles.set(key, pending);
181
+ }
182
+ return pending;
183
+ }
184
+ var requiresOf = (row, files) => row.requires ?? (row.specifier && files.chunkPlan?.(row.specifier) ? row.specifier === "@stack/core" ? [] : ["@stack/core"] : void 0);
185
+ var escapeRe = (v) => v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
186
+ async function sharedDependencies(rows, files) {
187
+ const get = files.fetch ?? ((u) => fetch(u));
188
+ const bySpecifier = new Map(rows.map((r) => [r.specifier, r.id]));
189
+ const deps = new Map();
190
+ try {
191
+ await Promise.all(rows.map(async (r) => {
192
+ const requires = requiresOf(r, files);
193
+ if (requires) return void deps.set(r.id, requires.map((s) => bySpecifier.get(s)).filter((id) => !!id && id !== r.id));
194
+ const url = files.url(r, "index.js");
195
+ const res = url ? await get(url) : null;
196
+ if (!res?.ok) throw new Error("unreadable");
197
+ const source = await res.text();
198
+ deps.set(r.id, rows.filter((o) => o.id !== r.id && new RegExp(`(?:from|import)\\s*\\(?\\s*(["'\`])${escapeRe(o.specifier)}\\1`).test(source)).map((o) => o.id));
199
+ }));
200
+ } catch {
201
+ return null;
202
+ }
203
+ return deps;
204
+ }
205
+ async function staticImports(row, shared, files) {
206
+ const requires = requiresOf(row, files);
207
+ if (requires) return requires.map((s) => shared.find((o) => o.specifier === s)?.id).filter((id) => !!id && id !== row.id);
208
+ const url = files.url(row, "index.js");
209
+ const res = url ? await (files.fetch ?? ((u) => fetch(u)))(url).catch(() => null) : null;
210
+ if (!res?.ok) return null;
211
+ const source = await res.text();
212
+ return shared.filter((o) => o.id !== row.id && new RegExp(`(?:from|import)\\s*(["'\`])${escapeRe(o.specifier)}\\1`).test(source)).map((o) => o.id);
213
+ }
214
+ async function neededRows(rows, files, only) {
215
+ const shared = rows.filter((r) => r.specifier);
216
+ if (!shared.some((r) => !only.has(r.id))) return rows;
217
+ const keep = new Set(rows.filter((r) => !r.specifier || only.has(r.id)).map((r) => r.id));
218
+ const queue = rows.filter((r) => keep.has(r.id));
219
+ const scanned = new Set();
220
+ while (queue.length) {
221
+ const batch = queue.splice(0).filter((r) => !scanned.has(r.id));
222
+ batch.forEach((r) => scanned.add(r.id));
223
+ const found = await Promise.all(batch.map((r) => staticImports(r, shared, files)));
224
+ if (found.some((f) => f === null)) return null;
225
+ for (const id of found.flat()) {
226
+ if (keep.has(id)) continue;
227
+ keep.add(id);
228
+ queue.push(rows.find((r) => r.id === id));
229
+ }
230
+ }
231
+ return rows.filter((r) => keep.has(r.id));
232
+ }
233
+ async function loadWaves(rows, files) {
234
+ const shared = rows.filter((r) => r.specifier);
235
+ const rest = rows.filter((r) => !r.specifier);
236
+ const waves = [];
237
+ const deps = shared.length > 1 ? await sharedDependencies(shared, files) : null;
238
+ if (!deps) return [rows];
239
+ const done = new Set();
240
+ let left = shared;
241
+ while (left.length) {
242
+ const wave = left.filter((r) => (deps.get(r.id) ?? []).every((d) => done.has(d)));
243
+ if (!wave.length) return [rows];
244
+ waves.push(wave);
245
+ wave.forEach((r) => done.add(r.id));
246
+ left = left.filter((r) => !done.has(r.id));
247
+ }
248
+ if (rest.length) waves.push(rest);
249
+ return waves;
250
+ }
251
+ async function loadBundlesSettled(rows, files, only, names) {
252
+ const loaded = [];
253
+ const failed = [];
254
+ const wanted = only ? await neededRows(rows, files, only) ?? rows : rows;
255
+ for (const wave of await loadWaves(wanted, files)) (await Promise.allSettled(wave.map((r) => loadBundle(r, files, only && names ? names : "all")))).forEach((s, i) => {
256
+ if (s.status === "fulfilled") loaded.push(s.value);
257
+ else {
258
+ failed.push(wave[i].id);
259
+ console.warn(`[bundles] ${wave[i].org_slug}/${wave[i].bundle_name} failed to load:`, s.reason);
260
+ }
261
+ });
262
+ return {
263
+ loaded,
264
+ failed
265
+ };
266
+ }
267
+ async function loadBundles(rows, files) {
268
+ return (await loadBundlesSettled(rows, files)).loaded;
269
+ }
270
+ function _clearBundleCache() {
271
+ cache.clear();
272
+ importedChunks.clear();
273
+ chunkedBundles.clear();
274
+ manifests.clear();
275
+ contractsOf.clear();
276
+ }
277
+ export { loadBundlesSettled as a, chunkPlan as c, loadBundles as i, parseChunkPlans as l, isComponentExport as n, projectModule as o, loadBundle as r, runtimeReady as s, _clearBundleCache as t, parseComponentManifest as u };
@@ -22,6 +22,21 @@ function rowForCell(rows, cell, pageOrgId) {
22
22
  const ref = normalizeRef(cell.bundle_ref, pageOrgId);
23
23
  return ref && rows.find((r) => rowMatches(ref, r)) || null;
24
24
  }
25
+ function rowsNeededBy(rows, cells, pageOrgId) {
26
+ const names = new Set(cells.flatMap((c) => c.component ? [c.component] : []));
27
+ const wantsCore = cells.some((c) => c.component?.startsWith("@core/"));
28
+ const out = new Set();
29
+ for (const r of rows) if (!r.specifier || !r.components?.length || wantsCore && r.specifier === "@stack/core") out.add(r.id);
30
+ else if (r.components.some((c) => c.component_name && names.has(c.component_name))) out.add(r.id);
31
+ for (const c of cells) {
32
+ const row = rowForCell(rows, c, pageOrgId);
33
+ if (row) out.add(row.id);
34
+ }
35
+ return out;
36
+ }
37
+ function componentNames(cells) {
38
+ return new Set(cells.flatMap((c) => c.component ? [c.component] : []));
39
+ }
25
40
  function pageBundles(scope, rows, loaded, pageOrgId, failed = false) {
26
41
  const byRow = new Map((loaded ?? []).map((b) => [b.id, b]));
27
42
  return {
@@ -33,4 +48,4 @@ function pageBundles(scope, rows, loaded, pageOrgId, failed = false) {
33
48
  }
34
49
  };
35
50
  }
36
- export { rowsInScope as i, pageBundles as n, rowForCell as r, pageBundleRefs as t };
51
+ export { rowsInScope as a, rowForCell as i, pageBundleRefs as n, rowsNeededBy as o, pageBundles as r, componentNames as t };
@@ -270,6 +270,11 @@ function resolveComponent(name, { cellBundle, scope, core }) {
270
270
  source: "core"
271
271
  } : null;
272
272
  }
273
+ function bundleNameOf(source, scope) {
274
+ if (source === "core") return "host";
275
+ const b = scope?.find((x) => x.label === source);
276
+ return b?.specifier ?? b?.label ?? source;
277
+ }
273
278
  var pageScopeKey = (pageId) => `page:${pageId}`;
274
279
  var projectScopeKey = (projectId) => `project:${projectId}`;
275
280
  function resolveScopeId(kind, ctx) {
@@ -342,4 +347,4 @@ function collectScopeIds(ctx, selections, viewState) {
342
347
  }
343
348
  return [...ids];
344
349
  }
345
- export { HYDRATED_CELL_FIELDS as C, normalizeCell as D, hasRef as E, resolveCell as O, CONTENT_FIELDS as S, STORE_FIELDS as T, failedLabels as _, projectSelections as a, isEmptyPropValue as b, pageScopeKey as c, resolveComponent as d, cellAttributes as f, assembleCellProps as g, pageContainerStyle as h, projectLive as i, rootCells as k, projectScopeKey as l, documentProfile as m, attachViewStateSetters as n, projectViewState as o, cellPlacementStyle as p, collectScopeIds as r, shallowEqualBundle as s, attachSelectionSetters as t, resolveScopeId as u, hiddenWhenEmpty as v, RENDER_FIELDS as w, projectCellData as x, hideWhenEmptyProblem as y };
350
+ export { rootCells as A, CONTENT_FIELDS as C, hasRef as D, STORE_FIELDS as E, normalizeCell as O, projectCellData as S, RENDER_FIELDS as T, assembleCellProps as _, projectSelections as a, hideWhenEmptyProblem as b, pageScopeKey as c, bundleNameOf as d, resolveComponent as f, pageContainerStyle as g, documentProfile as h, projectLive as i, resolveCell as k, projectScopeKey as l, cellPlacementStyle as m, attachViewStateSetters as n, projectViewState as o, cellAttributes as p, collectScopeIds as r, shallowEqualBundle as s, attachSelectionSetters as t, resolveScopeId as u, failedLabels as v, HYDRATED_CELL_FIELDS as w, isEmptyPropValue as x, hiddenWhenEmpty as y };
package/dist/core.js CHANGED
@@ -1,12 +1,37 @@
1
- import { C as HYDRATED_CELL_FIELDS, D as normalizeCell, E as hasRef, O as resolveCell, S as CONTENT_FIELDS, T as STORE_FIELDS, a as projectSelections, b as isEmptyPropValue, c as pageScopeKey, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, k as rootCells, l as projectScopeKey, n as attachViewStateSetters, o as projectViewState, p as cellPlacementStyle, r as collectScopeIds, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as hiddenWhenEmpty, w as RENDER_FIELDS, x as projectCellData, y as hideWhenEmptyProblem } from "./chunks/projection-e8MHn6Bt.js";
1
+ import { A as rootCells, C as CONTENT_FIELDS, D as hasRef, E as STORE_FIELDS, O as normalizeCell, S as projectCellData, T as RENDER_FIELDS, _ as assembleCellProps, a as projectSelections, b as hideWhenEmptyProblem, c as pageScopeKey, f as resolveComponent, g as pageContainerStyle, i as projectLive, k as resolveCell, l as projectScopeKey, m as cellPlacementStyle, n as attachViewStateSetters, o as projectViewState, p as cellAttributes, r as collectScopeIds, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, w as HYDRATED_CELL_FIELDS, x as isEmptyPropValue, y as hiddenWhenEmpty } from "./chunks/projection-qLyY8X3J.js";
2
2
  import { C as passesConditions, S as pageContext, T as settled, _ as EACH, a as VARIABLE_NAMESPACES, b as cellResolutionContext, c as pageVariables, d as resolveDescriptorVariables, f as selectionShape, g as variableReferences, h as variableLabels, i as UnsafeDocumentError, l as prepareDocument, m as validateDescriptor, n as RENDER_FUNCTIONS, o as descriptorShape, p as shapeAt, r as RENDER_FUNCTIONS_AHEAD, s as orderByVariable, t as PAGING_VARIABLES, u as queryKey, v as EACH_DEFAULT_AS, w as resolveReferences, x as isEach, y as cellContext } from "./chunks/query-D_f73wsU.js";
3
3
  import { S as walkRequest, _ as stateNames, a as eachFormProblems, b as systemsFromProcess, c as validatePage, d as mergeStates, f as needsWalk, g as resolveWalkStart, h as referencedLabels, i as componentsFor, l as selectionIssues, m as readWalk, n as STORE_SCOPES, o as nearestNames, p as readField, r as WALK_DIRECTIONS, s as validateCell, t as RESPONSIVE_BUCKETS, u as RESERVED_LABELS, v as stateValue, x as walkKey, y as systemsFromGraphs } from "./chunks/validate-BfXuQLmV.js";
4
4
  import { C as actionReferences, D as resolveAction, E as projectCellActions, S as actionProblems, T as normalizeActionDeclaration, _ as HOST_READ_KEY, a as deriveSectionReferences, b as isHostRead, c as nodePrintStyle, d as referencesFor, f as sectionAnchor, g as usesStructureLayout, h as tableOfContents, i as deriveSectionNumbering, l as normalizeStructure, m as structureIssues, n as SECTION_KINDS, r as deriveElementReferences, s as mergeSectionReferences, t as PAGE_DOCUMENT, u as numberingFor, v as bindHostReads, w as declaredActions, x as actionBindingKey, y as hostReadProblem } from "./chunks/structure-Ds2wfhkH.js";
5
- import { a as loadBundlesSettled, i as loadBundles, n as isComponentExport, o as projectModule, r as loadBundle, s as runtimeReady, t as _clearBundleCache } from "./chunks/load-H7hUCwPc.js";
5
+ import { a as loadBundlesSettled, c as chunkPlan, i as loadBundles, l as parseChunkPlans, n as isComponentExport, o as projectModule, r as loadBundle, s as runtimeReady, t as _clearBundleCache, u as parseComponentManifest } from "./chunks/load-CAus-wv_.js";
6
6
  import { a as normalizeRef, i as bundleScope, n as MAIN, o as refKey, r as PUBLIC, t as CORE_SPECIFIER } from "./chunks/refs-Csgh6rXq.js";
7
- import { i as rowsInScope, n as pageBundles, r as rowForCell, t as pageBundleRefs } from "./chunks/page-bundles-_wsGO9WU.js";
7
+ import { a as rowsInScope, i as rowForCell, n as pageBundleRefs, o as rowsNeededBy, r as pageBundles, t as componentNames } from "./chunks/page-bundles-dUYH4D73.js";
8
8
  import { a as createStackStore, i as saveScope, n as clearScope, r as loadScope } from "./chunks/persistence-hurkUUQ0.js";
9
9
  import { ACTION_KINDS, QUERY_DESCRIPTOR_KEY, SECTION_KINDS as SECTION_KINDS$1, STATE_ROLES, STATE_TIERS, WALK_DEFAULTS, isDescriptorBinding, isLiveQueryState, isReadOnlyVersion } from "@peripheries/runtime";
10
+ function pageForCell(page, cellId) {
11
+ const cell = (page.content?.cells ?? []).map((c) => normalizeCell(c).cell).find((c) => c.id === cellId);
12
+ const queries = page.content?.data?.queries ?? {};
13
+ const wanted = new Set();
14
+ const mentions = (value) => {
15
+ for (const m of JSON.stringify(value ?? null).matchAll(/@([A-Za-z_][A-Za-z0-9_]*)/g)) if (m[1] && m[1] in queries) wanted.add(m[1]);
16
+ };
17
+ if (cell) mentions(cell);
18
+ for (let seen = -1; seen !== wanted.size;) {
19
+ seen = wanted.size;
20
+ for (const label of [...wanted]) mentions(queries[label]);
21
+ }
22
+ const kept = cell && hasRef(cell) ? queries : Object.fromEntries(Object.entries(queries).filter(([label]) => wanted.has(label)));
23
+ return {
24
+ ...page,
25
+ content: {
26
+ ...page.content,
27
+ cells: cell ? [(page.content?.cells ?? []).find((c) => normalizeCell(c).cell.id === cellId)] : [],
28
+ ...page.content?.data ? { data: {
29
+ ...page.content.data,
30
+ queries: kept
31
+ } } : {}
32
+ }
33
+ };
34
+ }
10
35
  function resolveDeclarations(queries, systems, diagnostics = [], cellId) {
11
36
  const out = {};
12
37
  for (const [label, raw] of Object.entries(queries ?? {})) {
@@ -99,6 +124,7 @@ var LAYER_ROLES = {
99
124
  "organisation": null,
100
125
  "process-system": "process",
101
126
  "question": null,
127
+ "refinement": null,
102
128
  "submission": null
103
129
  };
104
130
  function layerName(s) {
@@ -148,7 +174,8 @@ function mainSystemFilter(source, diagnostics) {
148
174
  return (id) => known.get(id) === true;
149
175
  };
150
176
  }
151
- async function loadPageData(page, source, scope = {}) {
177
+ async function loadPageData(whole, source, scope = {}) {
178
+ const page = scope.only === void 0 ? whole : pageForCell(whole, scope.only);
152
179
  const diagnostics = validatePage(page);
153
180
  const systems = await resolveSystems(source, page);
154
181
  const engDataSystemId = systems.eng_data ?? null;
@@ -180,6 +207,19 @@ async function loadPageData(page, source, scope = {}) {
180
207
  return resolved;
181
208
  });
182
209
  const unresolved = cells.filter((c) => c.source === "pending").map((c) => c.id);
210
+ if (scope.structure) return {
211
+ page,
212
+ cells,
213
+ unresolved,
214
+ data: {},
215
+ declared: [],
216
+ cellData: {},
217
+ systems,
218
+ engDataSystemId,
219
+ graphNodeIds: [],
220
+ ...scope.version?.versionId ? { version: scope.version } : {},
221
+ diagnostics: dedupe(diagnostics)
222
+ };
183
223
  const declared = collectDeclarations(page, systems, diagnostics);
184
224
  const cellDecls = new Map(cells.filter((c) => c.component).map((c) => [c.id, resolveDeclarations(c.data?.queries, systems, diagnostics, c.id)]));
185
225
  const pageQueries = collectDescriptors(page.content?.data?.queries);
@@ -1144,4 +1184,4 @@ function manifestPageFrom(graphNodeId, data) {
1144
1184
  }
1145
1185
  };
1146
1186
  }
1147
- export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HOST_READ_KEY, HYDRATED_CELL_FIELDS, LAYER_ROLES, LAYOUT_TYPES, MAIN, PAGE_DOCUMENT, PAGE_RULES, PAGING_VARIABLES, PUBLIC, RENDER_FIELDS, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, RESERVED_LABELS, RESPONSIVE_BUCKETS, SECTION_KINDS, STORE_FIELDS, STORE_SCOPES, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, UnsafeDocumentError, VARIABLE_NAMESPACES, WALK_DIRECTIONS, _clearBundleCache, actionBindingKey, actionProblems, actionReferences, assembleCellProps, attachSelectionSetters, attachViewStateSetters, bindHostReads, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, componentsFor, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, hiddenWhenEmpty, hideWhenEmptyProblem, hostReadProblem, isComponentExport, isEach, isEmptyPropValue, isHostRead, layerName, loadBundle, loadBundles, loadBundlesSettled, loadPageData, loadScope, manifestPageFrom, mergeSectionReferences, mergeStates, nearestNames, needsWalk, nodePrintStyle, normalizeActionDeclaration, normalizeCell, normalizeRef, normalizeStructure, numberingFor, orderByVariable, pageBundleRefs, pageBundles, pageContainerStyle, pageContext, pageRuntimeFromValues, pageScopeKey, pageVariables, passesConditions, patchAt, prepareDocument, projectCellActions, projectCellData, projectLive, projectModule, projectScopeKey, projectSelections, projectViewState, queryKey, readField, readWalk, refKey, referencedLabels, referencesFor, resolveAction, resolveCell, resolveComponent, resolveDataSystem, resolveDeclarations, resolveDescriptorVariables, resolveReferences, resolveScopeId, resolveSystems, resolveWalkStart, rootCells, rowForCell, rowsInScope, runtimeReady, saveScope, sectionAnchor, selectionIssues, selectionShape, settled, shallowEqualBundle, shapeAt, stateNames, stateValue, structureIssues, systemsFromGraphs, systemsFromProcess, tableOfContents, usesStructureLayout, validateCell, validateDescriptor, validateManifest, validatePage, variableLabels, variableReferences, walkKey, walkRequest };
1187
+ export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HOST_READ_KEY, HYDRATED_CELL_FIELDS, LAYER_ROLES, LAYOUT_TYPES, MAIN, PAGE_DOCUMENT, PAGE_RULES, PAGING_VARIABLES, PUBLIC, RENDER_FIELDS, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, RESERVED_LABELS, RESPONSIVE_BUCKETS, SECTION_KINDS, STORE_FIELDS, STORE_SCOPES, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, UnsafeDocumentError, VARIABLE_NAMESPACES, WALK_DIRECTIONS, _clearBundleCache, actionBindingKey, actionProblems, actionReferences, assembleCellProps, attachSelectionSetters, attachViewStateSetters, bindHostReads, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, chunkPlan, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, componentNames, componentsFor, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, hiddenWhenEmpty, hideWhenEmptyProblem, hostReadProblem, isComponentExport, isEach, isEmptyPropValue, isHostRead, layerName, loadBundle, loadBundles, loadBundlesSettled, loadPageData, loadScope, manifestPageFrom, mergeSectionReferences, mergeStates, nearestNames, needsWalk, nodePrintStyle, normalizeActionDeclaration, normalizeCell, normalizeRef, normalizeStructure, numberingFor, orderByVariable, pageBundleRefs, pageBundles, pageContainerStyle, pageContext, pageForCell, pageRuntimeFromValues, pageScopeKey, pageVariables, parseChunkPlans, parseComponentManifest, passesConditions, patchAt, prepareDocument, projectCellActions, projectCellData, projectLive, projectModule, projectScopeKey, projectSelections, projectViewState, queryKey, readField, readWalk, refKey, referencedLabels, referencesFor, resolveAction, resolveCell, resolveComponent, resolveDataSystem, resolveDeclarations, resolveDescriptorVariables, resolveReferences, resolveScopeId, resolveSystems, resolveWalkStart, rootCells, rowForCell, rowsInScope, rowsNeededBy, runtimeReady, saveScope, sectionAnchor, selectionIssues, selectionShape, settled, shallowEqualBundle, shapeAt, stateNames, stateValue, structureIssues, systemsFromGraphs, systemsFromProcess, tableOfContents, usesStructureLayout, validateCell, validateDescriptor, validateManifest, validatePage, variableLabels, variableReferences, walkKey, walkRequest };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as failedLabels, a as projectSelections, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, k as rootCells, m as documentProfile, n as attachViewStateSetters, o as projectViewState, p as cellPlacementStyle, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as hiddenWhenEmpty, x as projectCellData, y as hideWhenEmptyProblem } from "./chunks/projection-e8MHn6Bt.js";
1
+ import { A as rootCells, S as projectCellData, _ as assembleCellProps, a as projectSelections, b as hideWhenEmptyProblem, d as bundleNameOf, f as resolveComponent, g as pageContainerStyle, h as documentProfile, i as projectLive, m as cellPlacementStyle, n as attachViewStateSetters, o as projectViewState, p as cellAttributes, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as failedLabels, y as hiddenWhenEmpty } from "./chunks/projection-qLyY8X3J.js";
2
2
  import { C as passesConditions, S as pageContext, T as settled, b as cellResolutionContext, c as pageVariables, v as EACH_DEFAULT_AS, w as resolveReferences, y as cellContext } from "./chunks/query-D_f73wsU.js";
3
3
  import { a as deriveSectionReferences, c as nodePrintStyle, d as referencesFor, f as sectionAnchor, g as usesStructureLayout, i as deriveSectionNumbering, l as normalizeStructure, m as structureIssues, o as isSectionNode, p as sortByOrder, r as deriveElementReferences, s as mergeSectionReferences, t as PAGE_DOCUMENT, u as numberingFor, v as bindHostReads, w as declaredActions } from "./chunks/structure-Ds2wfhkH.js";
4
4
  import { a as goToQuestion, c as missing, f as progress, g as visibleSteps, h as stepKind, i as goTo, l as move, m as settle, n as enterAdvances, o as isReadOnlyStatus, p as questionsOf, s as linkTo, t as defaultMode, u as positionFromLink } from "./chunks/forms-DxA9WzCt.js";
@@ -279,6 +279,10 @@ function CellView({ cell, env, nested = false, injectedProps }) {
279
279
  scope: env.bundles,
280
280
  core: env.core
281
281
  }) : null;
282
+ if (!found && env.bundles && env.moreBundlesComing && env.loadRest) {
283
+ queueMicrotask(env.loadRest);
284
+ return jsx(CellPlaceholder, { state: "loading" });
285
+ }
282
286
  if (!found) {
283
287
  env.onDiagnostic?.({
284
288
  severity: "warning",
@@ -298,6 +302,11 @@ function CellView({ cell, env, nested = false, injectedProps }) {
298
302
  })
299
303
  });
300
304
  }, [cell, env]);
305
+ const waitingForLineage = Boolean(env.bundles && !resolved && cell.component && env.moreBundlesComing && !env.bundlesFailed);
306
+ const loadRest = env.loadRest;
307
+ useEffect(() => {
308
+ if (waitingForLineage) loadRest?.();
309
+ }, [waitingForLineage, loadRest]);
301
310
  const contract = resolved && env.bundles ? env.bundles.find((b) => b.label === resolved.source)?.contracts[cell.component] : void 0;
302
311
  const size = useContainerSize(frame, Boolean(contract?.size));
303
312
  const loadedOwn = env.cellData?.[cell.id];
@@ -375,6 +384,7 @@ function CellView({ cell, env, nested = false, injectedProps }) {
375
384
  onRetry: env.retry,
376
385
  children: "This part of the page couldn't load."
377
386
  });
387
+ else if (!resolved && waitingForLineage) body = jsx(CellPlaceholder, { state: "loading" });
378
388
  else if (!resolved) body = jsxs(CellNotice, {
379
389
  state: "not-found",
380
390
  component: cell.component,
@@ -477,6 +487,7 @@ function CellView({ cell, env, nested = false, injectedProps }) {
477
487
  return jsx("div", {
478
488
  ref: frame,
479
489
  ...cellAttributes(cell),
490
+ "data-bundle": resolved ? bundleNameOf(resolved.source, env.bundles) : void 0,
480
491
  "data-nested": nested ? "" : void 0,
481
492
  ...extra?.attributes,
482
493
  className: ["cell", cell.layout?.className].filter(Boolean).join(" "),
package/dist/runtime.js CHANGED
@@ -1,4 +1,4 @@
1
- import { s as runtimeReady } from "./chunks/load-H7hUCwPc.js";
1
+ import { s as runtimeReady } from "./chunks/load-CAus-wv_.js";
2
2
  import { a as createStackStore, t as clearAllScopes } from "./chunks/persistence-hurkUUQ0.js";
3
3
  import { PINNED_RUNTIMES, READY_GLOBAL, RESOLVE_GLOBAL, RUNTIME_GLOBAL, buildImportMap } from "@peripheries/runtime";
4
4
  import * as React from "react";
package/dist/testing.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { l as prepareDocument } from "./chunks/query-D_f73wsU.js";
2
- import { o as projectModule } from "./chunks/load-H7hUCwPc.js";
2
+ import { o as projectModule } from "./chunks/load-CAus-wv_.js";
3
3
  import { i as bundleScope } from "./chunks/refs-Csgh6rXq.js";
4
- import { n as pageBundles, t as pageBundleRefs } from "./chunks/page-bundles-_wsGO9WU.js";
4
+ import { n as pageBundleRefs, r as pageBundles } from "./chunks/page-bundles-dUYH4D73.js";
5
5
  import { r as fromPageSteps } from "./chunks/forms-DxA9WzCt.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  var __defProp = Object.defineProperty;
@@ -0,0 +1,22 @@
1
+ export type ManifestComponent = {
2
+ js: string;
3
+ imports?: string[];
4
+ css?: string[];
5
+ requires?: Record<string, string[]>;
6
+ };
7
+ export type ComponentManifest = {
8
+ manifest: 1;
9
+ lineage: string;
10
+ base: 'version';
11
+ exports?: Record<string, string>;
12
+ components: Record<string, ManifestComponent>;
13
+ };
14
+ export declare function parseComponentManifest(value: unknown): ComponentManifest | null;
15
+ export type ChunkPlan = {
16
+ base: string;
17
+ entries: Record<string, string>;
18
+ js: string[];
19
+ css: string[];
20
+ };
21
+ export declare function chunkPlan(manifest: ComponentManifest, names: Iterable<string>, base: string): ChunkPlan;
22
+ export declare function parseChunkPlans(value: unknown): Record<string, ChunkPlan> | null;
@@ -1,4 +1,5 @@
1
1
  import type { ComponentType } from 'react';
2
+ import { type ChunkPlan } from './component-manifest.js';
2
3
  export type BundleRow = {
3
4
  id: string;
4
5
  org_id: string;
@@ -30,14 +31,17 @@ export type BundleFiles = {
30
31
  url: (row: BundleRow, file: string) => string | null;
31
32
  import?: (url: string) => Promise<Record<string, unknown>>;
32
33
  fetch?: (url: string) => Promise<Response>;
34
+ chunkPlan?: (specifier: string) => ChunkPlan | null;
35
+ linkStyles?: (urls: string[]) => void;
33
36
  };
34
37
  export declare function runtimeReady(g?: Record<string, unknown>): Promise<void>;
35
- export declare function loadBundle(row: BundleRow, files: BundleFiles): Promise<LoadedBundle>;
38
+ export declare function loadBundle(row: BundleRow, files: BundleFiles, wanted?: ReadonlySet<string> | 'all'): Promise<LoadedBundle>;
36
39
  export type LoadedBundles = {
37
40
  loaded: LoadedBundle[];
38
41
  failed: string[];
39
42
  };
43
+ export declare function neededRows(rows: BundleRow[], files: BundleFiles, only: ReadonlySet<string>): Promise<BundleRow[] | null>;
40
44
  export declare function loadWaves(rows: BundleRow[], files: BundleFiles): Promise<BundleRow[][]>;
41
- export declare function loadBundlesSettled(rows: BundleRow[], files: BundleFiles): Promise<LoadedBundles>;
45
+ export declare function loadBundlesSettled(rows: BundleRow[], files: BundleFiles, only?: ReadonlySet<string>, names?: ReadonlySet<string>): Promise<LoadedBundles>;
42
46
  export declare function loadBundles(rows: BundleRow[], files: BundleFiles): Promise<LoadedBundle[]>;
43
47
  export declare function _clearBundleCache(): void;
@@ -4,6 +4,8 @@ import { type LineageRef } from './refs.js';
4
4
  export declare function pageBundleRefs(scope: LineageRef[], cells: PageCell[], pageOrgId: string | null): LineageRef[];
5
5
  export declare function rowsInScope<R extends Pick<BundleRow, 'id' | 'bundle_name' | 'org_slug' | 'org_id'>>(rows: readonly R[], scope: LineageRef[]): R[];
6
6
  export declare function rowForCell<R extends Pick<BundleRow, 'id' | 'bundle_name' | 'org_slug' | 'org_id'>>(rows: readonly R[], cell: PageCell, pageOrgId: string | null): R | null;
7
+ export declare function rowsNeededBy(rows: readonly BundleRow[], cells: readonly Pick<PageCell, 'component' | 'bundle_ref'>[], pageOrgId: string | null): Set<string>;
8
+ export declare function componentNames(cells: readonly Pick<PageCell, 'component'>[]): Set<string>;
7
9
  export type PageBundles = {
8
10
  scope: LoadedBundle[] | null;
9
11
  forCell: (cell: PageCell) => LoadedBundle | null;
@@ -10,3 +10,4 @@ export declare function resolveComponent(name: string, { cellBundle, scope, core
10
10
  scope: LoadedBundle[];
11
11
  core: CoreRegistry;
12
12
  }): ResolvedComponent | null;
13
+ export declare function bundleNameOf(source: string, scope: readonly LoadedBundle[] | null | undefined): string;
@@ -1,4 +1,5 @@
1
1
  export { CONTENT_FIELDS, hasRef, HYDRATED_CELL_FIELDS, normalizeCell, resolveCell, RENDER_FIELDS, rootCells, STORE_FIELDS, type CellSource, type ResolvedCell } from './cells.js';
2
+ export { pageForCell } from './only-cell.js';
2
3
  export { buildDataContext, collectDeclarations, collectDescriptors, collectStatic, readField, resolveDeclarations, type ResolvedDeclaration, type StateRead } from './data-context.js';
3
4
  export { mergeStates, needsWalk, readWalk, referencedLabels, RESERVED_LABELS, resolveWalkStart, stateNames, stateValue, systemsFromGraphs, systemsFromProcess, walkKey, walkRequest, type Diagnostic, type GraphSystem, type ProcessSystems, type RawWalk, type WalkBinding, type WalkRequest, type WalkStart, } from './graph.js';
4
5
  export { LAYER_ROLES, layerName, type LayerType } from './layers.js';
@@ -19,7 +20,8 @@ export { assembleCellProps, hiddenWhenEmpty, hideWhenEmptyProblem, isEmptyPropVa
19
20
  export { cellAttributes, cellPlacementStyle, pageContainerStyle } from './layout.js';
20
21
  export { deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, mergeSectionReferences, nodePrintStyle, normalizeStructure, numberingFor, PAGE_DOCUMENT, referencesFor, SECTION_KINDS, sectionAnchor, structureIssues, tableOfContents, usesStructureLayout, type ContentsEntry, type LayoutNode, type SectionNumbering, type SectionReference, type SectionReferences, } from './structure.js';
21
22
  export { _clearBundleCache, isComponentExport, loadBundle, loadBundles, loadBundlesSettled, projectModule, runtimeReady, type BundleFiles, type BundleRow, type LoadedBundle, type LoadedBundles, } from './bundles/load.js';
22
- export { pageBundleRefs, pageBundles, rowForCell, rowsInScope, type PageBundles } from './bundles/page-bundles.js';
23
+ export { chunkPlan, parseChunkPlans, parseComponentManifest, type ChunkPlan, type ComponentManifest, type ManifestComponent } from './bundles/component-manifest.js';
24
+ export { componentNames, pageBundleRefs, pageBundles, rowForCell, rowsInScope, rowsNeededBy, type PageBundles } from './bundles/page-bundles.js';
23
25
  export { bundleScope, CORE_SPECIFIER, MAIN, normalizeRef, PUBLIC, refKey, type BundleRef, type BundleScopeInput, type LineageRef, type SharedLineage } from './bundles/refs.js';
24
26
  export { resolveComponent, type CoreRegistry, type ResolvedComponent } from './bundles/resolve.js';
25
27
  export { createStackStore, type StackStoreApi } from './store/create-store.js';
@@ -7,6 +7,7 @@ export declare const LAYER_ROLES: {
7
7
  readonly organisation: null;
8
8
  readonly "process-system": "process";
9
9
  readonly question: null;
10
+ readonly refinement: null;
10
11
  readonly submission: null;
11
12
  };
12
13
  export type LayerType = keyof typeof LAYER_ROLES;
@@ -41,6 +41,8 @@ export type PageScope = {
41
41
  embedded?: boolean;
42
42
  version?: VersionContext;
43
43
  recordedEmbeds?: RecordedEmbed[];
44
+ only?: string;
45
+ structure?: boolean;
44
46
  };
45
47
  export type CellWalk = {
46
48
  traversal: Traversal;
@@ -71,5 +73,5 @@ type SystemsSource = Pick<GraphSource, 'graphSystems' | 'processSystems'>;
71
73
  export declare function resolveSystems(source: SystemsSource, page: ProjectPage): Promise<ProcessSystems>;
72
74
  export declare function resolveDataSystem(source: SystemsSource, page: ProjectPage): Promise<string | null>;
73
75
  export declare function unresolvedEntry(missing: string[], data: DataContext): DataEntry;
74
- export declare function loadPageData(page: ProjectPage, source: GraphSource, scope?: PageScope): Promise<PageRuntime>;
76
+ export declare function loadPageData(whole: ProjectPage, source: GraphSource, scope?: PageScope): Promise<PageRuntime>;
75
77
  export {};
@@ -0,0 +1,2 @@
1
+ import type { ProjectPage } from './types.js';
2
+ export declare function pageForCell(page: ProjectPage, cellId: string): ProjectPage;
@@ -20,6 +20,8 @@ export type CellEnvironment = {
20
20
  bundles: LoadedBundle[] | null;
21
21
  bundleFor: (cell: PageCell) => LoadedBundle | null;
22
22
  bundlesFailed?: boolean;
23
+ loadRest?: () => void;
24
+ moreBundlesComing?: boolean;
23
25
  retry?: () => void;
24
26
  core: CoreRegistry;
25
27
  navigate: (to: string) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peripheries/renderer",
3
- "version": "0.28.1",
3
+ "version": "0.29.0",
4
4
  "description": "The one renderer for pages of federated component bundles: a framework-free core, a React renderer, the runtime a page boots with, and golden pages for testing.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1,104 +0,0 @@
1
- import { READY_GLOBAL } from "@peripheries/runtime";
2
- function isComponentExport(value) {
3
- if (typeof value === "function") return true;
4
- if (!value || typeof value !== "object") return false;
5
- const tag = value.$$typeof;
6
- return tag === Symbol.for("react.forward_ref") || tag === Symbol.for("react.memo") || tag === Symbol.for("react.lazy");
7
- }
8
- function projectModule(row, mod, contracts = {}) {
9
- const components = {};
10
- for (const c of row.components) {
11
- const exported = mod[c.exposed_export ?? c.component_name ?? ""];
12
- if (c.component_name && isComponentExport(exported)) components[c.component_name] = exported;
13
- }
14
- return {
15
- id: row.id,
16
- label: row.bundle_name === "main" ? row.org_slug : `${row.org_slug}/${row.bundle_name}`,
17
- ...row.specifier ? { specifier: row.specifier } : {},
18
- components,
19
- contracts,
20
- documentProfiles: mod.documentProfiles,
21
- paginatorBindings: mod.PAGINATOR_BINDINGS
22
- };
23
- }
24
- function runtimeReady(g = globalThis) {
25
- return g[READY_GLOBAL] ?? Promise.resolve();
26
- }
27
- var cache = new Map();
28
- var browserImport = (url) => import(url);
29
- function loadBundle(row, files) {
30
- let pending = cache.get(row.id);
31
- if (!pending) {
32
- pending = (async () => {
33
- const url = files.url(row, "index.js");
34
- if (!url) throw new Error(`[bundles] ${row.org_slug}/${row.bundle_name} has no storage path`);
35
- await runtimeReady();
36
- const contractsUrl = files.url(row, "contracts.json");
37
- const get = files.fetch ?? ((u) => fetch(u));
38
- const [mod, contracts] = await Promise.all([(files.import ?? browserImport)(row.specifier ?? url), get(contractsUrl).then((r) => r.ok ? r.json() : null, () => null)]);
39
- return projectModule(row, mod, contracts?.components ?? {});
40
- })();
41
- pending.catch(() => cache.delete(row.id));
42
- cache.set(row.id, pending);
43
- }
44
- return pending;
45
- }
46
- var escapeRe = (v) => v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
47
- async function sharedDependencies(rows, files) {
48
- const get = files.fetch ?? ((u) => fetch(u));
49
- const bySpecifier = new Map(rows.map((r) => [r.specifier, r.id]));
50
- const deps = new Map();
51
- try {
52
- await Promise.all(rows.map(async (r) => {
53
- if (r.requires) return void deps.set(r.id, r.requires.map((s) => bySpecifier.get(s)).filter((id) => !!id && id !== r.id));
54
- const url = files.url(r, "index.js");
55
- const res = url ? await get(url) : null;
56
- if (!res?.ok) throw new Error("unreadable");
57
- const source = await res.text();
58
- deps.set(r.id, rows.filter((o) => o.id !== r.id && new RegExp(`(?:from|import)\\s*\\(?\\s*(["'\`])${escapeRe(o.specifier)}\\1`).test(source)).map((o) => o.id));
59
- }));
60
- } catch {
61
- return null;
62
- }
63
- return deps;
64
- }
65
- async function loadWaves(rows, files) {
66
- const shared = rows.filter((r) => r.specifier);
67
- const rest = rows.filter((r) => !r.specifier);
68
- const waves = [];
69
- const deps = shared.length > 1 ? await sharedDependencies(shared, files) : null;
70
- if (!deps) return [rows];
71
- const done = new Set();
72
- let left = shared;
73
- while (left.length) {
74
- const wave = left.filter((r) => (deps.get(r.id) ?? []).every((d) => done.has(d)));
75
- if (!wave.length) return [rows];
76
- waves.push(wave);
77
- wave.forEach((r) => done.add(r.id));
78
- left = left.filter((r) => !done.has(r.id));
79
- }
80
- if (rest.length) waves.push(rest);
81
- return waves;
82
- }
83
- async function loadBundlesSettled(rows, files) {
84
- const loaded = [];
85
- const failed = [];
86
- for (const wave of await loadWaves(rows, files)) (await Promise.allSettled(wave.map((r) => loadBundle(r, files)))).forEach((s, i) => {
87
- if (s.status === "fulfilled") loaded.push(s.value);
88
- else {
89
- failed.push(wave[i].id);
90
- console.warn(`[bundles] ${wave[i].org_slug}/${wave[i].bundle_name} failed to load:`, s.reason);
91
- }
92
- });
93
- return {
94
- loaded,
95
- failed
96
- };
97
- }
98
- async function loadBundles(rows, files) {
99
- return (await loadBundlesSettled(rows, files)).loaded;
100
- }
101
- function _clearBundleCache() {
102
- cache.clear();
103
- }
104
- export { loadBundlesSettled as a, loadBundles as i, isComponentExport as n, projectModule as o, loadBundle as r, runtimeReady as s, _clearBundleCache as t };