htmx-router 1.0.0-alpha.4 → 1.0.0-alpha.6
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/{bin/util/css.js → css.js} +1 -1
- package/dynamic.d.ts +5 -0
- package/{bin/util/dynamic.js → dynamic.js} +20 -7
- package/{bin/util/endpoint.d.ts → endpoint.d.ts} +2 -2
- package/{bin/util/endpoint.js → endpoint.js} +3 -1
- package/event-source.d.ts +26 -0
- package/event-source.js +123 -0
- package/example/eventdim-react/package.json +67 -0
- package/example/eventdim-react/server.js +90 -0
- package/example/island-react/global.d.ts +8 -0
- package/example/island-react/package.json +38 -0
- package/example/island-react/server.js +58 -0
- package/global.d.ts +7 -0
- package/index.d.ts +19 -0
- package/index.js +2 -0
- package/internal/cli/config.d.ts +13 -0
- package/internal/cli/config.js +11 -0
- package/internal/cli/index.js +15 -0
- package/internal/client.d.ts +1 -0
- package/{bin/client/entry.js → internal/client.js} +3 -1
- package/internal/compile/manifest.d.ts +1 -0
- package/internal/compile/manifest.js +178 -0
- package/internal/compile/router.d.ts +1 -0
- package/internal/compile/router.js +51 -0
- package/internal/component/dynamic.d.ts +4 -0
- package/internal/component/dynamic.js +18 -0
- package/internal/component/head.d.ts +5 -0
- package/internal/component/head.js +22 -0
- package/internal/component/scripts.d.ts +4 -0
- package/internal/component/scripts.js +23 -0
- package/{bin/client → internal}/mount.js +15 -9
- package/internal/request/http.d.ts +10 -0
- package/internal/request/http.js +61 -0
- package/{bin → internal}/request/index.d.ts +3 -3
- package/internal/request/index.js +8 -0
- package/{bin → internal}/request/native.d.ts +2 -2
- package/{bin → internal}/request/native.js +12 -14
- package/{bin/helper.d.ts → internal/util.d.ts} +2 -0
- package/{bin/helper.js → internal/util.js} +15 -0
- package/package.json +9 -5
- package/readme.md +2 -214
- package/{bin/request → request}/http.d.ts +1 -1
- package/{bin/request → request}/http.js +22 -4
- package/request/index.d.ts +13 -0
- package/request/index.js +3 -0
- package/request/native.d.ts +9 -0
- package/request/native.js +46 -0
- package/response.d.ts +13 -0
- package/{bin/response.js → response.js} +25 -12
- package/{bin/router.d.ts → router.d.ts} +12 -10
- package/{bin/router.js → router.js} +62 -48
- package/shell.d.ts +120 -0
- package/shell.js +253 -0
- package/{bin/util → util}/parameters.d.ts +0 -3
- package/{bin/util → util}/parameters.js +0 -3
- package/{bin/util → util}/path-builder.js +2 -0
- package/util/route.d.ts +2 -0
- package/util/route.js +58 -0
- package/vite/bundle-splitter.d.ts +4 -0
- package/vite/bundle-splitter.js +26 -0
- package/vite/client-island.d.ts +4 -0
- package/vite/client-island.js +14 -0
- package/vite/code-splitting.d.ts +4 -0
- package/vite/code-splitting.js +14 -0
- package/vite/index.d.ts +3 -0
- package/vite/index.js +3 -0
- package/vite/router.d.ts +2 -0
- package/vite/router.js +29 -0
- package/bin/cli/config.d.ts +0 -10
- package/bin/cli/config.js +0 -4
- package/bin/cli/index.js +0 -72
- package/bin/client/entry.d.ts +0 -1
- package/bin/client/index.d.ts +0 -7
- package/bin/client/index.js +0 -126
- package/bin/client/watch.d.ts +0 -1
- package/bin/client/watch.js +0 -11
- package/bin/index.d.ts +0 -9
- package/bin/index.js +0 -8
- package/bin/request/index.js +0 -6
- package/bin/response.d.ts +0 -4
- package/bin/types.d.ts +0 -10
- package/bin/types.js +0 -1
- package/bin/util/dynamic.d.ts +0 -8
- package/bin/util/event-source.d.ts +0 -16
- package/bin/util/event-source.js +0 -85
- package/bin/util/index.d.ts +0 -1
- package/bin/util/index.js +0 -7
- package/bin/util/shell.d.ts +0 -32
- package/bin/util/shell.js +0 -8
- /package/{bin/util/cookies.d.ts → cookies.d.ts} +0 -0
- /package/{bin/util/cookies.js → cookies.js} +0 -0
- /package/{bin/util/css.d.ts → css.d.ts} +0 -0
- /package/{bin → internal}/cli/index.d.ts +0 -0
- /package/{bin/util → internal}/hash.d.ts +0 -0
- /package/{bin/util → internal}/hash.js +0 -0
- /package/{bin/client → internal}/mount.d.ts +0 -0
- /package/{bin/util → util}/path-builder.d.ts +0 -0
package/bin/client/index.d.ts
DELETED
package/bin/client/index.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Builds the SSR and client side mounter for client components
|
|
3
|
-
*/
|
|
4
|
-
import { readFile, writeFile } from "fs/promises";
|
|
5
|
-
import { init, parse } from "es-module-lexer";
|
|
6
|
-
import { QuickHash } from "../util/hash.js";
|
|
7
|
-
import { CutString } from "../helper.js";
|
|
8
|
-
const pivot = `\n// DO NOT EDIT BELOW THIS LINE\n`;
|
|
9
|
-
export async function GenerateClient(config, force = false) {
|
|
10
|
-
const file = await readFile(config.source, "utf8");
|
|
11
|
-
const [source, history] = CutString(file, pivot);
|
|
12
|
-
const hash = QuickHash(source);
|
|
13
|
-
if (!force && ExtractHash(history) === hash)
|
|
14
|
-
return;
|
|
15
|
-
await init;
|
|
16
|
-
const imported = ParseImports(source);
|
|
17
|
-
await Promise.all([
|
|
18
|
-
writeFile(config.source, source
|
|
19
|
-
+ pivot
|
|
20
|
-
+ `// hash: ${hash}\n`
|
|
21
|
-
+ BuildClientServer(imported)),
|
|
22
|
-
writeFile(CutString(config.source, ".", -1)[0] + ".manifest.tsx", BuildClientManifest(config.adapter, imported))
|
|
23
|
-
]);
|
|
24
|
-
}
|
|
25
|
-
function ParseImports(source) {
|
|
26
|
-
const parsed = parse(source)[0];
|
|
27
|
-
const out = [];
|
|
28
|
-
for (const imported of parsed) {
|
|
29
|
-
if (imported.a !== -1)
|
|
30
|
-
continue;
|
|
31
|
-
if (imported.t !== 1)
|
|
32
|
-
continue;
|
|
33
|
-
const href = source.slice(imported.s, imported.e);
|
|
34
|
-
const front = source.slice(imported.ss, imported.s);
|
|
35
|
-
const start = front.indexOf("{");
|
|
36
|
-
if (start === -1) {
|
|
37
|
-
const middle = CutString(CutString(front, "import")[1], "from", -1)[0];
|
|
38
|
-
out.push({ mapping: ExtractName(middle), href });
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
const end = front.lastIndexOf("}");
|
|
42
|
-
const segments = front.slice(start + 1, end).split(",");
|
|
43
|
-
out.push({ mapping: segments.map(ExtractName), href });
|
|
44
|
-
}
|
|
45
|
-
return out;
|
|
46
|
-
}
|
|
47
|
-
function BuildClientServer(imported) {
|
|
48
|
-
const names = new Array();
|
|
49
|
-
for (const imp of imported) {
|
|
50
|
-
if (Array.isArray(imp.mapping))
|
|
51
|
-
names.push(...imp.mapping.map(x => x.name));
|
|
52
|
-
else
|
|
53
|
-
names.push(imp.mapping.name);
|
|
54
|
-
}
|
|
55
|
-
let out = `import { StyleClass } from "htmx-router";\n`
|
|
56
|
-
+ `const island = new StyleClass("i", ".this{display:contents;}\\n").name;\n\n`
|
|
57
|
-
+ "type FirstArg<T> = T extends (arg: infer U, ...args: any[]) => any ? U : never;\n"
|
|
58
|
-
+ "function mount(name: string, data: string, ssr?: JSX.Element) {\n"
|
|
59
|
-
+ "\treturn (<>\n"
|
|
60
|
-
+ `\t\t<div className={island}>{ssr}</div>\n`
|
|
61
|
-
+ "\t\t<script>{`Router.mountAboveWith('${name}', ${data})`}</script>\n"
|
|
62
|
-
+ "\t</>);\n"
|
|
63
|
-
+ "}\n"
|
|
64
|
-
+ "\n"
|
|
65
|
-
+ "const Client = {\n";
|
|
66
|
-
for (const name of names) {
|
|
67
|
-
out += `\t${name}: function(props: FirstArg<typeof ${name}> & { children?: JSX.Element }) {\n`
|
|
68
|
-
+ `\t\tconst { children, ...rest } = props;\n`
|
|
69
|
-
+ `\t\treturn mount("${name}", JSON.stringify(rest), children);\n`
|
|
70
|
-
+ `\t},\n`;
|
|
71
|
-
}
|
|
72
|
-
out += "}\nexport default Client;\n\n"
|
|
73
|
-
+ `import { __RebuildClient__ } from "htmx-router/bin/client/watch.js";\n`
|
|
74
|
-
+ `__RebuildClient__();`;
|
|
75
|
-
return out;
|
|
76
|
-
}
|
|
77
|
-
const renderer = {
|
|
78
|
-
react: '\t\tconst r = await import("react-dom/client");\n'
|
|
79
|
-
+ "\t\tr.createRoot(element).render(<C {...props} />);\n"
|
|
80
|
-
};
|
|
81
|
-
function BuildClientManifest(type, imports) {
|
|
82
|
-
let out = "/*------------------------------------------\n"
|
|
83
|
-
+ " * Generated by htmx-router *\n"
|
|
84
|
-
+ " * Warn: Any changes will be overwritten *\n"
|
|
85
|
-
+ "-------------------------------------------*/\n\n"
|
|
86
|
-
+ "/* eslint-disable @typescript-eslint/no-explicit-any */\n"
|
|
87
|
-
+ "const client = {\n";
|
|
88
|
-
const render = renderer[type];
|
|
89
|
-
if (!render) {
|
|
90
|
-
console.error(`Unsupported client adapter ${type}`);
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
for (const imported of imports) {
|
|
94
|
-
if (Array.isArray(imported.mapping)) {
|
|
95
|
-
for (const map of imported.mapping) {
|
|
96
|
-
out += `\t${map.name}: async (element: HTMLElement, props: any) => {\n`
|
|
97
|
-
+ `\t\tconst C = (await import("${imported.href}")).${map.original};\n`
|
|
98
|
-
+ render
|
|
99
|
-
+ `\t},\n`;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
out += `\t${imported.mapping.name}: async (element: HTMLElement, props: any) => {\n`
|
|
104
|
-
+ `\t\tconst C = (await import("${imported.href}")).default;\n`
|
|
105
|
-
+ render
|
|
106
|
-
+ `\t},\n`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
out += "}\nexport default client;\n"
|
|
110
|
-
+ "(window as any).CLIENT = client;";
|
|
111
|
-
return out;
|
|
112
|
-
}
|
|
113
|
-
function ExtractName(str) {
|
|
114
|
-
const parts = CutString(str, "as");
|
|
115
|
-
if (parts[1].length !== 0)
|
|
116
|
-
return { name: parts[1].trim(), original: parts[0].trim() };
|
|
117
|
-
const name = parts[0].trim();
|
|
118
|
-
return { name, original: name };
|
|
119
|
-
}
|
|
120
|
-
function ExtractHash(source) {
|
|
121
|
-
const regex = /\/\/\s+hash\s*:\s*(\w+)/;
|
|
122
|
-
const match = source.match(regex);
|
|
123
|
-
if (match)
|
|
124
|
-
return match[1] || "";
|
|
125
|
-
return "";
|
|
126
|
-
}
|
package/bin/client/watch.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function __RebuildClient__(): Promise<void>;
|
package/bin/client/watch.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { GenerateClient } from "../client/index.js";
|
|
2
|
-
import { ReadConfig } from "../cli/config.js";
|
|
3
|
-
export async function __RebuildClient__() {
|
|
4
|
-
if (process.env.NODE_ENV === "production")
|
|
5
|
-
return;
|
|
6
|
-
const config = await ReadConfig();
|
|
7
|
-
const client = config.client;
|
|
8
|
-
if (!client)
|
|
9
|
-
return;
|
|
10
|
-
GenerateClient(client, false).catch(console.error);
|
|
11
|
-
}
|
package/bin/index.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { RouteModule, CatchFunction, RenderFunction } from './types.js';
|
|
2
|
-
import { RouteContext, GenericContext } from "./router.js";
|
|
3
|
-
import { createRequestHandler } from './request/index.js';
|
|
4
|
-
import { Cookies, CookieOptions } from "./util/cookies.js";
|
|
5
|
-
import { EventSourceConnection } from "./util/event-source.js";
|
|
6
|
-
import { StyleClass } from './util/css.js';
|
|
7
|
-
import { Endpoint } from './util/endpoint.js';
|
|
8
|
-
import { redirect, text, json, refresh } from './response.js';
|
|
9
|
-
export { CatchFunction, CookieOptions, Cookies, createRequestHandler, Endpoint, EventSourceConnection, GenericContext, RenderFunction, RouteContext, RouteModule, StyleClass, redirect, text, json, refresh };
|
package/bin/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { RouteContext, GenericContext } from "./router.js";
|
|
2
|
-
import { createRequestHandler } from './request/index.js';
|
|
3
|
-
import { Cookies } from "./util/cookies.js";
|
|
4
|
-
import { EventSourceConnection } from "./util/event-source.js";
|
|
5
|
-
import { StyleClass } from './util/css.js';
|
|
6
|
-
import { Endpoint } from './util/endpoint.js';
|
|
7
|
-
import { redirect, text, json, refresh } from './response.js';
|
|
8
|
-
export { Cookies, createRequestHandler, Endpoint, EventSourceConnection, GenericContext, RouteContext, StyleClass, redirect, text, json, refresh };
|
package/bin/request/index.js
DELETED
package/bin/response.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare function redirect(url: string, init?: ResponseInit): Response;
|
|
2
|
-
export declare function text(text: string, init?: ResponseInit): Response;
|
|
3
|
-
export declare function json(data: unknown, init?: ResponseInit): Response;
|
|
4
|
-
export declare function refresh(init?: ResponseInit): Response;
|
package/bin/types.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ParameterShaper } from "./util/parameters.js";
|
|
2
|
-
import { RouteContext } from "./router.js";
|
|
3
|
-
export type CatchFunction<T> = (args: T, err: unknown) => Promise<Response | JSX.Element>;
|
|
4
|
-
export type RenderFunction<T> = (args: T) => Promise<Response | JSX.Element | null>;
|
|
5
|
-
export type RouteModule<T extends ParameterShaper> = {
|
|
6
|
-
parameters?: T;
|
|
7
|
-
loader?: RenderFunction<RouteContext<T>>;
|
|
8
|
-
action?: RenderFunction<RouteContext<T>>;
|
|
9
|
-
error?: CatchFunction<RouteContext<T>>;
|
|
10
|
-
};
|
package/bin/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/bin/util/dynamic.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This whole file is only for internal use but the generated router for the <Dynamic> component
|
|
3
|
-
*/
|
|
4
|
-
import { GenericContext } from "../router.js";
|
|
5
|
-
export declare function RegisterDynamic<T>(load: Loader<T>): string;
|
|
6
|
-
type Loader<T> = (params: T, ctx: GenericContext) => Promise<JSX.Element>;
|
|
7
|
-
export declare function _resolve(fragments: string[], ctx: GenericContext): Promise<Response | null>;
|
|
8
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper for Server-Sent-Events, with auto close on SIGTERM and SIGHUP messages
|
|
3
|
-
* Includes a keep alive empty packet sent every 30sec (because Chrome implodes at 120sec, and can be unreliable at 60sec)
|
|
4
|
-
*/
|
|
5
|
-
export declare class EventSourceConnection {
|
|
6
|
-
private controller;
|
|
7
|
-
private stream;
|
|
8
|
-
private timer;
|
|
9
|
-
readonly createdAt: number;
|
|
10
|
-
constructor(request: Request, keepAlive?: number);
|
|
11
|
-
response(): Response;
|
|
12
|
-
private keepAlive;
|
|
13
|
-
send(type: string, data: string, timeStamp: number): boolean;
|
|
14
|
-
isClosed(): boolean;
|
|
15
|
-
close(unlink?: boolean): boolean;
|
|
16
|
-
}
|
package/bin/util/event-source.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper for Server-Sent-Events, with auto close on SIGTERM and SIGHUP messages
|
|
3
|
-
* Includes a keep alive empty packet sent every 30sec (because Chrome implodes at 120sec, and can be unreliable at 60sec)
|
|
4
|
-
*/
|
|
5
|
-
export class EventSourceConnection {
|
|
6
|
-
controller;
|
|
7
|
-
stream;
|
|
8
|
-
timer;
|
|
9
|
-
createdAt; // unix time
|
|
10
|
-
constructor(request, keepAlive = 30_000) {
|
|
11
|
-
this.createdAt = Date.now();
|
|
12
|
-
this.controller = null;
|
|
13
|
-
this.stream = new ReadableStream({
|
|
14
|
-
start: (c) => { this.controller = c; },
|
|
15
|
-
cancel: () => { this.close(); }
|
|
16
|
-
});
|
|
17
|
-
request.signal.addEventListener('abort', () => this.close());
|
|
18
|
-
this.timer = setInterval(() => this.keepAlive(), keepAlive);
|
|
19
|
-
register.push(this);
|
|
20
|
-
}
|
|
21
|
-
response() {
|
|
22
|
-
const headers = new Headers();
|
|
23
|
-
headers.set("Content-Type", "text/event-stream");
|
|
24
|
-
headers.set("Transfer-Encoding", "chunked");
|
|
25
|
-
headers.set("Connection", "keep-alive");
|
|
26
|
-
headers.set("Keep-Alive", `timeout=120`);
|
|
27
|
-
return new Response(this.stream, { headers });
|
|
28
|
-
}
|
|
29
|
-
keepAlive() {
|
|
30
|
-
if (!this.controller)
|
|
31
|
-
return;
|
|
32
|
-
try {
|
|
33
|
-
this.controller.enqueue("\n\n");
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
console.error(e);
|
|
37
|
-
this.close(); // unbind on failure
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
send(type, data, timeStamp) {
|
|
41
|
-
if (!this.controller)
|
|
42
|
-
return false;
|
|
43
|
-
try {
|
|
44
|
-
this.controller.enqueue(`event: ${type}\ndata: [${data},${timeStamp}]\n\n`);
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
console.error(e);
|
|
49
|
-
this.close(); // unbind on failure
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
isClosed() {
|
|
54
|
-
return this.controller === null;
|
|
55
|
-
}
|
|
56
|
-
close(unlink = true) {
|
|
57
|
-
clearInterval(this.timer);
|
|
58
|
-
if (!this.controller)
|
|
59
|
-
return false;
|
|
60
|
-
if (unlink) {
|
|
61
|
-
const i = register.indexOf(this);
|
|
62
|
-
if (i !== -1)
|
|
63
|
-
register.splice(i, 1);
|
|
64
|
-
}
|
|
65
|
-
try {
|
|
66
|
-
this.controller?.close();
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
console.error(e);
|
|
70
|
-
this.controller = null;
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
this.controller = null;
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// Auto close all SSE streams when shutdown requested
|
|
78
|
-
// Without this graceful shutdowns will hang indefinitely
|
|
79
|
-
const register = new Array();
|
|
80
|
-
function CloseAll() {
|
|
81
|
-
for (const connection of register)
|
|
82
|
-
connection.close(false); // don't waste time unregistering
|
|
83
|
-
}
|
|
84
|
-
process.on('SIGTERM', CloseAll);
|
|
85
|
-
process.on('SIGHUP', CloseAll);
|
package/bin/util/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function MergeHeaders(base: Headers, extension: Headers, override: boolean): void;
|
package/bin/util/index.js
DELETED
package/bin/util/shell.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* These types are just helpers which could be useful
|
|
3
|
-
* But the goal is to add a feature in the future to help will shells merging meta data
|
|
4
|
-
* Currently I want more experience using the slug-shell pattern before I build it out
|
|
5
|
-
*/
|
|
6
|
-
export type MetaDescriptor = {
|
|
7
|
-
charSet: "utf-8";
|
|
8
|
-
} | {
|
|
9
|
-
title: string;
|
|
10
|
-
} | {
|
|
11
|
-
name: string;
|
|
12
|
-
content: string;
|
|
13
|
-
} | {
|
|
14
|
-
property: string;
|
|
15
|
-
content: string;
|
|
16
|
-
} | {
|
|
17
|
-
httpEquiv: string;
|
|
18
|
-
content: string;
|
|
19
|
-
} | {
|
|
20
|
-
"script:ld+json": LdJsonObject;
|
|
21
|
-
} | {
|
|
22
|
-
tagName: "meta" | "link";
|
|
23
|
-
[name: string]: string;
|
|
24
|
-
} | {
|
|
25
|
-
[name: string]: unknown;
|
|
26
|
-
};
|
|
27
|
-
export type LdJsonObject = {
|
|
28
|
-
[Key in string]?: LdJsonValue | undefined;
|
|
29
|
-
};
|
|
30
|
-
export type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[];
|
|
31
|
-
export type LdJsonPrimitive = string | number | boolean | null;
|
|
32
|
-
export type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
|
package/bin/util/shell.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* These types are just helpers which could be useful
|
|
3
|
-
* But the goal is to add a feature in the future to help will shells merging meta data
|
|
4
|
-
* Currently I want more experience using the slug-shell pattern before I build it out
|
|
5
|
-
*/
|
|
6
|
-
export {};
|
|
7
|
-
// export type ShellOptions = { meta?: Array<MetaDescriptor> } | undefined;
|
|
8
|
-
// export type ShellProps<T> = T & ShellOptions;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|