@emkodev/emroute 1.7.2 → 1.8.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/README.md +1 -1
- package/core/component/abstract.component.ts +74 -0
- package/{src → core}/component/page.component.ts +3 -61
- package/core/component/widget.component.ts +54 -0
- package/core/pipeline/pipeline.ts +224 -0
- package/{src/renderer/ssr → core/renderer}/html.renderer.ts +19 -45
- package/{src/renderer/ssr → core/renderer}/md.renderer.ts +21 -40
- package/{src/renderer/ssr → core/renderer}/ssr.renderer.ts +42 -53
- package/{src/route → core/router}/route.resolver.ts +1 -10
- package/core/router/route.trie.ts +175 -0
- package/core/runtime/abstract.runtime.ts +47 -0
- package/core/server/emroute.server.ts +346 -0
- package/core/type/component.type.ts +39 -0
- package/core/type/element.type.ts +10 -0
- package/core/type/logger.type.ts +20 -0
- package/core/type/markdown.type.ts +8 -0
- package/core/type/route-tree.type.ts +28 -0
- package/core/type/route.type.ts +75 -0
- package/core/type/widget.type.ts +27 -0
- package/core/util/html.util.ts +50 -0
- package/{src → core}/util/md.util.ts +0 -2
- package/{src/route → core/util}/route-tree.util.ts +0 -2
- package/{src → core}/util/widget-resolve.util.ts +15 -45
- package/{src → core}/widget/widget.parser.ts +0 -21
- package/core/widget/widget.registry.ts +24 -0
- package/dist/core/component/abstract.component.d.ts +48 -0
- package/dist/core/component/abstract.component.js +42 -0
- package/dist/core/component/abstract.component.js.map +1 -0
- package/dist/core/component/page.component.d.ts +23 -0
- package/dist/core/component/page.component.js +49 -0
- package/dist/core/component/page.component.js.map +1 -0
- package/dist/core/component/widget.component.d.ts +17 -0
- package/dist/core/component/widget.component.js +37 -0
- package/dist/core/component/widget.component.js.map +1 -0
- package/dist/core/pipeline/pipeline.d.ts +61 -0
- package/dist/core/pipeline/pipeline.js +189 -0
- package/dist/core/pipeline/pipeline.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/html.renderer.d.ts +8 -24
- package/dist/{src/renderer/ssr → core/renderer}/html.renderer.js +12 -33
- package/dist/core/renderer/html.renderer.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/md.renderer.d.ts +6 -21
- package/dist/{src/renderer/ssr → core/renderer}/md.renderer.js +14 -31
- package/dist/core/renderer/md.renderer.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.d.ts +11 -17
- package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.js +34 -36
- package/dist/core/renderer/ssr.renderer.js.map +1 -0
- package/dist/{src/route → core/router}/route.resolver.d.ts +1 -8
- package/dist/{src/route → core/router}/route.resolver.js +0 -1
- package/dist/core/router/route.resolver.js.map +1 -0
- package/dist/core/router/route.trie.d.ts +32 -0
- package/dist/core/router/route.trie.js +152 -0
- package/dist/core/router/route.trie.js.map +1 -0
- package/dist/core/runtime/abstract.runtime.d.ts +32 -0
- package/dist/core/runtime/abstract.runtime.js +26 -0
- package/dist/core/runtime/abstract.runtime.js.map +1 -0
- package/dist/core/server/emroute.server.d.ts +48 -0
- package/dist/core/server/emroute.server.js +261 -0
- package/dist/core/server/emroute.server.js.map +1 -0
- package/dist/core/server/server.type.d.ts +45 -0
- package/dist/core/server/server.type.js +11 -0
- package/dist/core/server/server.type.js.map +1 -0
- package/dist/core/type/component.type.d.ts +37 -0
- package/dist/core/type/component.type.js +7 -0
- package/dist/core/type/component.type.js.map +1 -0
- package/dist/core/type/element.type.d.ts +9 -0
- package/dist/core/type/element.type.js +5 -0
- package/dist/core/type/element.type.js.map +1 -0
- package/dist/core/type/logger.type.d.ts +14 -0
- package/dist/core/type/logger.type.js +8 -0
- package/dist/core/type/logger.type.js.map +1 -0
- package/dist/core/type/markdown.type.d.ts +7 -0
- package/dist/core/type/markdown.type.js +5 -0
- package/dist/core/type/markdown.type.js.map +1 -0
- package/dist/{src → core}/type/route-tree.type.d.ts +0 -12
- package/dist/{src → core}/type/route-tree.type.js +0 -1
- package/dist/core/type/route-tree.type.js.map +1 -0
- package/dist/core/type/route.type.d.ts +62 -0
- package/dist/core/type/route.type.js +7 -0
- package/dist/core/type/route.type.js.map +1 -0
- package/dist/core/type/widget.type.d.ts +27 -0
- package/dist/core/type/widget.type.js +5 -0
- package/dist/core/type/widget.type.js.map +1 -0
- package/dist/core/util/html.util.d.ts +14 -0
- package/dist/core/util/html.util.js +43 -0
- package/dist/core/util/html.util.js.map +1 -0
- package/dist/{src → core}/util/md.util.d.ts +0 -1
- package/dist/{src → core}/util/md.util.js +0 -2
- package/dist/core/util/md.util.js.map +1 -0
- package/dist/{src/route → core/util}/route-tree.util.js +0 -2
- package/dist/core/util/route-tree.util.js.map +1 -0
- package/dist/core/util/widget-resolve.util.d.ts +32 -0
- package/dist/{src → core}/util/widget-resolve.util.js +11 -41
- package/dist/core/util/widget-resolve.util.js.map +1 -0
- package/dist/{src → core}/widget/widget.parser.d.ts +0 -13
- package/dist/{src → core}/widget/widget.parser.js +0 -21
- package/dist/core/widget/widget.parser.js.map +1 -0
- package/dist/core/widget/widget.registry.d.ts +13 -0
- package/dist/core/widget/widget.registry.js +19 -0
- package/dist/core/widget/widget.registry.js.map +1 -0
- package/dist/emroute.js +1137 -1151
- package/dist/emroute.js.map +36 -5
- package/dist/runtime/abstract.runtime.d.ts +50 -5
- package/dist/runtime/abstract.runtime.js +446 -6
- package/dist/runtime/abstract.runtime.js.map +1 -1
- package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +1 -0
- package/dist/runtime/bun/fs/bun-fs.runtime.js +18 -2
- package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +2 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +11 -1
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
- package/dist/runtime/fetch.runtime.d.ts +3 -3
- package/dist/runtime/fetch.runtime.js +3 -3
- package/dist/runtime/sitemap.generator.d.ts +1 -1
- package/dist/runtime/sitemap.generator.js +1 -1
- package/dist/runtime/sitemap.generator.js.map +1 -1
- package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +1 -0
- package/dist/runtime/universal/fs/universal-fs.runtime.js +18 -2
- package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
- package/dist/server/build.util.d.ts +9 -10
- package/dist/server/build.util.js +45 -36
- package/dist/server/build.util.js.map +1 -1
- package/dist/server/codegen.util.d.ts +1 -1
- package/dist/server/emroute.server.d.ts +8 -35
- package/dist/server/emroute.server.js +7 -341
- package/dist/server/emroute.server.js.map +1 -1
- package/dist/server/esbuild-manifest.plugin.js +1 -1
- package/dist/server/esbuild-manifest.plugin.js.map +1 -1
- package/dist/server/server-api.type.d.ts +3 -68
- package/dist/server/server-api.type.js +1 -8
- package/dist/server/server-api.type.js.map +1 -1
- package/dist/src/element/component.element.d.ts +4 -7
- package/dist/src/element/component.element.js +23 -22
- package/dist/src/element/component.element.js.map +1 -1
- package/dist/src/element/markdown.element.d.ts +2 -2
- package/dist/src/element/markdown.element.js +4 -3
- package/dist/src/element/markdown.element.js.map +1 -1
- package/dist/src/index.d.ts +15 -13
- package/dist/src/index.js +8 -8
- package/dist/src/index.js.map +1 -1
- package/dist/src/renderer/spa/emroute.app.d.ts +50 -0
- package/dist/src/renderer/spa/emroute.app.js +246 -0
- package/dist/src/renderer/spa/emroute.app.js.map +1 -0
- package/dist/src/renderer/spa/mod.d.ts +17 -16
- package/dist/src/renderer/spa/mod.js +9 -9
- package/dist/src/renderer/spa/mod.js.map +1 -1
- package/dist/src/renderer/spa/thin-client.d.ts +3 -3
- package/dist/src/renderer/spa/thin-client.js +34 -12
- package/dist/src/renderer/spa/thin-client.js.map +1 -1
- package/dist/src/route/route.core.d.ts +3 -3
- package/dist/src/route/route.core.js +21 -7
- package/dist/src/route/route.core.js.map +1 -1
- package/dist/src/util/html.util.d.ts +5 -22
- package/dist/src/util/html.util.js +8 -56
- package/dist/src/util/html.util.js.map +1 -1
- package/dist/src/widget/breadcrumb.widget.d.ts +2 -2
- package/dist/src/widget/breadcrumb.widget.js +2 -2
- package/dist/src/widget/breadcrumb.widget.js.map +1 -1
- package/dist/src/widget/page-title.widget.d.ts +1 -1
- package/dist/src/widget/page-title.widget.js +1 -1
- package/dist/src/widget/page-title.widget.js.map +1 -1
- package/package.json +8 -8
- package/runtime/abstract.runtime.ts +483 -8
- package/runtime/bun/fs/bun-fs.runtime.ts +17 -1
- package/runtime/bun/sqlite/bun-sqlite.runtime.ts +11 -0
- package/runtime/fetch.runtime.ts +3 -3
- package/runtime/sitemap.generator.ts +2 -2
- package/runtime/universal/fs/universal-fs.runtime.ts +17 -1
- package/server/build.util.ts +53 -47
- package/server/codegen.util.ts +1 -1
- package/server/emroute.server.ts +12 -412
- package/src/element/component.element.ts +24 -31
- package/src/element/markdown.element.ts +5 -4
- package/src/index.ts +22 -18
- package/src/renderer/spa/{thin-client.ts → emroute.app.ts} +46 -22
- package/src/renderer/spa/mod.ts +22 -22
- package/src/util/html.util.ts +16 -61
- package/src/widget/breadcrumb.widget.ts +3 -3
- package/src/widget/page-title.widget.ts +1 -1
- package/dist/src/component/abstract.component.d.ts +0 -199
- package/dist/src/component/abstract.component.js +0 -84
- package/dist/src/component/abstract.component.js.map +0 -1
- package/dist/src/component/page.component.d.ts +0 -74
- package/dist/src/component/page.component.js +0 -107
- package/dist/src/component/page.component.js.map +0 -1
- package/dist/src/component/widget.component.d.ts +0 -47
- package/dist/src/component/widget.component.js +0 -69
- package/dist/src/component/widget.component.js.map +0 -1
- package/dist/src/renderer/ssr/html.renderer.js.map +0 -1
- package/dist/src/renderer/ssr/md.renderer.js.map +0 -1
- package/dist/src/renderer/ssr/ssr.renderer.js.map +0 -1
- package/dist/src/route/route-tree.util.js.map +0 -1
- package/dist/src/route/route.matcher.d.ts +0 -86
- package/dist/src/route/route.matcher.js +0 -214
- package/dist/src/route/route.matcher.js.map +0 -1
- package/dist/src/route/route.resolver.js.map +0 -1
- package/dist/src/route/route.trie.d.ts +0 -38
- package/dist/src/route/route.trie.js +0 -206
- package/dist/src/route/route.trie.js.map +0 -1
- package/dist/src/type/logger.type.d.ts +0 -17
- package/dist/src/type/logger.type.js +0 -9
- package/dist/src/type/logger.type.js.map +0 -1
- package/dist/src/type/markdown.type.d.ts +0 -20
- package/dist/src/type/markdown.type.js +0 -2
- package/dist/src/type/markdown.type.js.map +0 -1
- package/dist/src/type/route-tree.type.js.map +0 -1
- package/dist/src/type/route.type.d.ts +0 -94
- package/dist/src/type/route.type.js +0 -8
- package/dist/src/type/route.type.js.map +0 -1
- package/dist/src/type/widget.type.d.ts +0 -55
- package/dist/src/type/widget.type.js +0 -10
- package/dist/src/type/widget.type.js.map +0 -1
- package/dist/src/util/logger.util.d.ts +0 -26
- package/dist/src/util/logger.util.js +0 -80
- package/dist/src/util/logger.util.js.map +0 -1
- package/dist/src/util/md.util.js.map +0 -1
- package/dist/src/util/widget-resolve.util.d.ts +0 -52
- package/dist/src/util/widget-resolve.util.js.map +0 -1
- package/dist/src/widget/widget.parser.js.map +0 -1
- package/dist/src/widget/widget.registry.d.ts +0 -23
- package/dist/src/widget/widget.registry.js +0 -42
- package/dist/src/widget/widget.registry.js.map +0 -1
- package/runtime/bun/esbuild-runtime-loader.plugin.ts +0 -112
- package/server/esbuild-manifest.plugin.ts +0 -209
- package/server/server-api.type.ts +0 -97
- package/src/component/abstract.component.ts +0 -231
- package/src/component/widget.component.ts +0 -85
- package/src/route/route.core.ts +0 -362
- package/src/route/route.trie.ts +0 -265
- package/src/type/logger.type.ts +0 -24
- package/src/type/markdown.type.ts +0 -21
- package/src/type/route-tree.type.ts +0 -51
- package/src/type/route.type.ts +0 -124
- package/src/type/widget.type.ts +0 -65
- package/src/util/logger.util.ts +0 -83
- package/src/widget/widget.registry.ts +0 -51
- /package/dist/{src/route → core/util}/route-tree.util.d.ts +0 -0
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import type { RouteNode } from '../
|
|
2
|
-
import type { WidgetManifestEntry } from '../
|
|
1
|
+
import type { RouteNode } from '../core/type/route-tree.type.ts';
|
|
2
|
+
import type { WidgetManifestEntry } from '../core/type/widget.type.ts';
|
|
3
|
+
import type { ElementManifestEntry } from '../core/type/element.type.ts';
|
|
3
4
|
export declare const CONTENT_TYPES: Map<string, string>;
|
|
4
5
|
export type FetchParams = Parameters<typeof fetch>;
|
|
5
6
|
export type FetchReturn = ReturnType<typeof fetch>;
|
|
6
7
|
export declare const DEFAULT_ROUTES_DIR = "/routes";
|
|
7
8
|
export declare const DEFAULT_WIDGETS_DIR = "/widgets";
|
|
8
|
-
export declare const
|
|
9
|
-
|
|
9
|
+
export declare const DEFAULT_ELEMENTS_DIR = "/elements";
|
|
10
|
+
import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, ELEMENTS_MANIFEST_PATH } from '../core/runtime/abstract.runtime.ts';
|
|
11
|
+
export { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, ELEMENTS_MANIFEST_PATH };
|
|
10
12
|
export interface RuntimeConfig {
|
|
11
13
|
routesDir?: string;
|
|
12
14
|
widgetsDir?: string;
|
|
15
|
+
elementsDir?: string;
|
|
13
16
|
}
|
|
14
17
|
/**
|
|
15
18
|
* Abstract resource provider. Speaks Request/Response (ADR-1).
|
|
@@ -37,7 +40,7 @@ export declare abstract class Runtime {
|
|
|
37
40
|
}): Promise<string>;
|
|
38
41
|
/** Read — returns full Response with headers, status, body. */
|
|
39
42
|
abstract query(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
|
|
40
|
-
/** Write. Defaults to PUT; pass `{ method: "DELETE" }`
|
|
43
|
+
/** Write or delete. Defaults to PUT; pass `{ method: "DELETE" }` to remove. */
|
|
41
44
|
command(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
|
|
42
45
|
/**
|
|
43
46
|
* Parse a single route file path and merge it into the stored manifest.
|
|
@@ -45,6 +48,31 @@ export declare abstract class Runtime {
|
|
|
45
48
|
* inserts the new entry, and writes it back.
|
|
46
49
|
*/
|
|
47
50
|
private mergeRouteIntoManifest;
|
|
51
|
+
/**
|
|
52
|
+
* Remove a route entry from the stored manifest when a file is deleted.
|
|
53
|
+
* Walks the tree to find the node, clears the relevant field, then
|
|
54
|
+
* prunes empty ancestor nodes.
|
|
55
|
+
*/
|
|
56
|
+
private pruneRouteFromManifest;
|
|
57
|
+
/** Find a target node without creating it (read-only counterpart to resolveTargetNode). */
|
|
58
|
+
private findTargetNode;
|
|
59
|
+
private isEmptyNode;
|
|
60
|
+
/**
|
|
61
|
+
* Remove a widget entry from the stored manifest when a file is deleted.
|
|
62
|
+
*/
|
|
63
|
+
private pruneWidgetFromManifest;
|
|
64
|
+
/**
|
|
65
|
+
* Remove an element entry from the stored manifest when a file is deleted.
|
|
66
|
+
*/
|
|
67
|
+
private pruneElementFromManifest;
|
|
68
|
+
/**
|
|
69
|
+
* After a source or companion file is written, check if a built `.js`
|
|
70
|
+
* artifact exists for that module. If so, re-transpile the `.ts` source
|
|
71
|
+
* with companions inlined and write the `.js` back.
|
|
72
|
+
*
|
|
73
|
+
* Best-effort: silently skips if `transpile()` is not implemented.
|
|
74
|
+
*/
|
|
75
|
+
private retranspileIfNeeded;
|
|
48
76
|
/**
|
|
49
77
|
* Dynamically import a module from this runtime's storage.
|
|
50
78
|
* Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.
|
|
@@ -55,8 +83,19 @@ export declare abstract class Runtime {
|
|
|
55
83
|
* Used by the build step to produce browser-loadable .js modules.
|
|
56
84
|
*/
|
|
57
85
|
transpile(_source: string): Promise<string>;
|
|
86
|
+
/**
|
|
87
|
+
* Parse a widget file path and merge it into the stored manifest.
|
|
88
|
+
* Reads the current manifest, upserts the entry, writes it back.
|
|
89
|
+
*/
|
|
90
|
+
private mergeWidgetIntoManifest;
|
|
91
|
+
/**
|
|
92
|
+
* Parse an element file path and merge it into the stored manifest.
|
|
93
|
+
* Reads the current manifest, upserts the entry, writes it back.
|
|
94
|
+
*/
|
|
95
|
+
private mergeElementIntoManifest;
|
|
58
96
|
private routesManifestCache;
|
|
59
97
|
private widgetsManifestCache;
|
|
98
|
+
private elementsManifestCache;
|
|
60
99
|
/** Clear cached manifests so the next query triggers a fresh scan. */
|
|
61
100
|
invalidateManifests(): void;
|
|
62
101
|
/**
|
|
@@ -69,6 +108,11 @@ export declare abstract class Runtime {
|
|
|
69
108
|
* 404 for WIDGETS_MANIFEST_PATH. Scans `config.widgetsDir` (or default).
|
|
70
109
|
*/
|
|
71
110
|
resolveWidgetsManifest(): Promise<Response>;
|
|
111
|
+
/**
|
|
112
|
+
* Resolve the elements manifest. Called when the concrete runtime returns
|
|
113
|
+
* 404 for ELEMENTS_MANIFEST_PATH. Scans `config.elementsDir` (or default).
|
|
114
|
+
*/
|
|
115
|
+
resolveElementsManifest(): Promise<Response>;
|
|
72
116
|
protected walkDirectory(dir: string): AsyncGenerator<string>;
|
|
73
117
|
/**
|
|
74
118
|
* Scan a routes directory and build a RouteNode tree.
|
|
@@ -76,4 +120,5 @@ export declare abstract class Runtime {
|
|
|
76
120
|
*/
|
|
77
121
|
protected scanRoutes(routesDir: string): Promise<RouteNode>;
|
|
78
122
|
protected scanWidgets(widgetsDir: string, pathPrefix?: string): Promise<WidgetManifestEntry[]>;
|
|
123
|
+
protected scanElements(elementsDir: string, pathPrefix?: string): Promise<ElementManifestEntry[]>;
|
|
79
124
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveTargetNode } from "../
|
|
1
|
+
import { resolveTargetNode } from "../core/util/route-tree.util.js";
|
|
2
2
|
export const CONTENT_TYPES = new Map([
|
|
3
3
|
['.html', 'text/html; charset=utf-8'],
|
|
4
4
|
['.css', 'text/css; charset=utf-8'],
|
|
@@ -24,8 +24,9 @@ export const CONTENT_TYPES = new Map([
|
|
|
24
24
|
]);
|
|
25
25
|
export const DEFAULT_ROUTES_DIR = '/routes';
|
|
26
26
|
export const DEFAULT_WIDGETS_DIR = '/widgets';
|
|
27
|
-
export const
|
|
28
|
-
|
|
27
|
+
export const DEFAULT_ELEMENTS_DIR = '/elements';
|
|
28
|
+
import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, ELEMENTS_MANIFEST_PATH, } from "../core/runtime/abstract.runtime.js";
|
|
29
|
+
export { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, ELEMENTS_MANIFEST_PATH };
|
|
29
30
|
/**
|
|
30
31
|
* Abstract resource provider. Speaks Request/Response (ADR-1).
|
|
31
32
|
*
|
|
@@ -44,16 +45,50 @@ export class Runtime {
|
|
|
44
45
|
this.config = config;
|
|
45
46
|
this.config = config;
|
|
46
47
|
}
|
|
47
|
-
/** Write. Defaults to PUT; pass `{ method: "DELETE" }`
|
|
48
|
+
/** Write or delete. Defaults to PUT; pass `{ method: "DELETE" }` to remove. */
|
|
48
49
|
command(resource, options) {
|
|
49
50
|
const path = typeof resource === 'string'
|
|
50
51
|
? resource
|
|
51
52
|
: new URL(resource instanceof Request ? resource.url : resource.toString()).pathname;
|
|
52
|
-
const
|
|
53
|
+
const method = options?.method ?? 'PUT';
|
|
54
|
+
const isDelete = method === 'DELETE';
|
|
55
|
+
const result = this.handle(resource, { method, ...options });
|
|
53
56
|
const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;
|
|
57
|
+
const widgetsDir = this.config.widgetsDir ?? DEFAULT_WIDGETS_DIR;
|
|
58
|
+
const elementsDir = this.config.elementsDir ?? DEFAULT_ELEMENTS_DIR;
|
|
54
59
|
if (path.startsWith(routesDir + '/')) {
|
|
55
60
|
return result.then(async (res) => {
|
|
56
|
-
|
|
61
|
+
if (isDelete) {
|
|
62
|
+
await this.pruneRouteFromManifest(path, routesDir);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
await this.mergeRouteIntoManifest(path, routesDir);
|
|
66
|
+
await this.retranspileIfNeeded(path, routesDir, 'route');
|
|
67
|
+
}
|
|
68
|
+
return res;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (path.startsWith(widgetsDir + '/')) {
|
|
72
|
+
return result.then(async (res) => {
|
|
73
|
+
if (isDelete) {
|
|
74
|
+
await this.pruneWidgetFromManifest(path, widgetsDir);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
await this.mergeWidgetIntoManifest(path, widgetsDir);
|
|
78
|
+
await this.retranspileIfNeeded(path, widgetsDir, 'widget');
|
|
79
|
+
}
|
|
80
|
+
return res;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (path.startsWith(elementsDir + '/')) {
|
|
84
|
+
return result.then(async (res) => {
|
|
85
|
+
if (isDelete) {
|
|
86
|
+
await this.pruneElementFromManifest(path, elementsDir);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await this.mergeElementIntoManifest(path, elementsDir);
|
|
90
|
+
await this.retranspileIfNeeded(path, elementsDir, 'element');
|
|
91
|
+
}
|
|
57
92
|
return res;
|
|
58
93
|
});
|
|
59
94
|
}
|
|
@@ -113,6 +148,265 @@ export class Runtime {
|
|
|
113
148
|
body: JSON.stringify(tree),
|
|
114
149
|
});
|
|
115
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Remove a route entry from the stored manifest when a file is deleted.
|
|
153
|
+
* Walks the tree to find the node, clears the relevant field, then
|
|
154
|
+
* prunes empty ancestor nodes.
|
|
155
|
+
*/
|
|
156
|
+
async pruneRouteFromManifest(filePath, routesDir) {
|
|
157
|
+
const relativePath = filePath.slice(routesDir.length + 1);
|
|
158
|
+
const parts = relativePath.split('/');
|
|
159
|
+
const filename = parts[parts.length - 1];
|
|
160
|
+
const dirSegments = parts.slice(0, -1);
|
|
161
|
+
const match = filename.match(/^(.+?)\.(page|error|redirect)\.(ts|js|html|md|css)$/);
|
|
162
|
+
if (!match)
|
|
163
|
+
return;
|
|
164
|
+
const [, name, kind, ext] = match;
|
|
165
|
+
const response = await this.handle(ROUTES_MANIFEST_PATH);
|
|
166
|
+
if (response.status === 404)
|
|
167
|
+
return;
|
|
168
|
+
const tree = await response.json();
|
|
169
|
+
// Walk to the parent node, tracking path for pruning
|
|
170
|
+
const ancestors = [];
|
|
171
|
+
let node = tree;
|
|
172
|
+
for (const dir of dirSegments) {
|
|
173
|
+
if (dir.startsWith('[') && dir.endsWith(']')) {
|
|
174
|
+
if (!node.dynamic)
|
|
175
|
+
return;
|
|
176
|
+
ancestors.push({ node, key: dir, via: 'dynamic' });
|
|
177
|
+
node = node.dynamic.child;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
if (!node.children?.[dir])
|
|
181
|
+
return;
|
|
182
|
+
ancestors.push({ node, key: dir, via: 'children' });
|
|
183
|
+
node = node.children[dir];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Clear the field
|
|
187
|
+
if (kind === 'error') {
|
|
188
|
+
if (node.errorBoundary === filePath)
|
|
189
|
+
delete node.errorBoundary;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const isRoot = dirSegments.length === 0;
|
|
193
|
+
const target = this.findTargetNode(node, name, isRoot);
|
|
194
|
+
if (!target)
|
|
195
|
+
return;
|
|
196
|
+
if (kind === 'redirect') {
|
|
197
|
+
if (target.redirect === filePath)
|
|
198
|
+
delete target.redirect;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
if (target.files?.[ext] === filePath) {
|
|
202
|
+
delete target.files[ext];
|
|
203
|
+
if (Object.keys(target.files).length === 0)
|
|
204
|
+
delete target.files;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// If target is a child node and now empty, remove it
|
|
208
|
+
if (target !== node && this.isEmptyNode(target)) {
|
|
209
|
+
if (name === 'index' && !isRoot) {
|
|
210
|
+
delete node.wildcard;
|
|
211
|
+
}
|
|
212
|
+
else if (name.startsWith('[') && name.endsWith(']')) {
|
|
213
|
+
delete node.dynamic;
|
|
214
|
+
}
|
|
215
|
+
else if (node.children) {
|
|
216
|
+
delete node.children[name];
|
|
217
|
+
if (Object.keys(node.children).length === 0)
|
|
218
|
+
delete node.children;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Prune empty ancestors bottom-up
|
|
223
|
+
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
224
|
+
const { node: parent, key, via } = ancestors[i];
|
|
225
|
+
const child = via === 'dynamic' ? parent.dynamic?.child : parent.children?.[key];
|
|
226
|
+
if (child && this.isEmptyNode(child)) {
|
|
227
|
+
if (via === 'dynamic') {
|
|
228
|
+
delete parent.dynamic;
|
|
229
|
+
}
|
|
230
|
+
else if (parent.children) {
|
|
231
|
+
delete parent.children[key];
|
|
232
|
+
if (Object.keys(parent.children).length === 0)
|
|
233
|
+
delete parent.children;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
this.routesManifestCache = null;
|
|
238
|
+
await this.handle(ROUTES_MANIFEST_PATH, {
|
|
239
|
+
method: 'PUT',
|
|
240
|
+
body: JSON.stringify(tree),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/** Find a target node without creating it (read-only counterpart to resolveTargetNode). */
|
|
244
|
+
findTargetNode(node, name, isRoot) {
|
|
245
|
+
if (name === 'index') {
|
|
246
|
+
return isRoot ? node : (node.wildcard?.child ?? null);
|
|
247
|
+
}
|
|
248
|
+
if (name.startsWith('[') && name.endsWith(']')) {
|
|
249
|
+
return node.dynamic?.child ?? null;
|
|
250
|
+
}
|
|
251
|
+
return node.children?.[name] ?? null;
|
|
252
|
+
}
|
|
253
|
+
isEmptyNode(node) {
|
|
254
|
+
return (!node.files &&
|
|
255
|
+
!node.errorBoundary &&
|
|
256
|
+
!node.redirect &&
|
|
257
|
+
!node.children &&
|
|
258
|
+
!node.dynamic &&
|
|
259
|
+
!node.wildcard);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Remove a widget entry from the stored manifest when a file is deleted.
|
|
263
|
+
*/
|
|
264
|
+
async pruneWidgetFromManifest(filePath, widgetsDir) {
|
|
265
|
+
const relativePath = filePath.slice(widgetsDir.length + 1);
|
|
266
|
+
const parts = relativePath.split('/');
|
|
267
|
+
if (parts.length !== 2)
|
|
268
|
+
return;
|
|
269
|
+
const [dirName, filename] = parts;
|
|
270
|
+
const match = filename.match(/^(.+?)\.widget\.(ts|js|html|md|css)$/);
|
|
271
|
+
if (!match)
|
|
272
|
+
return;
|
|
273
|
+
const [, name, ext] = match;
|
|
274
|
+
if (name !== dirName)
|
|
275
|
+
return;
|
|
276
|
+
const response = await this.handle(WIDGETS_MANIFEST_PATH);
|
|
277
|
+
if (response.status === 404)
|
|
278
|
+
return;
|
|
279
|
+
const entries = await response.json();
|
|
280
|
+
if (ext === 'ts' || ext === 'js') {
|
|
281
|
+
// Module deleted → remove entire entry
|
|
282
|
+
const idx = entries.findIndex((e) => e.name === name);
|
|
283
|
+
if (idx === -1)
|
|
284
|
+
return;
|
|
285
|
+
entries.splice(idx, 1);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// Companion deleted → remove from files
|
|
289
|
+
const entry = entries.find((e) => e.name === name);
|
|
290
|
+
if (!entry?.files)
|
|
291
|
+
return;
|
|
292
|
+
delete entry.files[ext];
|
|
293
|
+
if (Object.keys(entry.files).length === 0)
|
|
294
|
+
delete entry.files;
|
|
295
|
+
}
|
|
296
|
+
this.widgetsManifestCache = null;
|
|
297
|
+
await this.handle(WIDGETS_MANIFEST_PATH, {
|
|
298
|
+
method: 'PUT',
|
|
299
|
+
body: JSON.stringify(entries),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Remove an element entry from the stored manifest when a file is deleted.
|
|
304
|
+
*/
|
|
305
|
+
async pruneElementFromManifest(filePath, elementsDir) {
|
|
306
|
+
const relativePath = filePath.slice(elementsDir.length + 1);
|
|
307
|
+
const parts = relativePath.split('/');
|
|
308
|
+
if (parts.length !== 2)
|
|
309
|
+
return;
|
|
310
|
+
const [dirName, filename] = parts;
|
|
311
|
+
const match = filename.match(/^(.+?)\.element\.(ts|js)$/);
|
|
312
|
+
if (!match)
|
|
313
|
+
return;
|
|
314
|
+
const [, name] = match;
|
|
315
|
+
if (name !== dirName)
|
|
316
|
+
return;
|
|
317
|
+
const response = await this.handle(ELEMENTS_MANIFEST_PATH);
|
|
318
|
+
if (response.status === 404)
|
|
319
|
+
return;
|
|
320
|
+
const entries = await response.json();
|
|
321
|
+
const idx = entries.findIndex((e) => e.name === name);
|
|
322
|
+
if (idx === -1)
|
|
323
|
+
return;
|
|
324
|
+
entries.splice(idx, 1);
|
|
325
|
+
this.elementsManifestCache = null;
|
|
326
|
+
await this.handle(ELEMENTS_MANIFEST_PATH, {
|
|
327
|
+
method: 'PUT',
|
|
328
|
+
body: JSON.stringify(entries),
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* After a source or companion file is written, check if a built `.js`
|
|
333
|
+
* artifact exists for that module. If so, re-transpile the `.ts` source
|
|
334
|
+
* with companions inlined and write the `.js` back.
|
|
335
|
+
*
|
|
336
|
+
* Best-effort: silently skips if `transpile()` is not implemented.
|
|
337
|
+
*/
|
|
338
|
+
async retranspileIfNeeded(filePath, dir, kind) {
|
|
339
|
+
// Only act on source/companion files, not the .js output itself
|
|
340
|
+
if (filePath.endsWith('.js'))
|
|
341
|
+
return;
|
|
342
|
+
const relativePath = filePath.slice(dir.length + 1);
|
|
343
|
+
const parts = relativePath.split('/');
|
|
344
|
+
const filename = parts[parts.length - 1];
|
|
345
|
+
// Determine the module base name and the .js output path
|
|
346
|
+
let jsPath;
|
|
347
|
+
if (kind === 'route') {
|
|
348
|
+
const match = filename.match(/^(.+?)\.(page)\.(ts|html|md|css)$/);
|
|
349
|
+
if (!match)
|
|
350
|
+
return;
|
|
351
|
+
const [, name] = match;
|
|
352
|
+
jsPath = `${dir}/${parts.slice(0, -1).join('/')}${parts.length > 1 ? '/' : ''}${name}.page.js`;
|
|
353
|
+
}
|
|
354
|
+
else if (kind === 'widget') {
|
|
355
|
+
const match = filename.match(/^(.+?)\.(widget)\.(ts|html|md|css)$/);
|
|
356
|
+
if (!match)
|
|
357
|
+
return;
|
|
358
|
+
const [, name] = match;
|
|
359
|
+
jsPath = `${dir}/${name}/${name}.widget.js`;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
const match = filename.match(/^(.+?)\.(element)\.ts$/);
|
|
363
|
+
if (!match)
|
|
364
|
+
return;
|
|
365
|
+
const [, name] = match;
|
|
366
|
+
jsPath = `${dir}/${name}/${name}.element.js`;
|
|
367
|
+
}
|
|
368
|
+
// Check if the .js artifact exists
|
|
369
|
+
const jsResponse = await this.handle(jsPath);
|
|
370
|
+
if (jsResponse.status === 404)
|
|
371
|
+
return;
|
|
372
|
+
// Read the .ts source
|
|
373
|
+
const tsPath = jsPath.replace(/\.js$/, '.ts');
|
|
374
|
+
let tsSource;
|
|
375
|
+
try {
|
|
376
|
+
tsSource = await this.query(tsPath, { as: 'text' });
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
return; // .ts doesn't exist (maybe .js was hand-written)
|
|
380
|
+
}
|
|
381
|
+
// Collect companion files and inline them
|
|
382
|
+
const companionExts = kind === 'element' ? [] : ['html', 'md', 'css'];
|
|
383
|
+
const files = {};
|
|
384
|
+
for (const ext of companionExts) {
|
|
385
|
+
const companionPath = tsPath.replace(/\.ts$/, `.${ext}`);
|
|
386
|
+
try {
|
|
387
|
+
files[ext] = await this.query(companionPath, { as: 'text' });
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// companion doesn't exist — skip
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Transpile
|
|
394
|
+
let jsCode;
|
|
395
|
+
try {
|
|
396
|
+
jsCode = await this.transpile(tsSource);
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
return; // transpile not implemented — skip silently
|
|
400
|
+
}
|
|
401
|
+
// Append __files export if there are companions
|
|
402
|
+
if (Object.keys(files).length > 0) {
|
|
403
|
+
const entries = Object.entries(files)
|
|
404
|
+
.map(([k, v]) => `${k}: \`${v.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$')}\``)
|
|
405
|
+
.join(', ');
|
|
406
|
+
jsCode += `\nexport const __files = { ${entries} };\n`;
|
|
407
|
+
}
|
|
408
|
+
await this.handle(jsPath, { method: 'PUT', body: jsCode });
|
|
409
|
+
}
|
|
116
410
|
/**
|
|
117
411
|
* Dynamically import a module from this runtime's storage.
|
|
118
412
|
* Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.
|
|
@@ -127,13 +421,110 @@ export class Runtime {
|
|
|
127
421
|
transpile(_source) {
|
|
128
422
|
throw new Error(`transpile not implemented for ${this.constructor.name}`);
|
|
129
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* Parse a widget file path and merge it into the stored manifest.
|
|
426
|
+
* Reads the current manifest, upserts the entry, writes it back.
|
|
427
|
+
*/
|
|
428
|
+
async mergeWidgetIntoManifest(filePath, widgetsDir) {
|
|
429
|
+
const relativePath = filePath.slice(widgetsDir.length + 1);
|
|
430
|
+
const parts = relativePath.split('/');
|
|
431
|
+
if (parts.length !== 2)
|
|
432
|
+
return; // must be widgets/{name}/{file}
|
|
433
|
+
const [dirName, filename] = parts;
|
|
434
|
+
// Only act on .widget.{ts,js,html,md,css} files
|
|
435
|
+
const match = filename.match(/^(.+?)\.widget\.(ts|js|html|md|css)$/);
|
|
436
|
+
if (!match)
|
|
437
|
+
return;
|
|
438
|
+
const [, name, ext] = match;
|
|
439
|
+
if (name !== dirName)
|
|
440
|
+
return; // filename must match directory
|
|
441
|
+
const response = await this.handle(WIDGETS_MANIFEST_PATH);
|
|
442
|
+
const entries = response.status === 404
|
|
443
|
+
? []
|
|
444
|
+
: await response.json();
|
|
445
|
+
const prefix = widgetsDir.replace(/^\//, '');
|
|
446
|
+
if (ext === 'ts' || ext === 'js') {
|
|
447
|
+
// Module file — upsert the entry
|
|
448
|
+
let entry = entries.find((e) => e.name === name);
|
|
449
|
+
if (!entry) {
|
|
450
|
+
entry = {
|
|
451
|
+
name,
|
|
452
|
+
modulePath: `${prefix}/${name}/${filename}`,
|
|
453
|
+
tagName: `widget-${name}`,
|
|
454
|
+
};
|
|
455
|
+
entries.push(entry);
|
|
456
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
entry.modulePath = `${prefix}/${name}/${filename}`;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
// Companion file — update files on existing entry
|
|
464
|
+
const entry = entries.find((e) => e.name === name);
|
|
465
|
+
if (!entry)
|
|
466
|
+
return; // no module yet, companion alone is not enough
|
|
467
|
+
entry.files ??= {};
|
|
468
|
+
entry.files[ext] = `${prefix}/${name}/${filename}`;
|
|
469
|
+
}
|
|
470
|
+
this.widgetsManifestCache = null;
|
|
471
|
+
await this.handle(WIDGETS_MANIFEST_PATH, {
|
|
472
|
+
method: 'PUT',
|
|
473
|
+
body: JSON.stringify(entries),
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Parse an element file path and merge it into the stored manifest.
|
|
478
|
+
* Reads the current manifest, upserts the entry, writes it back.
|
|
479
|
+
*/
|
|
480
|
+
async mergeElementIntoManifest(filePath, elementsDir) {
|
|
481
|
+
const relativePath = filePath.slice(elementsDir.length + 1);
|
|
482
|
+
const parts = relativePath.split('/');
|
|
483
|
+
if (parts.length !== 2)
|
|
484
|
+
return;
|
|
485
|
+
const [dirName, filename] = parts;
|
|
486
|
+
const match = filename.match(/^(.+?)\.element\.(ts|js)$/);
|
|
487
|
+
if (!match)
|
|
488
|
+
return;
|
|
489
|
+
const [, name] = match;
|
|
490
|
+
if (name !== dirName)
|
|
491
|
+
return;
|
|
492
|
+
// Custom element names must contain a hyphen
|
|
493
|
+
if (!name.includes('-'))
|
|
494
|
+
return;
|
|
495
|
+
const response = await this.handle(ELEMENTS_MANIFEST_PATH);
|
|
496
|
+
const entries = response.status === 404
|
|
497
|
+
? []
|
|
498
|
+
: await response.json();
|
|
499
|
+
const prefix = elementsDir.replace(/^\//, '');
|
|
500
|
+
let entry = entries.find((e) => e.name === name);
|
|
501
|
+
if (!entry) {
|
|
502
|
+
entry = {
|
|
503
|
+
name,
|
|
504
|
+
modulePath: `${prefix}/${name}/${filename}`,
|
|
505
|
+
tagName: name,
|
|
506
|
+
};
|
|
507
|
+
entries.push(entry);
|
|
508
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
entry.modulePath = `${prefix}/${name}/${filename}`;
|
|
512
|
+
}
|
|
513
|
+
this.elementsManifestCache = null;
|
|
514
|
+
await this.handle(ELEMENTS_MANIFEST_PATH, {
|
|
515
|
+
method: 'PUT',
|
|
516
|
+
body: JSON.stringify(entries),
|
|
517
|
+
});
|
|
518
|
+
}
|
|
130
519
|
// ── Manifest resolution ─────────────────────────────────────────────
|
|
131
520
|
routesManifestCache = null;
|
|
132
521
|
widgetsManifestCache = null;
|
|
522
|
+
elementsManifestCache = null;
|
|
133
523
|
/** Clear cached manifests so the next query triggers a fresh scan. */
|
|
134
524
|
invalidateManifests() {
|
|
135
525
|
this.routesManifestCache = null;
|
|
136
526
|
this.widgetsManifestCache = null;
|
|
527
|
+
this.elementsManifestCache = null;
|
|
137
528
|
}
|
|
138
529
|
/**
|
|
139
530
|
* Resolve the routes manifest. Called when the concrete runtime returns
|
|
@@ -168,6 +559,22 @@ export class Runtime {
|
|
|
168
559
|
this.widgetsManifestCache = Response.json(entries);
|
|
169
560
|
return this.widgetsManifestCache.clone();
|
|
170
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Resolve the elements manifest. Called when the concrete runtime returns
|
|
564
|
+
* 404 for ELEMENTS_MANIFEST_PATH. Scans `config.elementsDir` (or default).
|
|
565
|
+
*/
|
|
566
|
+
async resolveElementsManifest() {
|
|
567
|
+
if (this.elementsManifestCache)
|
|
568
|
+
return this.elementsManifestCache.clone();
|
|
569
|
+
const elementsDir = this.config.elementsDir ?? DEFAULT_ELEMENTS_DIR;
|
|
570
|
+
const dirResponse = await this.query(elementsDir + '/');
|
|
571
|
+
if (dirResponse.status === 404) {
|
|
572
|
+
return new Response('Not Found', { status: 404 });
|
|
573
|
+
}
|
|
574
|
+
const entries = await this.scanElements(elementsDir, elementsDir.replace(/^\//, ''));
|
|
575
|
+
this.elementsManifestCache = Response.json(entries);
|
|
576
|
+
return this.elementsManifestCache.clone();
|
|
577
|
+
}
|
|
171
578
|
// ── Scanning ──────────────────────────────────────────────────────────
|
|
172
579
|
async *walkDirectory(dir) {
|
|
173
580
|
const trailingDir = dir.endsWith('/') ? dir : dir + '/';
|
|
@@ -280,5 +687,38 @@ export class Runtime {
|
|
|
280
687
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
281
688
|
return entries;
|
|
282
689
|
}
|
|
690
|
+
async scanElements(elementsDir, pathPrefix) {
|
|
691
|
+
const entries = [];
|
|
692
|
+
const trailingDir = elementsDir.endsWith('/') ? elementsDir : elementsDir + '/';
|
|
693
|
+
const response = await this.query(trailingDir);
|
|
694
|
+
const listing = await response.json();
|
|
695
|
+
for (const item of listing) {
|
|
696
|
+
if (!item.endsWith('/'))
|
|
697
|
+
continue;
|
|
698
|
+
const name = item.slice(0, -1);
|
|
699
|
+
// Custom element names must contain a hyphen (web spec requirement)
|
|
700
|
+
if (!name.includes('-')) {
|
|
701
|
+
console.warn(`[emroute] Skipping element "${name}": custom element names must contain a hyphen (e.g. "my-element")`);
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
// Try .element.ts first, then .element.js
|
|
705
|
+
let moduleFile = `${name}.element.ts`;
|
|
706
|
+
let modulePath = `${trailingDir}${name}/${moduleFile}`;
|
|
707
|
+
if ((await this.query(modulePath)).status === 404) {
|
|
708
|
+
moduleFile = `${name}.element.js`;
|
|
709
|
+
modulePath = `${trailingDir}${name}/${moduleFile}`;
|
|
710
|
+
if ((await this.query(modulePath)).status === 404)
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
const prefix = pathPrefix ? `${pathPrefix}/` : '';
|
|
714
|
+
entries.push({
|
|
715
|
+
name,
|
|
716
|
+
modulePath: `${prefix}${name}/${moduleFile}`,
|
|
717
|
+
tagName: name,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
721
|
+
return entries;
|
|
722
|
+
}
|
|
283
723
|
}
|
|
284
724
|
//# sourceMappingURL=abstract.runtime.js.map
|