@mosetta/runtime 0.0.9 → 0.0.11

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 (2) hide show
  1. package/package.json +3 -3
  2. package/src/bootstrap.ts +31 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mosetta/runtime",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "license": "MIT",
5
5
  "description": "mosetta browser runtime: start() (resolver prolog, tree loading, holder), version resolver, safe tile loader, asset runtime. Framework-agnostic — the react mount (startAndMount) lives in @mosetta/react/start. Ships as an ordinary package tile; the root export is the component-facing asset surface.",
6
6
  "type": "module",
@@ -17,8 +17,8 @@
17
17
  "./naming": "./src/naming.js"
18
18
  },
19
19
  "dependencies": {
20
- "@mosetta/core": "0.0.9",
21
- "@mosetta/di": "0.0.9"
20
+ "@mosetta/core": "0.0.11",
21
+ "@mosetta/di": "0.0.11"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"
package/src/bootstrap.ts CHANGED
@@ -151,11 +151,15 @@ async function run(): Promise<IStartResult> {
151
151
  // LOAD path.
152
152
  const catalog = new Map<string, ITileDescriptor | null>(Object.entries(realmCatalog));
153
153
  const DEP_PREFIX = '_ns_package_t_package_n_';
154
+ // where an entity outside the catalog was found: beside its importer, or at another tile host the
155
+ // realm knows — a block of a project's palette placed in the editor is loaded by the workbench's
156
+ // page, whose slice does not name it
157
+ const foundAt = new Map<string, string>();
154
158
  // an entity lives with the code source its catalog entry names, the host when it names none; an
155
- // entity outside the catalog — with the base it was asked from
159
+ // entity outside the catalog — where its descriptor was found, else the base it was asked from
156
160
  const sourceBaseOf = (id: string, pb: string): string => {
157
161
  const entry = catalog.get(id) ?? realmCatalog[id];
158
- if (!entry) return pb;
162
+ if (!entry) return foundAt.get(id) ?? pb;
159
163
  return (entry.provider ? sources[entry.provider] : base) || pb;
160
164
  };
161
165
  const entityFileUrl = (id: string, file: string, pb: string): string => new URL('modules/' + id + '/' + file, sourceBaseOf(id, pb)).href; // flat layout
@@ -165,12 +169,24 @@ async function run(): Promise<IStartResult> {
165
169
  const sliceIntegrity = (id: string): string | undefined => realmCatalog[id]?.integrity;
166
170
  const artifactUrl = (id: string, file: string, pb: string): string => versionedUrl(entityFileUrl(id, file, pb), sliceIntegrity(id));
167
171
  const fetched = new Map<string, Promise<ITileDescriptor | null>>();
172
+ const descriptorAt = (id: string, at: string): Promise<ITileDescriptor | null> => fetch(new URL('modules/' + id + '/' + id + '.json', at).href)
173
+ .then((r) => (r.ok ? (r.json() as Promise<ITileDescriptor>) : null))
174
+ .catch(() => null);
175
+ // an entity outside the catalog: its co-located descriptor beside the base it was asked from, else
176
+ // at the realm's other tile hosts (the host last) — the first that has it is where it lives
168
177
  const entityOf = (id: string, pb: string): Promise<ITileDescriptor | null> => {
169
178
  if (catalog.has(id)) return Promise.resolve(catalog.get(id) ?? null);
170
179
  if (!fetched.has(id)) {
171
- fetched.set(id, fetch(entityFileUrl(id, id + '.json', pb))
172
- .then((r) => (r.ok ? (r.json() as Promise<ITileDescriptor>) : null))
173
- .catch(() => null));
180
+ fetched.set(id, (async () => {
181
+ for (const at of new Set([foundAt.get(id) ?? pb, ...Object.values(sources), base])) {
182
+ const entity = await descriptorAt(id, at);
183
+ if (entity) {
184
+ foundAt.set(id, at);
185
+ return entity;
186
+ }
187
+ }
188
+ return null;
189
+ })());
174
190
  }
175
191
  return fetched.get(id)!;
176
192
  };
@@ -299,15 +315,21 @@ async function run(): Promise<IStartResult> {
299
315
  getModule: (ref: string): ILoadedTile | undefined => (handedOver.has(ref) ? loader.get(ref) : undefined),
300
316
  loadModule: (ref: string, pb?: string): Promise<ILoadedTile> => {
301
317
  const ready = handedOver.has(ref) ? loader.get(ref) : undefined;
302
- if (ready) return Promise.resolve(ready);
318
+ if (ready && !ready.error) return Promise.resolve(ready);
303
319
  const pending = handing.get(ref);
304
320
  if (pending) return pending;
305
- const target = pb || providerOf(ref);
306
- const handover = Promise.all([ensureCss(ref, target), loader.load(ref, target)]).then(([, loaded]) => {
321
+ const handover = (async () => {
322
+ const asked = pb || providerOf(ref);
323
+ // an entity outside the catalog: found first — its code loads from where its descriptor lies
324
+ if (!catalog.has(ref) && !realmCatalog[ref]) await entityOf(ref, asked);
325
+ const target = sourceBaseOf(ref, asked);
326
+ // a failure before (asked where it does not lie) is tried again
327
+ loader.forget(ref);
328
+ const [, loaded] = await Promise.all([ensureCss(ref, target), loader.load(ref, target)]);
307
329
  handedOver.add(ref);
308
330
  handing.delete(ref);
309
331
  return loaded;
310
- });
332
+ })();
311
333
  handing.set(ref, handover);
312
334
  return handover;
313
335
  },