@expofp/loader 1.0.63 → 1.0.65

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.
@@ -1,15 +1,15 @@
1
- import { d as x, r as v, b as O, e as R, f as w, h as d, p as S } from "./bundle.js";
1
+ import { d as w, r as O, b as R, e as S, f as b, h as x, p as E } from "./bundle.js";
2
2
  function u(t, n) {
3
3
  let r = n >>> 0;
4
4
  for (let a = 0; a < t.length; a++)
5
5
  r ^= t.charCodeAt(a), r = Math.imul(r, 16777619);
6
6
  return (r >>> 0).toString(16).padStart(8, "0");
7
7
  }
8
- function E(t) {
8
+ function j(t) {
9
9
  return u(t, 2166136261) + // your original seed
10
10
  u(t, 569420461) + u(t, 461845907) + u(t, 2246822507);
11
11
  }
12
- const m = /* @__PURE__ */ new Map(), $ = /* @__PURE__ */ new Map(), j = /* @__PURE__ */ new Set([
12
+ const m = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Set([
13
13
  "con",
14
14
  "prn",
15
15
  "aux",
@@ -33,29 +33,30 @@ const m = /* @__PURE__ */ new Map(), $ = /* @__PURE__ */ new Map(), j = /* @__PU
33
33
  "lpt8",
34
34
  "lpt9"
35
35
  ]);
36
- function y(t) {
36
+ function I(t) {
37
37
  let n = t.normalize("NFKD").replace(/[^\p{Letter}\p{Number}]+/gu, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
38
- return n = n.replace(/[<>:"/\\|?*]/g, ""), n = n.replace(/[. ]+$/g, ""), n || (n = "file"), j.has(n) && (n += "-file"), n;
38
+ return n = n.replace(/[<>:"/\\|?*]/g, ""), n = n.replace(/[. ]+$/g, ""), n || (n = "file"), y.has(n) && (n += "-file"), n;
39
39
  }
40
40
  function h(t) {
41
41
  const n = m.get(t);
42
42
  if (n) return n;
43
- const r = y(t);
43
+ const r = I(t);
44
44
  let a = r, o = 2;
45
45
  for (; ; ) {
46
- const e = $.get(a);
46
+ const e = p.get(a);
47
47
  if (!e)
48
- return $.set(a, t), m.set(t, a), a;
48
+ return p.set(a, t), m.set(t, a), a;
49
49
  if (e === t)
50
50
  return m.set(t, a), a;
51
51
  a = `${r}-${o++}`;
52
52
  }
53
53
  }
54
- function I(t, n = "") {
54
+ const d = w("efp:loader:offline");
55
+ function M(t, n = "") {
55
56
  let r = h(t);
56
57
  return n && (r = `${h(n)}$${r}`), r.endsWith("/") ? r += "index.json" : r.endsWith(".json") || (r += ".json"), "./" + r;
57
58
  }
58
- function M(t, n = "") {
59
+ function P(t, n = "") {
59
60
  try {
60
61
  new URL(t);
61
62
  } catch {
@@ -70,26 +71,24 @@ function M(t, n = "") {
70
71
  const c = l.match(/[^a-zA-Z0-9\-._\/]/g);
71
72
  if (c) {
72
73
  const f = h(l);
73
- console.warn(
74
- `Warning: pathname contains invalid filesystem characters (${[
75
- ...new Set(c)
76
- ].join(
74
+ d(
75
+ `Pathname contains invalid filesystem characters (${[...new Set(c)].join(
77
76
  ", "
78
77
  )}), slugifying it: ${l}${s} => ${f}${s}`
79
78
  ), l = f;
80
79
  }
81
- if (e = l + s, e.length > 120 && (console.warn(
82
- `Warning: pathname is too long (${e.length} characters), truncating to 150 characters: ${e}`
80
+ if (e = l + s, e.length > 120 && (d(
81
+ `Pathname is too long (${e.length} characters), truncating to 150 characters: ${e}`
83
82
  ), e = e.substring(0, 120 - s.length) + s), i) {
84
- const f = E(i), g = e.lastIndexOf(".");
83
+ const f = j(i), g = e.lastIndexOf(".");
85
84
  g !== -1 ? e = `${e.slice(0, g)}.${f}${e.slice(g)}` : e = `${e}${f}`;
86
85
  }
87
86
  return `./${n}${o}${e}`;
88
87
  }
89
- const b = x("efp:loader:makeOffline");
88
+ const v = w("efp:loader:makeOffline");
90
89
  async function C(t) {
91
- b("makeOffline", t);
92
- const n = await p(t);
90
+ v("makeOffline", t);
91
+ const n = await $(t);
93
92
  let r = !1, a;
94
93
  async function* o() {
95
94
  a = yield* n, r = !0;
@@ -102,8 +101,8 @@ async function C(t) {
102
101
  files: o()
103
102
  };
104
103
  }
105
- async function* p(t) {
106
- b("makeOfflineInternal", t);
104
+ async function* $(t) {
105
+ v("makeOfflineInternal", t);
107
106
  const n = {
108
107
  refCache: /* @__PURE__ */ new Map(),
109
108
  forceFetch: !0,
@@ -113,7 +112,7 @@ async function* p(t) {
113
112
  async function* a(o, e) {
114
113
  if (!(typeof o[e] != "object" || o[e] === null)) {
115
114
  if ("$ref" in o[e]) {
116
- const i = v.filter((f) => O(f, o[e].$ref));
115
+ const i = O.filter((f) => R(f, o[e].$ref));
117
116
  if (i.length === 0)
118
117
  throw new Error(`No resolver found for ref: ${o[e].$ref}`);
119
118
  if (i.length > 1)
@@ -122,17 +121,17 @@ async function* p(t) {
122
121
  let l;
123
122
  switch (s.offlineMethod) {
124
123
  case "localizeRef":
125
- l = W;
124
+ l = U;
126
125
  break;
127
126
  case "resolveRef":
128
- l = U;
127
+ l = F;
129
128
  break;
130
129
  default:
131
130
  throw new Error(`Unknown offlineMethod: ${s.offlineMethod}`);
132
131
  }
133
132
  const c = yield* l(s, o[e].$ref, n);
134
133
  if (Object.isFrozen(o)) throw new Error("Unexpected frozen node during makeOffline");
135
- o[e] = R({ $ref: c }, o[e]);
134
+ o[e] = S({ $ref: c }, o[e]);
136
135
  }
137
136
  if (Array.isArray(o[e]))
138
137
  for (const [i] of o[e].entries())
@@ -143,17 +142,17 @@ async function* p(t) {
143
142
  }
144
143
  }
145
144
  }
146
- async function* W(t, n, r) {
147
- const a = w(await d(t, n, r));
148
- yield* p(a);
149
- const o = S(n), e = M(o);
145
+ async function* U(t, n, r) {
146
+ const a = b(await x(t, n, r));
147
+ yield* $(a);
148
+ const o = E(n), e = P(o);
150
149
  return yield { url: o, targetFilePath: e }, `${n.substring(0, n.length - o.length - 1)}:${e}`;
151
150
  }
152
- async function* U(t, n, r) {
153
- const a = w(await d(t, n, r)), o = I(n);
154
- return yield { data: yield* p(a), targetFilePath: o }, o;
151
+ async function* F(t, n, r) {
152
+ const a = b(await x(t, n, r)), o = M(n);
153
+ return yield { data: yield* $(a), targetFilePath: o }, o;
155
154
  }
156
155
  export {
157
156
  C as makeOffline
158
157
  };
159
- //# sourceMappingURL=makeOffline-Doxc2dX7.js.map
158
+ //# sourceMappingURL=makeOffline-DH6wJEem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeOffline-DH6wJEem.js","sources":["../../src/offline/hashString.ts","../../src/offline/slugify.ts","../../src/offline/tools.ts","../../src/offline/makeOffline.ts"],"sourcesContent":["// 32-bit murmur-ish hash with configurable seed\nfunction murmur32WithSeed(str: string, seed: number): string {\n let h = seed >>> 0;\n\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193); // FNV-ish prime, good mixer\n }\n\n return (h >>> 0).toString(16).padStart(8, '0'); // 8 hex chars\n}\n\n// 128-bit (MD5-width) hash: 4 × 32-bit parts concatenated\nexport function hashString(str: string): string {\n return (\n murmur32WithSeed(str, 0x811c9dc5) + // your original seed\n murmur32WithSeed(str, 0x21f0aaad) +\n murmur32WithSeed(str, 0x1b873593) +\n murmur32WithSeed(str, 0x85ebca6b)\n );\n}\n","// Module-level caches\nconst inputToSlug = new Map<string, string>();\nconst slugToInput = new Map<string, string>();\n\nconst WINDOWS_RESERVED = new Set([\n \"con\", \"prn\", \"aux\", \"nul\",\n \"com1\", \"com2\", \"com3\", \"com4\", \"com5\", \"com6\", \"com7\", \"com8\", \"com9\",\n \"lpt1\", \"lpt2\", \"lpt3\", \"lpt4\", \"lpt5\", \"lpt6\", \"lpt7\", \"lpt8\", \"lpt9\",\n]);\n\nfunction makeBaseSlug(input: string): string {\n let slug = input\n .normalize(\"NFKD\")\n // All non letters/numbers → \"-\"\n .replace(/[^\\p{Letter}\\p{Number}]+/gu, \"-\")\n // Collapse multiple \"-\"\n .replace(/-+/g, \"-\")\n // Trim \"-\" from start/end\n .replace(/^-|-$/g, \"\")\n .toLowerCase();\n\n // Strip forbidden Windows characters just in case\n slug = slug.replace(/[<>:\"/\\\\|?*]/g, \"\");\n\n // Windows forbids trailing space/period\n slug = slug.replace(/[. ]+$/g, \"\");\n\n // Fallback if everything was stripped\n if (!slug) slug = \"file\";\n\n // Avoid bare reserved device names\n if (WINDOWS_RESERVED.has(slug)) {\n slug += \"-file\";\n }\n\n return slug;\n}\n\nexport function slugifyFsUnique(input: string): string {\n // If we've seen this exact input before, return the same slug\n const existing = inputToSlug.get(input);\n if (existing) return existing;\n\n const base = makeBaseSlug(input);\n let candidate = base;\n let counter = 2;\n\n while (true) {\n const existingInput = slugToInput.get(candidate);\n\n if (!existingInput) {\n // Free slug → claim it for this input\n slugToInput.set(candidate, input);\n inputToSlug.set(input, candidate);\n return candidate;\n }\n\n if (existingInput === input) {\n // Same input somehow (super defensive)\n inputToSlug.set(input, candidate);\n return candidate;\n }\n\n // Collision: same slug already used by different input → add suffix\n candidate = `${base}-${counter++}`;\n }\n}\n\n// // Optional: to reset between runs/tests\n// export function resetSlugCache() {\n// inputToSlug.clear();\n// slugToInput.clear();\n// }","import debug from 'debug';\nimport { hashString } from './hashString';\nimport { slugifyFsUnique } from './slugify';\n\nconst log = debug('efp:loader:offline');\n\nexport function makeUniqueJsonTargetPathFromString(str: string, namespace: string = ''): string {\n // const hash = hashString(str);\n let result = slugifyFsUnique(str); // + '-' + hash;\n if (namespace) {\n result = `${slugifyFsUnique(namespace)}$${result}`;\n }\n\n if (result.endsWith('/')) {\n result += 'index.json';\n } else if (!result.endsWith('.json')) {\n result += '.json';\n }\n return './' + result;\n // handle directory case\n}\n\nexport function makeTargetPathFromUrl(url: string, prefix: string = ''): string {\n // https://example.com/dir1/dir2/a.js => \"{prefix}{origin-slug}/dir1/dir2/a.js\";\n // https://example.com/dir1/dir2/a.js?params => \"{prefix}{origin-slug}/dir1/dir2/a{paramsmd5hash}.js\";\n // use slugify.ts\n\n try {\n new URL(url);\n } catch {\n debugger;\n }\n const urlObj = new URL(url);\n const origin = `${urlObj.protocol}//${urlObj.host}`;\n const originSlug = slugifyFsUnique(origin);\n\n let pathname = urlObj.pathname;\n let search = urlObj.search;\n\n // if path doesn't end with extension, throw\n if (!pathname.match(/\\.[^\\/]+$/)) {\n throw new Error(`Cannot make target path from URL without file extension: ${url}`);\n }\n\n const extension = pathname.substring(pathname.lastIndexOf('.'));\n let pathnameWithoutExtension = pathname.substring(0, pathname.lastIndexOf('.'));\n\n // check the pathname contains only valid fs characters\n const invalidPathnameChars = pathnameWithoutExtension.match(/[^a-zA-Z0-9\\-._\\/]/g);\n if (invalidPathnameChars) {\n const fixedPathnameWithoutExtension = slugifyFsUnique(pathnameWithoutExtension);\n log(\n `Pathname contains invalid filesystem characters (${[...new Set(invalidPathnameChars)].join(\n ', '\n )}), slugifying it: ${pathnameWithoutExtension}${extension} => ${fixedPathnameWithoutExtension}${extension}`\n );\n pathnameWithoutExtension = fixedPathnameWithoutExtension;\n }\n\n pathname = pathnameWithoutExtension + extension;\n\n if (pathname.length > 120) {\n log(\n `Pathname is too long (${pathname.length} characters), truncating to 150 characters: ${pathname}`\n );\n pathname = pathname.substring(0, 120 - extension.length) + extension;\n }\n\n if (search) {\n // create a hash from search params\n const hash = hashString(search);\n const dotIndex = pathname.lastIndexOf('.');\n if (dotIndex !== -1) {\n pathname = `${pathname.slice(0, dotIndex)}.${hash}${pathname.slice(dotIndex)}`;\n } else {\n pathname = `${pathname}${hash}`;\n }\n }\n\n // // handle directory case\n // if (pathname.endsWith('/')) {\n // pathname += '__index.json';\n // }\n\n return `./${prefix}${originSlug}${pathname}`;\n}\n","import debug from 'debug';\nimport {\n canResolve,\n parseRefValue,\n resolverResolve,\n type ResolveContextInternal,\n} from '../resolve';\nimport { resolvers } from '../resolvers';\nimport { createMergedObjectWithOverridenNonRefProps, deepClone } from '../shared';\nimport type { LocalFile, MakeOfflineResult, ManifestData, Resolver } from '../types';\nimport { makeTargetPathFromUrl, makeUniqueJsonTargetPathFromString } from './tools';\n\nconst log = debug('efp:loader:makeOffline');\n\nexport async function makeOffline(manifest: any): Promise<MakeOfflineResult> {\n log('makeOffline', manifest);\n // if (typeof manifest !== 'object' || manifest === null) {\n // throw new Error('Manifest must be an object');\n // }\n\n const res = await makeOfflineInternal(manifest);\n let done = false;\n let resultManifest: any;\n async function* files() {\n resultManifest = yield* res;\n done = true;\n }\n\n return {\n get manifest(): ManifestData {\n if (!done) throw new Error('Iterate over files before getting manifest');\n return resultManifest;\n },\n files: files() as AsyncGenerator<LocalFile, void, void>,\n };\n}\n\nasync function* makeOfflineInternal(manifest: any): AsyncGenerator<LocalFile, ManifestData, void> {\n log('makeOfflineInternal', manifest);\n const resolveContext: ResolveContextInternal = {\n refCache: new Map<string, Promise<any>>(),\n forceFetch: true,\n signal: null,\n };\n const parent = { manifest };\n yield* walk(parent, 'manifest');\n return parent.manifest;\n\n async function* walk(node: any, key: string | number): AsyncGenerator<LocalFile> {\n // console.log('walk', node, key, node[key]);\n // let node[key] = node[key];\n if (typeof node[key] !== 'object' || node[key] === null) {\n return;\n }\n // let resolversToUse1 = resolvers.filter((r) => r.canResolve(node[key].$ref));\n // const usedResolvers = new Set<Resolver>();\n // do {\n if ('$ref' in node[key]) {\n const resolversToUse = resolvers.filter((r) => canResolve(r, node[key].$ref));\n if (resolversToUse.length === 0) {\n throw new Error(`No resolver found for ref: ${node[key].$ref}`);\n }\n if (resolversToUse.length > 1) {\n throw new Error(`Multiple resolvers can make offline ref: ${node[key].$ref}`);\n }\n\n const resolver = resolversToUse[0];\n\n let func: typeof offlineLocalizeRef;\n switch (resolver.offlineMethod) {\n case 'localizeRef':\n func = offlineLocalizeRef;\n break;\n case 'resolveRef':\n func = offlineResolveRef;\n break;\n default:\n throw new Error(`Unknown offlineMethod: ${resolver.offlineMethod}`);\n }\n\n const mergeRef = yield* func(resolver, node[key].$ref, resolveContext);\n\n if (Object.isFrozen(node)) throw new Error('Unexpected frozen node during makeOffline');\n\n node[key] = createMergedObjectWithOverridenNonRefProps({ $ref: mergeRef }, node[key]);\n }\n\n // recurse\n if (Array.isArray(node[key])) {\n for (const [index] of node[key].entries()) {\n yield* walk(node[key], index);\n }\n } else if (typeof node[key] === 'object' && node[key] !== null) {\n for (const key1 of Object.keys(node[key])) {\n // debugger;\n yield* walk(node[key], key1);\n }\n }\n }\n}\n\n// function canResolve(resolver: Resolver, ref: string): boolean {\n// if (resolver.canResolve) {\n// return resolver.canResolve(ref);\n// }\n// if (resolver.schema) {\n// return canResolveRefSchema(ref, resolver.schema);\n// }\n// throw new Error('Resolver is missing canResolve method and schema property');\n// }\n\nasync function* offlineLocalizeRef(\n resolver: Resolver,\n ref: string,\n context: ResolveContextInternal\n): AsyncGenerator<LocalFile, string, void> {\n const refData = deepClone(await resolverResolve(resolver, ref, context));\n // emit assets\n yield* makeOfflineInternal(refData);\n const url = parseRefValue(ref);\n const targetFilePath = makeTargetPathFromUrl(url);\n // TODO: handle CSS and other text files that may reference other assets\n yield { url, targetFilePath };\n const schema = ref.substring(0, ref.length - url.length - 1);\n return `${schema}:${targetFilePath}`;\n}\n\nasync function* offlineResolveRef(\n resolver: Resolver,\n ref: string,\n context: ResolveContextInternal\n): AsyncGenerator<LocalFile, string, void> {\n const refData = deepClone(await resolverResolve(resolver, ref, context));\n const targetFilePath = makeUniqueJsonTargetPathFromString(ref);\n const data = yield* makeOfflineInternal(refData);\n yield { data, targetFilePath };\n return targetFilePath;\n}\n\n// export function createMakeOfflineResult(\n// manifest: any,\n// walk: (node: any, key: string | number) => AsyncGenerator<LocalFile>\n// ): MakeOfflineResult {\n// log('createMakeOfflineResult', manifest);\n// if (typeof manifest !== 'object' || manifest === null) {\n// throw new Error('Manifest must be an object');\n// }\n// const parent = { manifest };\n// let done = false;\n// async function* files() {\n// yield* walk(parent, 'manifest');\n// done = true;\n// }\n\n// return {\n// get manifest() {\n// if (!done) {\n// throw new Error('Cannot access manifest before all files are generated');\n// }\n// return parent.manifest;\n// },\n// files: files(),\n// };\n// }\n"],"names":["murmur32WithSeed","str","seed","h","i","hashString","inputToSlug","slugToInput","WINDOWS_RESERVED","makeBaseSlug","input","slug","slugifyFsUnique","existing","base","candidate","counter","existingInput","log","debug","makeUniqueJsonTargetPathFromString","namespace","result","makeTargetPathFromUrl","url","prefix","urlObj","origin","originSlug","pathname","search","extension","pathnameWithoutExtension","invalidPathnameChars","fixedPathnameWithoutExtension","hash","dotIndex","makeOffline","manifest","res","makeOfflineInternal","done","resultManifest","files","resolveContext","parent","walk","node","key","resolversToUse","resolvers","r","canResolve","resolver","func","offlineLocalizeRef","offlineResolveRef","mergeRef","createMergedObjectWithOverridenNonRefProps","index","key1","ref","context","refData","deepClone","resolverResolve","parseRefValue","targetFilePath"],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { d, a as f, resolve as s } from "./bundle.js";
2
+ import { makeOffline as c } from "./makeOffline-DH6wJEem.js";
3
+ const l = d("efp:loader:makeOfflineBundle");
4
+ async function* p(e) {
5
+ l("Bundling", e), f(e);
6
+ const a = await c(e), n = /* @__PURE__ */ new Map();
7
+ for await (const t of a.files)
8
+ if ("data" in t) {
9
+ n.set(t.targetFilePath, t.data);
10
+ const i = JSON.stringify(t.data, null, 2);
11
+ l("Bundling file with data", t.targetFilePath, i), yield {
12
+ path: t.targetFilePath,
13
+ data: new TextEncoder().encode(i).buffer
14
+ };
15
+ } else if ("url" in t) {
16
+ const i = await w(t.url);
17
+ l("Bundling file from url", t.targetFilePath), yield {
18
+ path: t.targetFilePath,
19
+ data: await i.arrayBuffer()
20
+ };
21
+ }
22
+ const r = await g(a.manifest, n);
23
+ yield {
24
+ path: "./index.html",
25
+ data: new TextEncoder().encode(r).buffer
26
+ };
27
+ }
28
+ const u = 10, o = /* @__PURE__ */ new Set();
29
+ async function w(e) {
30
+ for (; o.size >= u; )
31
+ await Promise.race(o);
32
+ const a = (async () => {
33
+ l("Fetching file for zip:", e);
34
+ const n = await fetch(e);
35
+ return n.ok || (e.includes("/data/fp.svg.ViewBox.js"), console.warn(`Warning: Failed to fetch ${e}: ${n.status}`)), await n.blob();
36
+ })();
37
+ o.add(a);
38
+ try {
39
+ return await a;
40
+ } finally {
41
+ o.delete(a);
42
+ }
43
+ }
44
+ async function g(e, a) {
45
+ const n = await s(e, "/runtime/entry", { preResolvedRefs: a });
46
+ return `
47
+ <!DOCTYPE html>
48
+ <script type="module">
49
+ import { load } from ${JSON.stringify(n)};
50
+ await load(${JSON.stringify(e)});
51
+ console.info('🚀 loaded');
52
+ <\/script>
53
+ `;
54
+ }
55
+ export {
56
+ p as makeOfflineBundle
57
+ };
58
+ //# sourceMappingURL=makeOfflineBundle-C-xleVMN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeOfflineBundle-C-xleVMN.js","sources":["../../src/offline/makeOfflineBundle.ts"],"sourcesContent":["import debug from 'debug';\nimport { resolve } from '..';\nimport { makeOffline } from './makeOffline';\nimport { deepFreeze } from '../shared';\n\nconst log = debug('efp:loader:makeOfflineBundle');\n\nexport async function* makeOfflineBundle(\n manifest: unknown\n): AsyncGenerator<{ path: string; data: ArrayBuffer }> {\n log('Bundling', manifest);\n deepFreeze(manifest);\n const offlineData = await makeOffline(manifest);\n const preResolvedRefs = new Map<string, any>();\n\n for await (const file of offlineData.files) {\n if ('data' in file) {\n preResolvedRefs.set(file.targetFilePath, file.data);\n const jsonString = JSON.stringify(file.data, null, 2);\n log('Bundling file with data', file.targetFilePath, jsonString);\n yield {\n path: file.targetFilePath,\n data: new TextEncoder().encode(jsonString).buffer,\n };\n } else if ('url' in file) {\n const blob = await downloadFile(file.url);\n log('Bundling file from url', file.targetFilePath);\n yield {\n path: file.targetFilePath,\n data: await blob.arrayBuffer(),\n };\n }\n }\n // yield* generateJsLoaderFiles();\n const html = await getIndexHtml(offlineData.manifest, preResolvedRefs);\n yield {\n path: './index.html',\n data: new TextEncoder().encode(html).buffer,\n };\n}\n\nconst MAX_CONCURRENT_DOWNLOADS = 10;\nconst queue = new Set<Promise<Blob>>();\n// have a queue to limit concurrent downloads\nasync function downloadFile(url: string): Promise<Blob> {\n while (queue.size >= MAX_CONCURRENT_DOWNLOADS) {\n await Promise.race(queue);\n }\n const downloadPromise = (async () => {\n log('Fetching file for zip:', url);\n const response = await fetch(url);\n if (!response.ok) {\n // Rodion's bug. May be missing file.\n if (!url.includes('/data/fp.svg.ViewBox.js')) {\n // throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n }\n console.warn(`Warning: Failed to fetch ${url}: ${response.status}`);\n }\n return await response.blob();\n })();\n queue.add(downloadPromise);\n try {\n return await downloadPromise;\n } finally {\n queue.delete(downloadPromise);\n }\n}\n\nasync function getIndexHtml(manifest: unknown, preResolvedRefs: Map<string, any>): Promise<string> {\n const entryPoint = await resolve(manifest, '/runtime/entry', { preResolvedRefs });\n const html = `\n<!DOCTYPE html>\n<script type=\"module\">\n import { load } from ${JSON.stringify(entryPoint)};\n await load(${JSON.stringify(manifest)});\n console.info('🚀 loaded');\n</script> \n`;\n return html;\n}\n"],"names":["log","debug","makeOfflineBundle","manifest","deepFreeze","offlineData","makeOffline","preResolvedRefs","file","jsonString","blob","downloadFile","html","getIndexHtml","MAX_CONCURRENT_DOWNLOADS","queue","url","downloadPromise","response","entryPoint","resolve"],"mappings":";;AAKA,MAAMA,IAAMC,EAAM,8BAA8B;AAEhD,gBAAuBC,EACrBC,GACqD;AACrD,EAAAH,EAAI,YAAYG,CAAQ,GACxBC,EAAWD,CAAQ;AACnB,QAAME,IAAc,MAAMC,EAAYH,CAAQ,GACxCI,wBAAsB,IAAA;AAE5B,mBAAiBC,KAAQH,EAAY;AACnC,QAAI,UAAUG,GAAM;AAClB,MAAAD,EAAgB,IAAIC,EAAK,gBAAgBA,EAAK,IAAI;AAClD,YAAMC,IAAa,KAAK,UAAUD,EAAK,MAAM,MAAM,CAAC;AACpD,MAAAR,EAAI,2BAA2BQ,EAAK,gBAAgBC,CAAU,GAC9D,MAAM;AAAA,QACJ,MAAMD,EAAK;AAAA,QACX,MAAM,IAAI,YAAA,EAAc,OAAOC,CAAU,EAAE;AAAA,MAAA;AAAA,IAE/C,WAAW,SAASD,GAAM;AACxB,YAAME,IAAO,MAAMC,EAAaH,EAAK,GAAG;AACxC,MAAAR,EAAI,0BAA0BQ,EAAK,cAAc,GACjD,MAAM;AAAA,QACJ,MAAMA,EAAK;AAAA,QACX,MAAM,MAAME,EAAK,YAAA;AAAA,MAAY;AAAA,IAEjC;AAGF,QAAME,IAAO,MAAMC,EAAaR,EAAY,UAAUE,CAAe;AACrE,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM,IAAI,YAAA,EAAc,OAAOK,CAAI,EAAE;AAAA,EAAA;AAEzC;AAEA,MAAME,IAA2B,IAC3BC,wBAAY,IAAA;AAElB,eAAeJ,EAAaK,GAA4B;AACtD,SAAOD,EAAM,QAAQD;AACnB,UAAM,QAAQ,KAAKC,CAAK;AAE1B,QAAME,KAAmB,YAAY;AACnC,IAAAjB,EAAI,0BAA0BgB,CAAG;AACjC,UAAME,IAAW,MAAM,MAAMF,CAAG;AAChC,WAAKE,EAAS,OAEPF,EAAI,SAAS,yBAAyB,GAG3C,QAAQ,KAAK,4BAA4BA,CAAG,KAAKE,EAAS,MAAM,EAAE,IAE7D,MAAMA,EAAS,KAAA;AAAA,EACxB,GAAA;AACA,EAAAH,EAAM,IAAIE,CAAe;AACzB,MAAI;AACF,WAAO,MAAMA;AAAA,EACf,UAAA;AACE,IAAAF,EAAM,OAAOE,CAAe;AAAA,EAC9B;AACF;AAEA,eAAeJ,EAAaV,GAAmBI,GAAoD;AACjG,QAAMY,IAAa,MAAMC,EAAQjB,GAAU,kBAAkB,EAAE,iBAAAI,GAAiB;AAShF,SARa;AAAA;AAAA;AAAA,yBAGU,KAAK,UAAUY,CAAU,CAAC;AAAA,eACpC,KAAK,UAAUhB,CAAQ,CAAC;AAAA;AAAA;AAAA;AAKvC;"}
@@ -45,7 +45,11 @@ async function downloadFile(url) {
45
45
  log('Fetching file for zip:', url);
46
46
  const response = await fetch(url);
47
47
  if (!response.ok) {
48
- throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
48
+ // Rodion's bug. May be missing file.
49
+ if (!url.includes('/data/fp.svg.ViewBox.js')) {
50
+ // throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
51
+ }
52
+ console.warn(`Warning: Failed to fetch ${url}: ${response.status}`);
49
53
  }
50
54
  return await response.blob();
51
55
  })();
@@ -1,5 +1,7 @@
1
+ import debug from 'debug';
1
2
  import { hashString } from './hashString';
2
3
  import { slugifyFsUnique } from './slugify';
4
+ const log = debug('efp:loader:offline');
3
5
  export function makeUniqueJsonTargetPathFromString(str, namespace = '') {
4
6
  // const hash = hashString(str);
5
7
  let result = slugifyFsUnique(str); // + '-' + hash;
@@ -40,14 +42,12 @@ export function makeTargetPathFromUrl(url, prefix = '') {
40
42
  const invalidPathnameChars = pathnameWithoutExtension.match(/[^a-zA-Z0-9\-._\/]/g);
41
43
  if (invalidPathnameChars) {
42
44
  const fixedPathnameWithoutExtension = slugifyFsUnique(pathnameWithoutExtension);
43
- console.warn(`Warning: pathname contains invalid filesystem characters (${[
44
- ...new Set(invalidPathnameChars),
45
- ].join(', ')}), slugifying it: ${pathnameWithoutExtension}${extension} => ${fixedPathnameWithoutExtension}${extension}`);
45
+ log(`Pathname contains invalid filesystem characters (${[...new Set(invalidPathnameChars)].join(', ')}), slugifying it: ${pathnameWithoutExtension}${extension} => ${fixedPathnameWithoutExtension}${extension}`);
46
46
  pathnameWithoutExtension = fixedPathnameWithoutExtension;
47
47
  }
48
48
  pathname = pathnameWithoutExtension + extension;
49
49
  if (pathname.length > 120) {
50
- console.warn(`Warning: pathname is too long (${pathname.length} characters), truncating to 150 characters: ${pathname}`);
50
+ log(`Pathname is too long (${pathname.length} characters), truncating to 150 characters: ${pathname}`);
51
51
  pathname = pathname.substring(0, 120 - extension.length) + extension;
52
52
  }
53
53
  if (search) {
@@ -88,6 +88,16 @@ function populateDataJsAssetsMap(dataUrlBase, data) {
88
88
  addLink(data.logo);
89
89
  data.exhibitors?.forEach((e) => {
90
90
  addLink(e.logo);
91
+ // add same files but with __small and __tiny suffixes
92
+ if (e.logo) {
93
+ const dotIndex = e.logo.lastIndexOf('.');
94
+ if (dotIndex !== -1) {
95
+ const name = e.logo.substring(0, dotIndex);
96
+ const ext = e.logo.substring(dotIndex);
97
+ addLink(`${name}__small${ext}`);
98
+ addLink(`${name}__tiny${ext}`);
99
+ }
100
+ }
91
101
  e.gallery?.forEach((img) => addLink(img));
92
102
  });
93
103
  data.events?.forEach((e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/loader",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "description": "ExpoFP JavaScript loader library",
5
5
  "license": "MIT",
6
6
  "homepage": "https://expofp.com",
@@ -29,7 +29,8 @@
29
29
  "build": "pnpm clean && tsc && vite build",
30
30
  "preview": "vite preview",
31
31
  "offline:build": "tsx ./scripts/buildOffline.ts",
32
- "offline:serve": "http-server ./tmp/offline"
32
+ "offline:serve": "http-server ./tmp/offline",
33
+ "prepare": "husky"
33
34
  },
34
35
  "dependencies": {
35
36
  "debug": "^4.4.3",
@@ -40,6 +41,7 @@
40
41
  "@types/node": "^24.10.0",
41
42
  "@types/unzipper": "^0.10.11",
42
43
  "http-server": "^14.1.1",
44
+ "husky": "^9.1.7",
43
45
  "tsx": "^4.21.0",
44
46
  "typescript": "~5.9.3",
45
47
  "unzipper": "^0.12.3",
@@ -1 +0,0 @@
1
- {"version":3,"file":"makeOffline-Doxc2dX7.js","sources":["../../src/offline/hashString.ts","../../src/offline/slugify.ts","../../src/offline/tools.ts","../../src/offline/makeOffline.ts"],"sourcesContent":["// 32-bit murmur-ish hash with configurable seed\nfunction murmur32WithSeed(str: string, seed: number): string {\n let h = seed >>> 0;\n\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193); // FNV-ish prime, good mixer\n }\n\n return (h >>> 0).toString(16).padStart(8, '0'); // 8 hex chars\n}\n\n// 128-bit (MD5-width) hash: 4 × 32-bit parts concatenated\nexport function hashString(str: string): string {\n return (\n murmur32WithSeed(str, 0x811c9dc5) + // your original seed\n murmur32WithSeed(str, 0x21f0aaad) +\n murmur32WithSeed(str, 0x1b873593) +\n murmur32WithSeed(str, 0x85ebca6b)\n );\n}\n","// Module-level caches\nconst inputToSlug = new Map<string, string>();\nconst slugToInput = new Map<string, string>();\n\nconst WINDOWS_RESERVED = new Set([\n \"con\", \"prn\", \"aux\", \"nul\",\n \"com1\", \"com2\", \"com3\", \"com4\", \"com5\", \"com6\", \"com7\", \"com8\", \"com9\",\n \"lpt1\", \"lpt2\", \"lpt3\", \"lpt4\", \"lpt5\", \"lpt6\", \"lpt7\", \"lpt8\", \"lpt9\",\n]);\n\nfunction makeBaseSlug(input: string): string {\n let slug = input\n .normalize(\"NFKD\")\n // All non letters/numbers → \"-\"\n .replace(/[^\\p{Letter}\\p{Number}]+/gu, \"-\")\n // Collapse multiple \"-\"\n .replace(/-+/g, \"-\")\n // Trim \"-\" from start/end\n .replace(/^-|-$/g, \"\")\n .toLowerCase();\n\n // Strip forbidden Windows characters just in case\n slug = slug.replace(/[<>:\"/\\\\|?*]/g, \"\");\n\n // Windows forbids trailing space/period\n slug = slug.replace(/[. ]+$/g, \"\");\n\n // Fallback if everything was stripped\n if (!slug) slug = \"file\";\n\n // Avoid bare reserved device names\n if (WINDOWS_RESERVED.has(slug)) {\n slug += \"-file\";\n }\n\n return slug;\n}\n\nexport function slugifyFsUnique(input: string): string {\n // If we've seen this exact input before, return the same slug\n const existing = inputToSlug.get(input);\n if (existing) return existing;\n\n const base = makeBaseSlug(input);\n let candidate = base;\n let counter = 2;\n\n while (true) {\n const existingInput = slugToInput.get(candidate);\n\n if (!existingInput) {\n // Free slug → claim it for this input\n slugToInput.set(candidate, input);\n inputToSlug.set(input, candidate);\n return candidate;\n }\n\n if (existingInput === input) {\n // Same input somehow (super defensive)\n inputToSlug.set(input, candidate);\n return candidate;\n }\n\n // Collision: same slug already used by different input → add suffix\n candidate = `${base}-${counter++}`;\n }\n}\n\n// // Optional: to reset between runs/tests\n// export function resetSlugCache() {\n// inputToSlug.clear();\n// slugToInput.clear();\n// }","import { hashString } from './hashString';\nimport { slugifyFsUnique } from './slugify';\n\nexport function makeUniqueJsonTargetPathFromString(str: string, namespace: string = ''): string {\n // const hash = hashString(str);\n let result = slugifyFsUnique(str); // + '-' + hash;\n if (namespace) {\n result = `${slugifyFsUnique(namespace)}$${result}`;\n }\n\n if (result.endsWith('/')) {\n result += 'index.json';\n } else if (!result.endsWith('.json')) {\n result += '.json';\n }\n return './' + result;\n // handle directory case\n}\n\nexport function makeTargetPathFromUrl(url: string, prefix: string = ''): string {\n // https://example.com/dir1/dir2/a.js => \"{prefix}{origin-slug}/dir1/dir2/a.js\";\n // https://example.com/dir1/dir2/a.js?params => \"{prefix}{origin-slug}/dir1/dir2/a{paramsmd5hash}.js\";\n // use slugify.ts\n\n try {\n new URL(url);\n } catch {\n debugger;\n }\n const urlObj = new URL(url);\n const origin = `${urlObj.protocol}//${urlObj.host}`;\n const originSlug = slugifyFsUnique(origin);\n\n let pathname = urlObj.pathname;\n let search = urlObj.search;\n\n // if path doesn't end with extension, throw\n if (!pathname.match(/\\.[^\\/]+$/)) {\n throw new Error(`Cannot make target path from URL without file extension: ${url}`);\n }\n\n const extension = pathname.substring(pathname.lastIndexOf('.'));\n let pathnameWithoutExtension = pathname.substring(0, pathname.lastIndexOf('.'));\n\n // check the pathname contains only valid fs characters\n const invalidPathnameChars = pathnameWithoutExtension.match(/[^a-zA-Z0-9\\-._\\/]/g);\n if (invalidPathnameChars) {\n const fixedPathnameWithoutExtension = slugifyFsUnique(pathnameWithoutExtension);\n console.warn(\n `Warning: pathname contains invalid filesystem characters (${[\n ...new Set(invalidPathnameChars),\n ].join(\n ', '\n )}), slugifying it: ${pathnameWithoutExtension}${extension} => ${fixedPathnameWithoutExtension}${extension}`\n );\n pathnameWithoutExtension = fixedPathnameWithoutExtension;\n }\n\n pathname = pathnameWithoutExtension + extension;\n\n if (pathname.length > 120) {\n console.warn(\n `Warning: pathname is too long (${pathname.length} characters), truncating to 150 characters: ${pathname}`\n );\n pathname = pathname.substring(0, 120 - extension.length) + extension;\n }\n\n if (search) {\n // create a hash from search params\n const hash = hashString(search);\n const dotIndex = pathname.lastIndexOf('.');\n if (dotIndex !== -1) {\n pathname = `${pathname.slice(0, dotIndex)}.${hash}${pathname.slice(dotIndex)}`;\n } else {\n pathname = `${pathname}${hash}`;\n }\n }\n\n // // handle directory case\n // if (pathname.endsWith('/')) {\n // pathname += '__index.json';\n // }\n\n return `./${prefix}${originSlug}${pathname}`;\n}\n","import debug from 'debug';\nimport {\n canResolve,\n parseRefValue,\n resolverResolve,\n type ResolveContextInternal,\n} from '../resolve';\nimport { resolvers } from '../resolvers';\nimport { createMergedObjectWithOverridenNonRefProps, deepClone } from '../shared';\nimport type { LocalFile, MakeOfflineResult, ManifestData, Resolver } from '../types';\nimport { makeTargetPathFromUrl, makeUniqueJsonTargetPathFromString } from './tools';\n\nconst log = debug('efp:loader:makeOffline');\n\nexport async function makeOffline(manifest: any): Promise<MakeOfflineResult> {\n log('makeOffline', manifest);\n // if (typeof manifest !== 'object' || manifest === null) {\n // throw new Error('Manifest must be an object');\n // }\n\n const res = await makeOfflineInternal(manifest);\n let done = false;\n let resultManifest: any;\n async function* files() {\n resultManifest = yield* res;\n done = true;\n }\n\n return {\n get manifest(): ManifestData {\n if (!done) throw new Error('Iterate over files before getting manifest');\n return resultManifest;\n },\n files: files() as AsyncGenerator<LocalFile, void, void>,\n };\n}\n\nasync function* makeOfflineInternal(manifest: any): AsyncGenerator<LocalFile, ManifestData, void> {\n log('makeOfflineInternal', manifest);\n const resolveContext: ResolveContextInternal = {\n refCache: new Map<string, Promise<any>>(),\n forceFetch: true,\n signal: null,\n };\n const parent = { manifest };\n yield* walk(parent, 'manifest');\n return parent.manifest;\n\n async function* walk(node: any, key: string | number): AsyncGenerator<LocalFile> {\n // console.log('walk', node, key, node[key]);\n // let node[key] = node[key];\n if (typeof node[key] !== 'object' || node[key] === null) {\n return;\n }\n // let resolversToUse1 = resolvers.filter((r) => r.canResolve(node[key].$ref));\n // const usedResolvers = new Set<Resolver>();\n // do {\n if ('$ref' in node[key]) {\n const resolversToUse = resolvers.filter((r) => canResolve(r, node[key].$ref));\n if (resolversToUse.length === 0) {\n throw new Error(`No resolver found for ref: ${node[key].$ref}`);\n }\n if (resolversToUse.length > 1) {\n throw new Error(`Multiple resolvers can make offline ref: ${node[key].$ref}`);\n }\n\n const resolver = resolversToUse[0];\n\n let func: typeof offlineLocalizeRef;\n switch (resolver.offlineMethod) {\n case 'localizeRef':\n func = offlineLocalizeRef;\n break;\n case 'resolveRef':\n func = offlineResolveRef;\n break;\n default:\n throw new Error(`Unknown offlineMethod: ${resolver.offlineMethod}`);\n }\n\n const mergeRef = yield* func(resolver, node[key].$ref, resolveContext);\n\n if (Object.isFrozen(node)) throw new Error('Unexpected frozen node during makeOffline');\n\n node[key] = createMergedObjectWithOverridenNonRefProps({ $ref: mergeRef }, node[key]);\n }\n\n // recurse\n if (Array.isArray(node[key])) {\n for (const [index] of node[key].entries()) {\n yield* walk(node[key], index);\n }\n } else if (typeof node[key] === 'object' && node[key] !== null) {\n for (const key1 of Object.keys(node[key])) {\n // debugger;\n yield* walk(node[key], key1);\n }\n }\n }\n}\n\n// function canResolve(resolver: Resolver, ref: string): boolean {\n// if (resolver.canResolve) {\n// return resolver.canResolve(ref);\n// }\n// if (resolver.schema) {\n// return canResolveRefSchema(ref, resolver.schema);\n// }\n// throw new Error('Resolver is missing canResolve method and schema property');\n// }\n\nasync function* offlineLocalizeRef(\n resolver: Resolver,\n ref: string,\n context: ResolveContextInternal\n): AsyncGenerator<LocalFile, string, void> {\n const refData = deepClone(await resolverResolve(resolver, ref, context));\n // emit assets\n yield* makeOfflineInternal(refData);\n const url = parseRefValue(ref);\n const targetFilePath = makeTargetPathFromUrl(url);\n // TODO: handle CSS and other text files that may reference other assets\n yield { url, targetFilePath };\n const schema = ref.substring(0, ref.length - url.length - 1);\n return `${schema}:${targetFilePath}`;\n}\n\nasync function* offlineResolveRef(\n resolver: Resolver,\n ref: string,\n context: ResolveContextInternal\n): AsyncGenerator<LocalFile, string, void> {\n const refData = deepClone(await resolverResolve(resolver, ref, context));\n const targetFilePath = makeUniqueJsonTargetPathFromString(ref);\n const data = yield* makeOfflineInternal(refData);\n yield { data, targetFilePath };\n return targetFilePath;\n}\n\n// export function createMakeOfflineResult(\n// manifest: any,\n// walk: (node: any, key: string | number) => AsyncGenerator<LocalFile>\n// ): MakeOfflineResult {\n// log('createMakeOfflineResult', manifest);\n// if (typeof manifest !== 'object' || manifest === null) {\n// throw new Error('Manifest must be an object');\n// }\n// const parent = { manifest };\n// let done = false;\n// async function* files() {\n// yield* walk(parent, 'manifest');\n// done = true;\n// }\n\n// return {\n// get manifest() {\n// if (!done) {\n// throw new Error('Cannot access manifest before all files are generated');\n// }\n// return parent.manifest;\n// },\n// files: files(),\n// };\n// }\n"],"names":["murmur32WithSeed","str","seed","h","i","hashString","inputToSlug","slugToInput","WINDOWS_RESERVED","makeBaseSlug","input","slug","slugifyFsUnique","existing","base","candidate","counter","existingInput","makeUniqueJsonTargetPathFromString","namespace","result","makeTargetPathFromUrl","url","prefix","urlObj","origin","originSlug","pathname","search","extension","pathnameWithoutExtension","invalidPathnameChars","fixedPathnameWithoutExtension","hash","dotIndex","log","debug","makeOffline","manifest","res","makeOfflineInternal","done","resultManifest","files","resolveContext","parent","walk","node","key","resolversToUse","resolvers","r","canResolve","resolver","func","offlineLocalizeRef","offlineResolveRef","mergeRef","createMergedObjectWithOverridenNonRefProps","index","key1","ref","context","refData","deepClone","resolverResolve","parseRefValue","targetFilePath"],"mappings":";AACA,SAASA,EAAiBC,GAAaC,GAAsB;AAC3D,MAAIC,IAAID,MAAS;AAEjB,WAASE,IAAI,GAAGA,IAAIH,EAAI,QAAQG;AAC9B,IAAAD,KAAKF,EAAI,WAAWG,CAAC,GACrBD,IAAI,KAAK,KAAKA,GAAG,QAAU;AAG7B,UAAQA,MAAM,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC/C;AAGO,SAASE,EAAWJ,GAAqB;AAC9C,SACED,EAAiBC,GAAK,UAAU;AAAA,EAChCD,EAAiBC,GAAK,SAAU,IAChCD,EAAiBC,GAAK,SAAU,IAChCD,EAAiBC,GAAK,UAAU;AAEpC;ACnBA,MAAMK,wBAAkB,IAAA,GAClBC,wBAAkB,IAAA,GAElBC,wBAAuB,IAAI;AAAA,EAC/B;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EACrB;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAChE;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAClE,CAAC;AAED,SAASC,EAAaC,GAAuB;AAC3C,MAAIC,IAAOD,EACR,UAAU,MAAM,EAEhB,QAAQ,8BAA8B,GAAG,EAEzC,QAAQ,OAAO,GAAG,EAElB,QAAQ,UAAU,EAAE,EACpB,YAAA;AAGH,SAAAC,IAAOA,EAAK,QAAQ,iBAAiB,EAAE,GAGvCA,IAAOA,EAAK,QAAQ,WAAW,EAAE,GAG5BA,MAAMA,IAAO,SAGdH,EAAiB,IAAIG,CAAI,MAC3BA,KAAQ,UAGHA;AACT;AAEO,SAASC,EAAgBF,GAAuB;AAErD,QAAMG,IAAWP,EAAY,IAAII,CAAK;AACtC,MAAIG,EAAU,QAAOA;AAErB,QAAMC,IAAOL,EAAaC,CAAK;AAC/B,MAAIK,IAAYD,GACZE,IAAU;AAEd,aAAa;AACX,UAAMC,IAAgBV,EAAY,IAAIQ,CAAS;AAE/C,QAAI,CAACE;AAEH,aAAAV,EAAY,IAAIQ,GAAWL,CAAK,GAChCJ,EAAY,IAAII,GAAOK,CAAS,GACzBA;AAGT,QAAIE,MAAkBP;AAEpB,aAAAJ,EAAY,IAAII,GAAOK,CAAS,GACzBA;AAIT,IAAAA,IAAY,GAAGD,CAAI,IAAIE,GAAS;AAAA,EAClC;AACF;AC/DO,SAASE,EAAmCjB,GAAakB,IAAoB,IAAY;AAE9F,MAAIC,IAASR,EAAgBX,CAAG;AAChC,SAAIkB,MACFC,IAAS,GAAGR,EAAgBO,CAAS,CAAC,IAAIC,CAAM,KAG9CA,EAAO,SAAS,GAAG,IACrBA,KAAU,eACAA,EAAO,SAAS,OAAO,MACjCA,KAAU,UAEL,OAAOA;AAEhB;AAEO,SAASC,EAAsBC,GAAaC,IAAiB,IAAY;AAK9E,MAAI;AACF,QAAI,IAAID,CAAG;AAAA,EACb,QAAQ;AACN;AAAA,EACF;AACA,QAAME,IAAS,IAAI,IAAIF,CAAG,GACpBG,IAAS,GAAGD,EAAO,QAAQ,KAAKA,EAAO,IAAI,IAC3CE,IAAad,EAAgBa,CAAM;AAEzC,MAAIE,IAAWH,EAAO,UAClBI,IAASJ,EAAO;AAGpB,MAAI,CAACG,EAAS,MAAM,WAAW;AAC7B,UAAM,IAAI,MAAM,4DAA4DL,CAAG,EAAE;AAGnF,QAAMO,IAAYF,EAAS,UAAUA,EAAS,YAAY,GAAG,CAAC;AAC9D,MAAIG,IAA2BH,EAAS,UAAU,GAAGA,EAAS,YAAY,GAAG,CAAC;AAG9E,QAAMI,IAAuBD,EAAyB,MAAM,qBAAqB;AACjF,MAAIC,GAAsB;AACxB,UAAMC,IAAgCpB,EAAgBkB,CAAwB;AAC9E,YAAQ;AAAA,MACN,6DAA6D;AAAA,QAC3D,GAAG,IAAI,IAAIC,CAAoB;AAAA,MAAA,EAC/B;AAAA,QACA;AAAA,MAAA,CACD,qBAAqBD,CAAwB,GAAGD,CAAS,OAAOG,CAA6B,GAAGH,CAAS;AAAA,IAAA,GAE5GC,IAA2BE;AAAA,EAC7B;AAWA,MATAL,IAAWG,IAA2BD,GAElCF,EAAS,SAAS,QACpB,QAAQ;AAAA,IACN,kCAAkCA,EAAS,MAAM,+CAA+CA,CAAQ;AAAA,EAAA,GAE1GA,IAAWA,EAAS,UAAU,GAAG,MAAME,EAAU,MAAM,IAAIA,IAGzDD,GAAQ;AAEV,UAAMK,IAAO5B,EAAWuB,CAAM,GACxBM,IAAWP,EAAS,YAAY,GAAG;AACzC,IAAIO,MAAa,KACfP,IAAW,GAAGA,EAAS,MAAM,GAAGO,CAAQ,CAAC,IAAID,CAAI,GAAGN,EAAS,MAAMO,CAAQ,CAAC,KAE5EP,IAAW,GAAGA,CAAQ,GAAGM,CAAI;AAAA,EAEjC;AAOA,SAAO,KAAKV,CAAM,GAAGG,CAAU,GAAGC,CAAQ;AAC5C;ACxEA,MAAMQ,IAAMC,EAAM,wBAAwB;AAE1C,eAAsBC,EAAYC,GAA2C;AAC3E,EAAAH,EAAI,eAAeG,CAAQ;AAK3B,QAAMC,IAAM,MAAMC,EAAoBF,CAAQ;AAC9C,MAAIG,IAAO,IACPC;AACJ,kBAAgBC,IAAQ;AACtB,IAAAD,IAAiB,OAAOH,GACxBE,IAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,IAAI,WAAyB;AAC3B,UAAI,CAACA,EAAM,OAAM,IAAI,MAAM,4CAA4C;AACvE,aAAOC;AAAA,IACT;AAAA,IACA,OAAOC,EAAA;AAAA,EAAM;AAEjB;AAEA,gBAAgBH,EAAoBF,GAA8D;AAChG,EAAAH,EAAI,uBAAuBG,CAAQ;AACnC,QAAMM,IAAyC;AAAA,IAC7C,8BAAc,IAAA;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,EAAA,GAEJC,IAAS,EAAE,UAAAP,EAAA;AACjB,gBAAOQ,EAAKD,GAAQ,UAAU,GACvBA,EAAO;AAEd,kBAAgBC,EAAKC,GAAWC,GAAiD;AAG/E,QAAI,SAAOD,EAAKC,CAAG,KAAM,YAAYD,EAAKC,CAAG,MAAM,OAMnD;AAAA,UAAI,UAAUD,EAAKC,CAAG,GAAG;AACvB,cAAMC,IAAiBC,EAAU,OAAO,CAACC,MAAMC,EAAWD,GAAGJ,EAAKC,CAAG,EAAE,IAAI,CAAC;AAC5E,YAAIC,EAAe,WAAW;AAC5B,gBAAM,IAAI,MAAM,8BAA8BF,EAAKC,CAAG,EAAE,IAAI,EAAE;AAEhE,YAAIC,EAAe,SAAS;AAC1B,gBAAM,IAAI,MAAM,4CAA4CF,EAAKC,CAAG,EAAE,IAAI,EAAE;AAG9E,cAAMK,IAAWJ,EAAe,CAAC;AAEjC,YAAIK;AACJ,gBAAQD,EAAS,eAAA;AAAA,UACf,KAAK;AACH,YAAAC,IAAOC;AACP;AAAA,UACF,KAAK;AACH,YAAAD,IAAOE;AACP;AAAA,UACF;AACE,kBAAM,IAAI,MAAM,0BAA0BH,EAAS,aAAa,EAAE;AAAA,QAAA;AAGtE,cAAMI,IAAW,OAAOH,EAAKD,GAAUN,EAAKC,CAAG,EAAE,MAAMJ,CAAc;AAErE,YAAI,OAAO,SAASG,CAAI,EAAG,OAAM,IAAI,MAAM,2CAA2C;AAEtF,QAAAA,EAAKC,CAAG,IAAIU,EAA2C,EAAE,MAAMD,EAAA,GAAYV,EAAKC,CAAG,CAAC;AAAA,MACtF;AAGA,UAAI,MAAM,QAAQD,EAAKC,CAAG,CAAC;AACzB,mBAAW,CAACW,CAAK,KAAKZ,EAAKC,CAAG,EAAE;AAC9B,iBAAOF,EAAKC,EAAKC,CAAG,GAAGW,CAAK;AAAA,eAErB,OAAOZ,EAAKC,CAAG,KAAM,YAAYD,EAAKC,CAAG,MAAM;AACxD,mBAAWY,KAAQ,OAAO,KAAKb,EAAKC,CAAG,CAAC;AAEtC,iBAAOF,EAAKC,EAAKC,CAAG,GAAGY,CAAI;AAAA;AAAA,EAGjC;AACF;AAYA,gBAAgBL,EACdF,GACAQ,GACAC,GACyC;AACzC,QAAMC,IAAUC,EAAU,MAAMC,EAAgBZ,GAAUQ,GAAKC,CAAO,CAAC;AAEvE,SAAOtB,EAAoBuB,CAAO;AAClC,QAAMzC,IAAM4C,EAAcL,CAAG,GACvBM,IAAiB9C,EAAsBC,CAAG;AAEhD,eAAM,EAAE,KAAAA,GAAK,gBAAA6C,EAAA,GAEN,GADQN,EAAI,UAAU,GAAGA,EAAI,SAASvC,EAAI,SAAS,CAAC,CAC3C,IAAI6C,CAAc;AACpC;AAEA,gBAAgBX,EACdH,GACAQ,GACAC,GACyC;AACzC,QAAMC,IAAUC,EAAU,MAAMC,EAAgBZ,GAAUQ,GAAKC,CAAO,CAAC,GACjEK,IAAiBjD,EAAmC2C,CAAG;AAE7D,eAAM,EAAE,MADK,OAAOrB,EAAoBuB,CAAO,GACjC,gBAAAI,EAAA,GACPA;AACT;"}
@@ -1,60 +0,0 @@
1
- import { d, a as f, resolve as s } from "./bundle.js";
2
- import { makeOffline as c } from "./makeOffline-Doxc2dX7.js";
3
- const l = d("efp:loader:makeOfflineBundle");
4
- async function* p(t) {
5
- l("Bundling", t), f(t);
6
- const n = await c(t), a = /* @__PURE__ */ new Map();
7
- for await (const e of n.files)
8
- if ("data" in e) {
9
- a.set(e.targetFilePath, e.data);
10
- const i = JSON.stringify(e.data, null, 2);
11
- l("Bundling file with data", e.targetFilePath, i), yield {
12
- path: e.targetFilePath,
13
- data: new TextEncoder().encode(i).buffer
14
- };
15
- } else if ("url" in e) {
16
- const i = await w(e.url);
17
- l("Bundling file from url", e.targetFilePath), yield {
18
- path: e.targetFilePath,
19
- data: await i.arrayBuffer()
20
- };
21
- }
22
- const r = await h(n.manifest, a);
23
- yield {
24
- path: "./index.html",
25
- data: new TextEncoder().encode(r).buffer
26
- };
27
- }
28
- const u = 10, o = /* @__PURE__ */ new Set();
29
- async function w(t) {
30
- for (; o.size >= u; )
31
- await Promise.race(o);
32
- const n = (async () => {
33
- l("Fetching file for zip:", t);
34
- const a = await fetch(t);
35
- if (!a.ok)
36
- throw new Error(`Failed to fetch ${t}: ${a.status} ${a.statusText}`);
37
- return await a.blob();
38
- })();
39
- o.add(n);
40
- try {
41
- return await n;
42
- } finally {
43
- o.delete(n);
44
- }
45
- }
46
- async function h(t, n) {
47
- const a = await s(t, "/runtime/entry", { preResolvedRefs: n });
48
- return `
49
- <!DOCTYPE html>
50
- <script type="module">
51
- import { load } from ${JSON.stringify(a)};
52
- await load(${JSON.stringify(t)});
53
- console.info('🚀 loaded');
54
- <\/script>
55
- `;
56
- }
57
- export {
58
- p as makeOfflineBundle
59
- };
60
- //# sourceMappingURL=makeOfflineBundle-BoEPc05D.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"makeOfflineBundle-BoEPc05D.js","sources":["../../src/offline/makeOfflineBundle.ts"],"sourcesContent":["import debug from 'debug';\nimport { resolve } from '..';\nimport { makeOffline } from './makeOffline';\nimport { deepFreeze } from '../shared';\n\nconst log = debug('efp:loader:makeOfflineBundle');\n\nexport async function* makeOfflineBundle(\n manifest: unknown\n): AsyncGenerator<{ path: string; data: ArrayBuffer }> {\n log('Bundling', manifest);\n deepFreeze(manifest);\n const offlineData = await makeOffline(manifest);\n const preResolvedRefs = new Map<string, any>();\n\n for await (const file of offlineData.files) {\n if ('data' in file) {\n preResolvedRefs.set(file.targetFilePath, file.data);\n const jsonString = JSON.stringify(file.data, null, 2);\n log('Bundling file with data', file.targetFilePath, jsonString);\n yield {\n path: file.targetFilePath,\n data: new TextEncoder().encode(jsonString).buffer,\n };\n } else if ('url' in file) {\n const blob = await downloadFile(file.url);\n log('Bundling file from url', file.targetFilePath);\n yield {\n path: file.targetFilePath,\n data: await blob.arrayBuffer(),\n };\n }\n }\n // yield* generateJsLoaderFiles();\n const html = await getIndexHtml(offlineData.manifest, preResolvedRefs);\n yield {\n path: './index.html',\n data: new TextEncoder().encode(html).buffer,\n };\n}\n\nconst MAX_CONCURRENT_DOWNLOADS = 10;\nconst queue = new Set<Promise<Blob>>();\n// have a queue to limit concurrent downloads\nasync function downloadFile(url: string): Promise<Blob> {\n while (queue.size >= MAX_CONCURRENT_DOWNLOADS) {\n await Promise.race(queue);\n }\n const downloadPromise = (async () => {\n log('Fetching file for zip:', url);\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n }\n return await response.blob();\n })();\n queue.add(downloadPromise);\n try {\n return await downloadPromise;\n } finally {\n queue.delete(downloadPromise);\n }\n}\n\nasync function getIndexHtml(manifest: unknown, preResolvedRefs: Map<string, any>): Promise<string> {\n const entryPoint = await resolve(manifest, '/runtime/entry', { preResolvedRefs });\n const html = `\n<!DOCTYPE html>\n<script type=\"module\">\n import { load } from ${JSON.stringify(entryPoint)};\n await load(${JSON.stringify(manifest)});\n console.info('🚀 loaded');\n</script> \n`;\n return html;\n}\n"],"names":["log","debug","makeOfflineBundle","manifest","deepFreeze","offlineData","makeOffline","preResolvedRefs","file","jsonString","blob","downloadFile","html","getIndexHtml","MAX_CONCURRENT_DOWNLOADS","queue","url","downloadPromise","response","entryPoint","resolve"],"mappings":";;AAKA,MAAMA,IAAMC,EAAM,8BAA8B;AAEhD,gBAAuBC,EACrBC,GACqD;AACrD,EAAAH,EAAI,YAAYG,CAAQ,GACxBC,EAAWD,CAAQ;AACnB,QAAME,IAAc,MAAMC,EAAYH,CAAQ,GACxCI,wBAAsB,IAAA;AAE5B,mBAAiBC,KAAQH,EAAY;AACnC,QAAI,UAAUG,GAAM;AAClB,MAAAD,EAAgB,IAAIC,EAAK,gBAAgBA,EAAK,IAAI;AAClD,YAAMC,IAAa,KAAK,UAAUD,EAAK,MAAM,MAAM,CAAC;AACpD,MAAAR,EAAI,2BAA2BQ,EAAK,gBAAgBC,CAAU,GAC9D,MAAM;AAAA,QACJ,MAAMD,EAAK;AAAA,QACX,MAAM,IAAI,YAAA,EAAc,OAAOC,CAAU,EAAE;AAAA,MAAA;AAAA,IAE/C,WAAW,SAASD,GAAM;AACxB,YAAME,IAAO,MAAMC,EAAaH,EAAK,GAAG;AACxC,MAAAR,EAAI,0BAA0BQ,EAAK,cAAc,GACjD,MAAM;AAAA,QACJ,MAAMA,EAAK;AAAA,QACX,MAAM,MAAME,EAAK,YAAA;AAAA,MAAY;AAAA,IAEjC;AAGF,QAAME,IAAO,MAAMC,EAAaR,EAAY,UAAUE,CAAe;AACrE,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM,IAAI,YAAA,EAAc,OAAOK,CAAI,EAAE;AAAA,EAAA;AAEzC;AAEA,MAAME,IAA2B,IAC3BC,wBAAY,IAAA;AAElB,eAAeJ,EAAaK,GAA4B;AACtD,SAAOD,EAAM,QAAQD;AACnB,UAAM,QAAQ,KAAKC,CAAK;AAE1B,QAAME,KAAmB,YAAY;AACnC,IAAAjB,EAAI,0BAA0BgB,CAAG;AACjC,UAAME,IAAW,MAAM,MAAMF,CAAG;AAChC,QAAI,CAACE,EAAS;AACZ,YAAM,IAAI,MAAM,mBAAmBF,CAAG,KAAKE,EAAS,MAAM,IAAIA,EAAS,UAAU,EAAE;AAErF,WAAO,MAAMA,EAAS,KAAA;AAAA,EACxB,GAAA;AACA,EAAAH,EAAM,IAAIE,CAAe;AACzB,MAAI;AACF,WAAO,MAAMA;AAAA,EACf,UAAA;AACE,IAAAF,EAAM,OAAOE,CAAe;AAAA,EAC9B;AACF;AAEA,eAAeJ,EAAaV,GAAmBI,GAAoD;AACjG,QAAMY,IAAa,MAAMC,EAAQjB,GAAU,kBAAkB,EAAE,iBAAAI,GAAiB;AAShF,SARa;AAAA;AAAA;AAAA,yBAGU,KAAK,UAAUY,CAAU,CAAC;AAAA,eACpC,KAAK,UAAUhB,CAAQ,CAAC;AAAA;AAAA;AAAA;AAKvC;"}