@emkodev/emroute 1.8.2-beta.2 → 1.10.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/component/widget.component.ts +1 -1
- package/core/pipeline/pipeline.ts +11 -1
- package/core/renderer/html.renderer.ts +16 -18
- package/core/renderer/md.renderer.ts +2 -4
- package/core/renderer/ssr.renderer.ts +6 -10
- package/core/server/emroute.server.ts +9 -25
- package/core/widget/widget.registry.ts +3 -44
- package/dist/core/component/widget.component.d.ts +1 -1
- package/dist/core/component/widget.component.js +1 -1
- package/dist/core/pipeline/pipeline.d.ts +1 -0
- package/dist/core/pipeline/pipeline.js +9 -1
- package/dist/core/pipeline/pipeline.js.map +1 -1
- package/dist/core/renderer/html.renderer.js +10 -12
- package/dist/core/renderer/html.renderer.js.map +1 -1
- package/dist/core/renderer/md.renderer.js +2 -4
- package/dist/core/renderer/md.renderer.js.map +1 -1
- package/dist/core/renderer/ssr.renderer.d.ts +4 -5
- package/dist/core/renderer/ssr.renderer.js +3 -10
- package/dist/core/renderer/ssr.renderer.js.map +1 -1
- package/dist/core/server/emroute.server.d.ts +2 -2
- package/dist/core/server/emroute.server.js +7 -23
- package/dist/core/server/emroute.server.js.map +1 -1
- package/dist/core/widget/widget.registry.d.ts +3 -16
- package/dist/core/widget/widget.registry.js +3 -34
- package/dist/core/widget/widget.registry.js.map +1 -1
- package/dist/emroute.js +430 -92
- package/dist/emroute.js.map +15 -12
- package/dist/runtime/cache.runtime.d.ts +31 -0
- package/dist/runtime/cache.runtime.js +107 -0
- package/dist/runtime/cache.runtime.js.map +1 -0
- package/dist/runtime/idb.runtime.d.ts +31 -0
- package/dist/runtime/idb.runtime.js +178 -0
- package/dist/runtime/idb.runtime.js.map +1 -0
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/renderer/spa/emroute.app.js +1 -6
- package/dist/src/renderer/spa/emroute.app.js.map +1 -1
- package/dist/src/renderer/spa/mod.d.ts +4 -3
- package/dist/src/renderer/spa/mod.js +5 -3
- package/dist/src/renderer/spa/mod.js.map +1 -1
- package/dist/src/service-worker/emroute.sw.d.ts +54 -0
- package/dist/src/service-worker/emroute.sw.js +181 -0
- package/dist/src/service-worker/emroute.sw.js.map +1 -0
- package/dist/src/service-worker/mod.d.ts +8 -0
- package/dist/src/service-worker/mod.js +9 -0
- package/dist/src/service-worker/mod.js.map +1 -0
- package/package.json +16 -1
- package/runtime/cache.runtime.ts +127 -0
- package/runtime/idb.runtime.ts +203 -0
- package/src/index.ts +0 -1
- package/src/renderer/spa/emroute.app.ts +2 -6
- package/src/renderer/spa/mod.ts +6 -4
- package/src/service-worker/emroute.sw.ts +264 -0
- package/src/service-worker/mod.ts +9 -0
package/dist/emroute.js
CHANGED
|
@@ -472,47 +472,6 @@ class ComponentElement extends HTMLElementBase {
|
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
// dist/core/widget/widget.registry.js
|
|
476
|
-
class WidgetRegistry {
|
|
477
|
-
entries = new Map;
|
|
478
|
-
add(widget, modulePath) {
|
|
479
|
-
this.entries.set(widget.name, { widget, modulePath });
|
|
480
|
-
}
|
|
481
|
-
addLazy(name, modulePath) {
|
|
482
|
-
if (!this.entries.has(name)) {
|
|
483
|
-
this.entries.set(name, { modulePath });
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
get(name) {
|
|
487
|
-
return this.entries.get(name)?.widget;
|
|
488
|
-
}
|
|
489
|
-
getModulePath(name) {
|
|
490
|
-
return this.entries.get(name)?.modulePath;
|
|
491
|
-
}
|
|
492
|
-
[Symbol.iterator]() {
|
|
493
|
-
const entries = this.entries.values();
|
|
494
|
-
return function* () {
|
|
495
|
-
for (const entry of entries) {
|
|
496
|
-
if (entry.widget)
|
|
497
|
-
yield entry.widget;
|
|
498
|
-
}
|
|
499
|
-
}();
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
function extractWidgetExport(mod) {
|
|
503
|
-
for (const value of Object.values(mod)) {
|
|
504
|
-
if (!value)
|
|
505
|
-
continue;
|
|
506
|
-
if (typeof value === "object" && "getData" in value) {
|
|
507
|
-
return value;
|
|
508
|
-
}
|
|
509
|
-
if (typeof value === "function" && value.prototype?.getData) {
|
|
510
|
-
return new value;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
return null;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
475
|
// dist/core/router/route.trie.js
|
|
517
476
|
class RouteTrie {
|
|
518
477
|
tree;
|
|
@@ -735,6 +694,13 @@ class Pipeline {
|
|
|
735
694
|
}
|
|
736
695
|
return hierarchy;
|
|
737
696
|
}
|
|
697
|
+
async findWidgetModulePath(name) {
|
|
698
|
+
const response = await this.runtime.query(WIDGETS_MANIFEST_PATH);
|
|
699
|
+
if (response.status === 404)
|
|
700
|
+
return;
|
|
701
|
+
const entries = await response.json();
|
|
702
|
+
return entries.find((e) => e.name === name)?.modulePath;
|
|
703
|
+
}
|
|
738
704
|
async loadModule(modulePath) {
|
|
739
705
|
const loader = this.moduleLoaders[modulePath];
|
|
740
706
|
if (loader) {
|
|
@@ -1037,23 +1003,31 @@ class PageComponent extends Component {
|
|
|
1037
1003
|
}
|
|
1038
1004
|
var page_component_default = new PageComponent;
|
|
1039
1005
|
|
|
1006
|
+
// dist/core/widget/widget.registry.js
|
|
1007
|
+
function extractWidgetExport(mod) {
|
|
1008
|
+
for (const value of Object.values(mod)) {
|
|
1009
|
+
if (!value)
|
|
1010
|
+
continue;
|
|
1011
|
+
if (typeof value === "object" && "getData" in value) {
|
|
1012
|
+
return value;
|
|
1013
|
+
}
|
|
1014
|
+
if (typeof value === "function" && value.prototype?.getData) {
|
|
1015
|
+
return new value;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1040
1021
|
// dist/core/renderer/ssr.renderer.js
|
|
1041
1022
|
class SsrRenderer {
|
|
1042
1023
|
pipeline;
|
|
1043
|
-
widgets;
|
|
1044
1024
|
logger;
|
|
1045
|
-
constructor(pipeline,
|
|
1025
|
+
constructor(pipeline, _options = {}) {
|
|
1046
1026
|
this.pipeline = pipeline;
|
|
1047
1027
|
this.logger = pipeline.logger;
|
|
1048
|
-
this.widgets = options.widgets ?? null;
|
|
1049
1028
|
}
|
|
1050
1029
|
async resolveWidget(name) {
|
|
1051
|
-
|
|
1052
|
-
return;
|
|
1053
|
-
const widget = this.widgets.get(name);
|
|
1054
|
-
if (widget)
|
|
1055
|
-
return widget;
|
|
1056
|
-
const path = this.widgets.getModulePath(name);
|
|
1030
|
+
const path = await this.pipeline.findWidgetModulePath(name);
|
|
1057
1031
|
if (!path)
|
|
1058
1032
|
return;
|
|
1059
1033
|
try {
|
|
@@ -1227,18 +1201,16 @@ class SsrHtmlRenderer extends SsrRenderer {
|
|
|
1227
1201
|
let content = rawContent;
|
|
1228
1202
|
content = await this.expandMarkdown(content);
|
|
1229
1203
|
content = this.attributeSlots(content, route.pattern);
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
}, this.pipeline.contextProvider, this.logger);
|
|
1241
|
-
}
|
|
1204
|
+
content = await resolveWidgetTags(content, (name) => this.resolveWidget(name), routeInfo, async (name) => {
|
|
1205
|
+
const modulePath = await this.pipeline.findWidgetModulePath(name);
|
|
1206
|
+
if (modulePath) {
|
|
1207
|
+
const mod = await this.pipeline.loadModule(modulePath);
|
|
1208
|
+
const inlined = this.pipeline.getModuleFiles(mod);
|
|
1209
|
+
if (inlined)
|
|
1210
|
+
return inlined;
|
|
1211
|
+
}
|
|
1212
|
+
return {};
|
|
1213
|
+
}, this.pipeline.contextProvider, this.logger);
|
|
1242
1214
|
return { content, ...title !== undefined ? { title } : {} };
|
|
1243
1215
|
}
|
|
1244
1216
|
renderContent(component, args) {
|
|
@@ -1350,9 +1322,7 @@ class SsrMdRenderer extends SsrRenderer {
|
|
|
1350
1322
|
const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);
|
|
1351
1323
|
let content = rawContent;
|
|
1352
1324
|
content = content.replaceAll(BARE_SLOT_BLOCK, routerSlotBlock(route.pattern));
|
|
1353
|
-
|
|
1354
|
-
content = await this.resolveWidgets(content, routeInfo);
|
|
1355
|
-
}
|
|
1325
|
+
content = await this.resolveWidgets(content, routeInfo);
|
|
1356
1326
|
return { content, ...title !== undefined ? { title } : {} };
|
|
1357
1327
|
}
|
|
1358
1328
|
renderContent(component, args) {
|
|
@@ -1382,7 +1352,7 @@ Path: \`${url.pathname}\``;
|
|
|
1382
1352
|
}
|
|
1383
1353
|
try {
|
|
1384
1354
|
let files;
|
|
1385
|
-
const modulePath = this.
|
|
1355
|
+
const modulePath = await this.pipeline.findWidgetModulePath(block.widgetName);
|
|
1386
1356
|
if (modulePath) {
|
|
1387
1357
|
const mod = await this.pipeline.loadModule(modulePath);
|
|
1388
1358
|
files = this.pipeline.getModuleFiles(mod);
|
|
@@ -1467,31 +1437,13 @@ class Emroute {
|
|
|
1467
1437
|
...config.extendContext ? { contextProvider: config.extendContext } : {},
|
|
1468
1438
|
...config.moduleLoaders ? { moduleLoaders: config.moduleLoaders } : {}
|
|
1469
1439
|
});
|
|
1470
|
-
let widgets;
|
|
1471
|
-
const widgetsResponse = await runtime.query(WIDGETS_MANIFEST_PATH);
|
|
1472
|
-
if (widgetsResponse.status !== 404) {
|
|
1473
|
-
const entries = await widgetsResponse.json();
|
|
1474
|
-
widgets = new WidgetRegistry;
|
|
1475
|
-
for (const entry of entries) {
|
|
1476
|
-
widgets.addLazy(entry.name, entry.modulePath);
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
if (config.widgets) {
|
|
1480
|
-
if (!widgets)
|
|
1481
|
-
widgets = new WidgetRegistry;
|
|
1482
|
-
for (const w of config.widgets)
|
|
1483
|
-
widgets.add(w);
|
|
1484
|
-
}
|
|
1485
1440
|
let ssrHtmlRenderer = null;
|
|
1486
1441
|
let ssrMdRenderer = null;
|
|
1487
1442
|
if (spa !== "only") {
|
|
1488
1443
|
ssrHtmlRenderer = new SsrHtmlRenderer(pipeline, {
|
|
1489
|
-
...config.markdownRenderer ? { markdownRenderer: config.markdownRenderer } : {}
|
|
1490
|
-
...widgets ? { widgets } : {}
|
|
1491
|
-
});
|
|
1492
|
-
ssrMdRenderer = new SsrMdRenderer(pipeline, {
|
|
1493
|
-
...widgets ? { widgets } : {}
|
|
1444
|
+
...config.markdownRenderer ? { markdownRenderer: config.markdownRenderer } : {}
|
|
1494
1445
|
});
|
|
1446
|
+
ssrMdRenderer = new SsrMdRenderer(pipeline);
|
|
1495
1447
|
}
|
|
1496
1448
|
const title = config.title ?? "emroute";
|
|
1497
1449
|
const shellBase = spa === "root" || spa === "only" ? appBase : htmlBase;
|
|
@@ -1574,6 +1526,11 @@ class Emroute {
|
|
|
1574
1526
|
static async buildHtmlShell(runtime, title, basePath, spa) {
|
|
1575
1527
|
const baseTag = basePath ? `
|
|
1576
1528
|
<base href="${escapeHtml(basePath)}/">` : "";
|
|
1529
|
+
let manifestTag = "";
|
|
1530
|
+
if ((await runtime.query("/manifest.json")).status !== 404) {
|
|
1531
|
+
manifestTag = `
|
|
1532
|
+
<link rel="manifest" href="/manifest.json">`;
|
|
1533
|
+
}
|
|
1577
1534
|
let cssTag = "";
|
|
1578
1535
|
if ((await runtime.query("/main.css")).status !== 404) {
|
|
1579
1536
|
cssTag = `
|
|
@@ -1602,7 +1559,7 @@ ${importMap}
|
|
|
1602
1559
|
<meta charset="utf-8">
|
|
1603
1560
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1604
1561
|
<title>${escapeHtml(title)}</title>
|
|
1605
|
-
<style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>${cssTag}
|
|
1562
|
+
<style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>${manifestTag}${cssTag}
|
|
1606
1563
|
</head>
|
|
1607
1564
|
<body>
|
|
1608
1565
|
<router-slot></router-slot>${importMapHtml}${scriptHtml}
|
|
@@ -2426,9 +2383,7 @@ async function bootEmrouteApp(options) {
|
|
|
2426
2383
|
const elementsResponse = await runtime.handle(ELEMENTS_MANIFEST_PATH);
|
|
2427
2384
|
const elementEntries = elementsResponse.ok ? await elementsResponse.json() : [];
|
|
2428
2385
|
const moduleLoaders = buildLazyLoaders(routeTree, widgetEntries, elementEntries, runtime);
|
|
2429
|
-
const widgets = new WidgetRegistry;
|
|
2430
2386
|
for (const entry of widgetEntries) {
|
|
2431
|
-
widgets.addLazy(entry.name, entry.modulePath);
|
|
2432
2387
|
ComponentElement.registerLazy(entry.name, moduleLoaders[entry.modulePath]);
|
|
2433
2388
|
}
|
|
2434
2389
|
for (const entry of elementEntries) {
|
|
@@ -2450,7 +2405,6 @@ async function bootEmrouteApp(options) {
|
|
|
2450
2405
|
const mdRenderer = MarkdownElement.getConfiguredRenderer();
|
|
2451
2406
|
const server = await Emroute.create({
|
|
2452
2407
|
routeTree,
|
|
2453
|
-
widgets,
|
|
2454
2408
|
moduleLoaders,
|
|
2455
2409
|
...mdRenderer ? { markdownRenderer: mdRenderer } : {},
|
|
2456
2410
|
...options?.extendContext ? { extendContext: options.extendContext } : {}
|
|
@@ -3031,6 +2985,388 @@ function createOverlayService() {
|
|
|
3031
2985
|
dismissAll
|
|
3032
2986
|
};
|
|
3033
2987
|
}
|
|
2988
|
+
// dist/runtime/cache.runtime.js
|
|
2989
|
+
var __rewriteRelativeImportExtension2 = function(path, preserveJsx) {
|
|
2990
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
2991
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
2992
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
return path;
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
class CacheRuntime extends Runtime {
|
|
2999
|
+
cache = null;
|
|
3000
|
+
cacheName;
|
|
3001
|
+
constructor(cacheName, config = {}) {
|
|
3002
|
+
super(config);
|
|
3003
|
+
this.cacheName = cacheName;
|
|
3004
|
+
}
|
|
3005
|
+
async getCache() {
|
|
3006
|
+
this.cache ??= await caches.open(this.cacheName);
|
|
3007
|
+
return this.cache;
|
|
3008
|
+
}
|
|
3009
|
+
handle(resource, init) {
|
|
3010
|
+
const path = this.parsePath(resource);
|
|
3011
|
+
const method = init?.method ?? "GET";
|
|
3012
|
+
switch (method) {
|
|
3013
|
+
case "PUT":
|
|
3014
|
+
return this.write(path, init?.body ?? null);
|
|
3015
|
+
case "DELETE":
|
|
3016
|
+
return this.delete(path);
|
|
3017
|
+
default:
|
|
3018
|
+
return this.read(path);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
query(resource, options) {
|
|
3022
|
+
if (options?.as === "text") {
|
|
3023
|
+
return this.read(this.parsePath(resource)).then(async (r) => {
|
|
3024
|
+
if (r.status === 404)
|
|
3025
|
+
throw new Error(`Not found: ${this.parsePath(resource)}`);
|
|
3026
|
+
return r.text();
|
|
3027
|
+
});
|
|
3028
|
+
}
|
|
3029
|
+
return this.handle(resource, options);
|
|
3030
|
+
}
|
|
3031
|
+
async loadModule(path) {
|
|
3032
|
+
const response = await this.read(path);
|
|
3033
|
+
if (response.status === 404) {
|
|
3034
|
+
throw new Error(`Module not found in cache: ${path}`);
|
|
3035
|
+
}
|
|
3036
|
+
const js = await response.text();
|
|
3037
|
+
const blob = new Blob([js], { type: "application/javascript" });
|
|
3038
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
3039
|
+
try {
|
|
3040
|
+
return await import(__rewriteRelativeImportExtension2(objectUrl));
|
|
3041
|
+
} finally {
|
|
3042
|
+
URL.revokeObjectURL(objectUrl);
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
async read(path) {
|
|
3046
|
+
const cache = await this.getCache();
|
|
3047
|
+
const key = new Request(this.toFakeUrl(path));
|
|
3048
|
+
const cached = await cache.match(key);
|
|
3049
|
+
if (!cached)
|
|
3050
|
+
return new Response("Not Found", { status: 404 });
|
|
3051
|
+
return cached;
|
|
3052
|
+
}
|
|
3053
|
+
async write(path, body) {
|
|
3054
|
+
const cache = await this.getCache();
|
|
3055
|
+
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
3056
|
+
const contentType = CONTENT_TYPES.get(ext) ?? "application/octet-stream";
|
|
3057
|
+
const response = new Response(body, {
|
|
3058
|
+
status: 200,
|
|
3059
|
+
headers: { "Content-Type": contentType }
|
|
3060
|
+
});
|
|
3061
|
+
await cache.put(new Request(this.toFakeUrl(path)), response);
|
|
3062
|
+
return new Response(null, { status: 204 });
|
|
3063
|
+
}
|
|
3064
|
+
async delete(path) {
|
|
3065
|
+
const cache = await this.getCache();
|
|
3066
|
+
await cache.delete(new Request(this.toFakeUrl(path)));
|
|
3067
|
+
return new Response(null, { status: 204 });
|
|
3068
|
+
}
|
|
3069
|
+
parsePath(resource) {
|
|
3070
|
+
if (typeof resource === "string")
|
|
3071
|
+
return resource;
|
|
3072
|
+
if (resource instanceof URL)
|
|
3073
|
+
return resource.pathname;
|
|
3074
|
+
return new URL(resource.url).pathname;
|
|
3075
|
+
}
|
|
3076
|
+
toFakeUrl(path) {
|
|
3077
|
+
return `https://emroute-cache${path}`;
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3081
|
+
// dist/runtime/idb.runtime.js
|
|
3082
|
+
var __rewriteRelativeImportExtension3 = function(path, preserveJsx) {
|
|
3083
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3084
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
3085
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
3086
|
+
});
|
|
3087
|
+
}
|
|
3088
|
+
return path;
|
|
3089
|
+
};
|
|
3090
|
+
var STORE_NAME = "files";
|
|
3091
|
+
|
|
3092
|
+
class IdbRuntime extends Runtime {
|
|
3093
|
+
db = null;
|
|
3094
|
+
dbName;
|
|
3095
|
+
constructor(dbName, config = {}) {
|
|
3096
|
+
super(config);
|
|
3097
|
+
this.dbName = dbName;
|
|
3098
|
+
}
|
|
3099
|
+
open() {
|
|
3100
|
+
if (this.db)
|
|
3101
|
+
return Promise.resolve(this.db);
|
|
3102
|
+
return new Promise((resolve, reject) => {
|
|
3103
|
+
const request = indexedDB.open(this.dbName, 1);
|
|
3104
|
+
request.onupgradeneeded = () => {
|
|
3105
|
+
request.result.createObjectStore(STORE_NAME);
|
|
3106
|
+
};
|
|
3107
|
+
request.onsuccess = () => {
|
|
3108
|
+
this.db = request.result;
|
|
3109
|
+
resolve(this.db);
|
|
3110
|
+
};
|
|
3111
|
+
request.onerror = () => reject(request.error);
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
handle(resource, init) {
|
|
3115
|
+
const [pathname, method, body] = this.parse(resource, init);
|
|
3116
|
+
switch (method) {
|
|
3117
|
+
case "PUT":
|
|
3118
|
+
return this.write(pathname, body);
|
|
3119
|
+
case "DELETE":
|
|
3120
|
+
return this.delete(pathname);
|
|
3121
|
+
default:
|
|
3122
|
+
return this.read(pathname);
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
query(resource, options) {
|
|
3126
|
+
if (options?.as === "text") {
|
|
3127
|
+
const pathname = this.parsePath(resource);
|
|
3128
|
+
return this.get(pathname).then((data) => {
|
|
3129
|
+
if (!data)
|
|
3130
|
+
throw new Error(`Not found: ${pathname}`);
|
|
3131
|
+
return new TextDecoder().decode(data);
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
3134
|
+
return this.handle(resource, options);
|
|
3135
|
+
}
|
|
3136
|
+
async loadModule(path) {
|
|
3137
|
+
const data = await this.get(path);
|
|
3138
|
+
if (!data)
|
|
3139
|
+
throw new Error(`Module not found in IDB: ${path}`);
|
|
3140
|
+
const buf = data.buffer;
|
|
3141
|
+
const blob = new Blob([buf], { type: "application/javascript" });
|
|
3142
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
3143
|
+
try {
|
|
3144
|
+
return await import(__rewriteRelativeImportExtension3(objectUrl));
|
|
3145
|
+
} finally {
|
|
3146
|
+
URL.revokeObjectURL(objectUrl);
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
async read(path) {
|
|
3150
|
+
if (path.endsWith("/")) {
|
|
3151
|
+
const children = await this.listChildren(path);
|
|
3152
|
+
if (children.length === 0)
|
|
3153
|
+
return new Response("Not Found", { status: 404 });
|
|
3154
|
+
return Response.json(children);
|
|
3155
|
+
}
|
|
3156
|
+
const data = await this.get(path);
|
|
3157
|
+
if (!data) {
|
|
3158
|
+
const children = await this.listChildren(path + "/");
|
|
3159
|
+
if (children.length > 0)
|
|
3160
|
+
return Response.json(children);
|
|
3161
|
+
return new Response("Not Found", { status: 404 });
|
|
3162
|
+
}
|
|
3163
|
+
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
3164
|
+
return new Response(data.buffer, {
|
|
3165
|
+
status: 200,
|
|
3166
|
+
headers: { "Content-Type": CONTENT_TYPES.get(ext) ?? "application/octet-stream" }
|
|
3167
|
+
});
|
|
3168
|
+
}
|
|
3169
|
+
async write(path, body) {
|
|
3170
|
+
const data = body ? new Uint8Array(await new Response(body).arrayBuffer()) : new Uint8Array;
|
|
3171
|
+
await this.put(path, data);
|
|
3172
|
+
return new Response(null, { status: 204 });
|
|
3173
|
+
}
|
|
3174
|
+
async delete(path) {
|
|
3175
|
+
const db = await this.open();
|
|
3176
|
+
return new Promise((resolve, reject) => {
|
|
3177
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
3178
|
+
tx.objectStore(STORE_NAME).delete(path);
|
|
3179
|
+
tx.oncomplete = () => resolve(new Response(null, { status: 204 }));
|
|
3180
|
+
tx.onerror = () => reject(tx.error);
|
|
3181
|
+
});
|
|
3182
|
+
}
|
|
3183
|
+
async get(path) {
|
|
3184
|
+
const db = await this.open();
|
|
3185
|
+
return new Promise((resolve, reject) => {
|
|
3186
|
+
const tx = db.transaction(STORE_NAME, "readonly");
|
|
3187
|
+
const req = tx.objectStore(STORE_NAME).get(path);
|
|
3188
|
+
req.onsuccess = () => resolve(req.result);
|
|
3189
|
+
req.onerror = () => reject(req.error);
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
async put(path, data) {
|
|
3193
|
+
const db = await this.open();
|
|
3194
|
+
return new Promise((resolve, reject) => {
|
|
3195
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
3196
|
+
tx.objectStore(STORE_NAME).put(data, path);
|
|
3197
|
+
tx.oncomplete = () => resolve();
|
|
3198
|
+
tx.onerror = () => reject(tx.error);
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
async listChildren(prefix) {
|
|
3202
|
+
const db = await this.open();
|
|
3203
|
+
return new Promise((resolve, reject) => {
|
|
3204
|
+
const tx = db.transaction(STORE_NAME, "readonly");
|
|
3205
|
+
const store = tx.objectStore(STORE_NAME);
|
|
3206
|
+
const range = IDBKeyRange.bound(prefix, prefix + "", false, false);
|
|
3207
|
+
const req = store.getAllKeys(range);
|
|
3208
|
+
req.onsuccess = () => {
|
|
3209
|
+
const entries = new Set;
|
|
3210
|
+
for (const key of req.result) {
|
|
3211
|
+
const rest = key.slice(prefix.length);
|
|
3212
|
+
const slashIdx = rest.indexOf("/");
|
|
3213
|
+
if (slashIdx === -1) {
|
|
3214
|
+
entries.add(rest);
|
|
3215
|
+
} else {
|
|
3216
|
+
entries.add(rest.slice(0, slashIdx + 1));
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
resolve([...entries]);
|
|
3220
|
+
};
|
|
3221
|
+
req.onerror = () => reject(req.error);
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
parsePath(resource) {
|
|
3225
|
+
if (typeof resource === "string")
|
|
3226
|
+
return resource;
|
|
3227
|
+
if (resource instanceof URL)
|
|
3228
|
+
return resource.pathname;
|
|
3229
|
+
return new URL(resource.url).pathname;
|
|
3230
|
+
}
|
|
3231
|
+
parse(resource, init) {
|
|
3232
|
+
const pathname = this.parsePath(resource);
|
|
3233
|
+
if (typeof resource === "string" || resource instanceof URL) {
|
|
3234
|
+
return [pathname, init?.method ?? "GET", init?.body ?? null];
|
|
3235
|
+
}
|
|
3236
|
+
return [
|
|
3237
|
+
pathname,
|
|
3238
|
+
init?.method ?? resource.method,
|
|
3239
|
+
init?.body ?? resource.body
|
|
3240
|
+
];
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
// dist/src/service-worker/emroute.sw.js
|
|
3245
|
+
class SwRuntime extends Runtime {
|
|
3246
|
+
cache;
|
|
3247
|
+
idb;
|
|
3248
|
+
constructor(cache, idb) {
|
|
3249
|
+
super();
|
|
3250
|
+
this.cache = cache;
|
|
3251
|
+
this.idb = idb;
|
|
3252
|
+
}
|
|
3253
|
+
handle(resource, init) {
|
|
3254
|
+
const method = init?.method ?? "GET";
|
|
3255
|
+
if (method === "PUT" || method === "DELETE") {
|
|
3256
|
+
return this.idb.handle(resource, init);
|
|
3257
|
+
}
|
|
3258
|
+
return this.cache.handle(resource, init).then(async (r) => {
|
|
3259
|
+
if (r.status !== 404)
|
|
3260
|
+
return r;
|
|
3261
|
+
return this.idb.handle(resource, init);
|
|
3262
|
+
});
|
|
3263
|
+
}
|
|
3264
|
+
query(resource, options) {
|
|
3265
|
+
if (options?.as === "text") {
|
|
3266
|
+
return this.handle(resource, options).then(async (r) => {
|
|
3267
|
+
if (r.status === 404) {
|
|
3268
|
+
const path = typeof resource === "string" ? resource : resource instanceof URL ? resource.pathname : new URL(resource.url).pathname;
|
|
3269
|
+
throw new Error(`Not found: ${path}`);
|
|
3270
|
+
}
|
|
3271
|
+
return r.text();
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
return this.handle(resource, options);
|
|
3275
|
+
}
|
|
3276
|
+
async loadModule(path) {
|
|
3277
|
+
try {
|
|
3278
|
+
return await this.cache.loadModule(path);
|
|
3279
|
+
} catch {
|
|
3280
|
+
return await this.idb.loadModule(path);
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
function createEmrouteSW(options) {
|
|
3285
|
+
const { cacheName, precache, content = [], dbName = "emroute-content", origin = self.location.origin } = options;
|
|
3286
|
+
const cacheRuntime = new CacheRuntime(cacheName);
|
|
3287
|
+
const idbRuntime = new IdbRuntime(dbName);
|
|
3288
|
+
const swRuntime = new SwRuntime(cacheRuntime, idbRuntime);
|
|
3289
|
+
let emroute = null;
|
|
3290
|
+
async function getEmroute() {
|
|
3291
|
+
if (emroute)
|
|
3292
|
+
return emroute;
|
|
3293
|
+
emroute = await Emroute.create({
|
|
3294
|
+
spa: options.spa ?? "only",
|
|
3295
|
+
...options.basePath ? { basePath: options.basePath } : {},
|
|
3296
|
+
...options.title ? { title: options.title } : {},
|
|
3297
|
+
...options.markdownRenderer ? { markdownRenderer: options.markdownRenderer } : {},
|
|
3298
|
+
...options.extendContext ? { extendContext: options.extendContext } : {}
|
|
3299
|
+
}, swRuntime);
|
|
3300
|
+
return emroute;
|
|
3301
|
+
}
|
|
3302
|
+
self.addEventListener("install", (event) => {
|
|
3303
|
+
event.waitUntil((async () => {
|
|
3304
|
+
if (precache.length > 0) {
|
|
3305
|
+
const cache = await caches.open(cacheName);
|
|
3306
|
+
await Promise.all(precache.map(async (path) => {
|
|
3307
|
+
try {
|
|
3308
|
+
const response = await fetch(`${origin}${path}`);
|
|
3309
|
+
if (response.ok) {
|
|
3310
|
+
await cache.put(new Request(`https://emroute-cache${path}`), response);
|
|
3311
|
+
}
|
|
3312
|
+
} catch {
|
|
3313
|
+
console.error(`[emroute-sw] Failed to precache asset: ${path}`);
|
|
3314
|
+
}
|
|
3315
|
+
}));
|
|
3316
|
+
}
|
|
3317
|
+
if (content.length > 0) {
|
|
3318
|
+
await Promise.all(content.map(async (path) => {
|
|
3319
|
+
try {
|
|
3320
|
+
const response = await fetch(`${origin}${path}`);
|
|
3321
|
+
if (response.ok) {
|
|
3322
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
3323
|
+
await idbRuntime.handle(path, {
|
|
3324
|
+
method: "PUT",
|
|
3325
|
+
body: data
|
|
3326
|
+
});
|
|
3327
|
+
}
|
|
3328
|
+
} catch {
|
|
3329
|
+
console.error(`[emroute-sw] Failed to precache content: ${path}`);
|
|
3330
|
+
}
|
|
3331
|
+
}));
|
|
3332
|
+
}
|
|
3333
|
+
await self.skipWaiting();
|
|
3334
|
+
})());
|
|
3335
|
+
});
|
|
3336
|
+
self.addEventListener("activate", (event) => {
|
|
3337
|
+
event.waitUntil((async () => {
|
|
3338
|
+
const keys = await caches.keys();
|
|
3339
|
+
await Promise.all(keys.filter((key) => key !== cacheName && key.startsWith("emroute")).map((key) => caches.delete(key)));
|
|
3340
|
+
await self.clients.claim();
|
|
3341
|
+
})());
|
|
3342
|
+
});
|
|
3343
|
+
self.addEventListener("fetch", (event) => {
|
|
3344
|
+
const url = new URL(event.request.url);
|
|
3345
|
+
if (url.origin !== self.location.origin)
|
|
3346
|
+
return;
|
|
3347
|
+
event.respondWith(handleFetch(event.request, url));
|
|
3348
|
+
});
|
|
3349
|
+
async function handleFetch(request, url) {
|
|
3350
|
+
if (request.mode === "navigate") {
|
|
3351
|
+
try {
|
|
3352
|
+
const server = await getEmroute();
|
|
3353
|
+
const response = await server.handleRequest(request);
|
|
3354
|
+
if (response)
|
|
3355
|
+
return response;
|
|
3356
|
+
} catch (e) {
|
|
3357
|
+
console.error("[emroute-sw] Navigation error:", e);
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
const cached = await swRuntime.handle(url.pathname);
|
|
3361
|
+
if (cached.status !== 404)
|
|
3362
|
+
return cached;
|
|
3363
|
+
try {
|
|
3364
|
+
return await fetch(request);
|
|
3365
|
+
} catch {
|
|
3366
|
+
return new Response("Offline", { status: 503 });
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3034
3370
|
// dist/src/widget/page-title.widget.js
|
|
3035
3371
|
class PageTitleWidget extends WidgetComponent {
|
|
3036
3372
|
name = "page-title";
|
|
@@ -3109,23 +3445,25 @@ export {
|
|
|
3109
3445
|
scopeWidgetCss,
|
|
3110
3446
|
escapeHtml,
|
|
3111
3447
|
createOverlayService,
|
|
3448
|
+
createEmrouteSW,
|
|
3112
3449
|
createEmrouteApp,
|
|
3113
3450
|
bootEmrouteApp,
|
|
3114
|
-
WidgetRegistry,
|
|
3115
3451
|
WidgetComponent,
|
|
3116
3452
|
RouterSlot,
|
|
3117
3453
|
RouteTrie,
|
|
3118
3454
|
PageTitleWidget,
|
|
3119
3455
|
PageComponent,
|
|
3120
3456
|
MarkdownElement,
|
|
3457
|
+
IdbRuntime,
|
|
3121
3458
|
FetchRuntime,
|
|
3122
3459
|
EmrouteApp,
|
|
3123
3460
|
Emroute,
|
|
3124
3461
|
DEFAULT_BASE_PATH,
|
|
3125
3462
|
ComponentElement,
|
|
3126
3463
|
Component,
|
|
3464
|
+
CacheRuntime,
|
|
3127
3465
|
BreadcrumbWidget
|
|
3128
3466
|
};
|
|
3129
3467
|
|
|
3130
|
-
//# debugId=
|
|
3468
|
+
//# debugId=FB9DE7997217939864756E2164756E21
|
|
3131
3469
|
//# sourceMappingURL=emroute.js.map
|