@solidjs/start 2.0.0-beta.0 → 2.0.0-beta.2
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/CHANGELOG.md +14 -0
- package/dist/config/dev-server.js +3 -1
- package/dist/config/fs-router.d.ts +1 -1
- package/dist/http/index.d.ts +4 -4
- package/package.json +11 -5
- package/scripts/build.js +0 -15
- package/scripts/validate-imports.js +0 -316
- package/src/client/StartClient.tsx +0 -34
- package/src/client/index.tsx +0 -2
- package/src/client/mount.ts +0 -1
- package/src/client/spa/index.tsx +0 -9
- package/src/config/constants.ts +0 -19
- package/src/config/dev-server.ts +0 -157
- package/src/config/env.ts +0 -105
- package/src/config/fs-router.ts +0 -162
- package/src/config/fs-routes/fs-watcher.ts +0 -66
- package/src/config/fs-routes/index.ts +0 -136
- package/src/config/fs-routes/router.ts +0 -184
- package/src/config/fs-routes/tree-shake.ts +0 -324
- package/src/config/index.ts +0 -239
- package/src/config/lazy.ts +0 -132
- package/src/config/manifest.ts +0 -120
- package/src/config/utils.ts +0 -5
- package/src/config/vite-utils.ts +0 -113
- package/src/directives/bubble-function-declaration.ts +0 -33
- package/src/directives/compile.ts +0 -54
- package/src/directives/generate-unique-name.ts +0 -22
- package/src/directives/get-descriptive-name.ts +0 -39
- package/src/directives/get-import-identifier.ts +0 -34
- package/src/directives/get-root-statement-path.ts +0 -14
- package/src/directives/index.ts +0 -233
- package/src/directives/is-statement-top-level.ts +0 -13
- package/src/directives/paths.ts +0 -63
- package/src/directives/plugin.ts +0 -389
- package/src/directives/remove-unused-variables.ts +0 -70
- package/src/directives/types.ts +0 -12
- package/src/directives/xxhash32.ts +0 -214
- package/src/env.d.ts +0 -17
- package/src/fns/client.ts +0 -141
- package/src/fns/handler.spec.ts +0 -85
- package/src/fns/handler.ts +0 -287
- package/src/fns/registration.ts +0 -19
- package/src/fns/serialization.ts +0 -250
- package/src/fns/server.ts +0 -46
- package/src/fns/shared.ts +0 -116
- package/src/http/index.ts +0 -216
- package/src/index.tsx +0 -7
- package/src/internal.d.ts +0 -14
- package/src/middleware/index.ts +0 -92
- package/src/router.tsx +0 -37
- package/src/server/StartServer.tsx +0 -58
- package/src/server/assets/PatchVirtualDevStyles.tsx +0 -31
- package/src/server/assets/index.ts +0 -70
- package/src/server/assets/render.tsx +0 -46
- package/src/server/collect-styles.ts +0 -70
- package/src/server/fetchEvent.spec.ts +0 -85
- package/src/server/fetchEvent.ts +0 -36
- package/src/server/handler.ts +0 -261
- package/src/server/index.tsx +0 -29
- package/src/server/manifest/client-manifest.ts +0 -8
- package/src/server/manifest/dev-client-manifest.ts +0 -21
- package/src/server/manifest/dev-ssr-manifest.ts +0 -23
- package/src/server/manifest/prod-client-manifest.ts +0 -21
- package/src/server/manifest/prod-ssr-manifest.ts +0 -109
- package/src/server/manifest/ssr-manifest.ts +0 -10
- package/src/server/routes.ts +0 -126
- package/src/server/spa/StartServer.tsx +0 -42
- package/src/server/spa/handler.ts +0 -29
- package/src/server/spa/index.tsx +0 -5
- package/src/server/types.ts +0 -82
- package/src/server/util.ts +0 -12
- package/src/shared/ErrorBoundary.tsx +0 -52
- package/src/shared/GET.ts +0 -8
- package/src/shared/HttpHeader.tsx +0 -42
- package/src/shared/HttpStatusCode.ts +0 -27
- package/src/shared/clientOnly.ts +0 -44
- package/src/shared/dev-overlay/CodeView.tsx +0 -90
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +0 -316
- package/src/shared/dev-overlay/createStackFrame.ts +0 -74
- package/src/shared/dev-overlay/download.ts +0 -6
- package/src/shared/dev-overlay/env.d.ts +0 -4
- package/src/shared/dev-overlay/get-source-map.ts +0 -33
- package/src/shared/dev-overlay/icons.tsx +0 -456
- package/src/shared/dev-overlay/index.tsx +0 -63
- package/src/shared/dev-overlay/styles.css +0 -292
- package/src/shared/lazy.ts +0 -52
- package/src/shared/serverFunction.ts +0 -10
- package/src/utils/debounce.ts +0 -10
- package/src/virtual.d.ts +0 -27
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -9
package/src/config/env.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { loadEnv, type Plugin } from "vite";
|
|
2
|
-
|
|
3
|
-
const LOADERS = {
|
|
4
|
-
node: `export default key => process.env[key];`,
|
|
5
|
-
"cloudflare-workers": `import { env } from 'cloudflare:workers';export default key => env[key];`,
|
|
6
|
-
"netlify-edge": `export default key => Netlify.env.get(key);`,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export interface EnvPluginOptions {
|
|
10
|
-
server?: {
|
|
11
|
-
runtime?: keyof typeof LOADERS | (string & {});
|
|
12
|
-
load?: (mode: string) => Record<string, string>;
|
|
13
|
-
prefix?: string;
|
|
14
|
-
};
|
|
15
|
-
client?: {
|
|
16
|
-
load?: (mode: string) => Record<string, string>;
|
|
17
|
-
prefix?: string;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const SERVER_ENV = "env:server";
|
|
22
|
-
const CLIENT_ENV = "env:client";
|
|
23
|
-
|
|
24
|
-
const SERVER_RUNTIME_ENV = `${SERVER_ENV}/runtime`;
|
|
25
|
-
|
|
26
|
-
const SERVER_RUNTIME_LOADER = `${SERVER_RUNTIME_ENV}/loader`;
|
|
27
|
-
|
|
28
|
-
const DEFAULT_SERVER_PREFIX = "SERVER_";
|
|
29
|
-
const DEFAULT_CLIENT_PREFIX = "CLIENT_";
|
|
30
|
-
|
|
31
|
-
const SERVER_ONLY_MODULE = `throw new Error('Attempt to load server-only environment variables in client runtime.');`;
|
|
32
|
-
|
|
33
|
-
const SERVER_RUNTIME_CODE = `import load from '${SERVER_RUNTIME_LOADER}';
|
|
34
|
-
|
|
35
|
-
export default new Proxy({}, {
|
|
36
|
-
get(_, key) {
|
|
37
|
-
return load(key);
|
|
38
|
-
},
|
|
39
|
-
})`;
|
|
40
|
-
|
|
41
|
-
function convertObjectToModule(object: Record<string, string>): string {
|
|
42
|
-
let result = "";
|
|
43
|
-
for (const key in object) {
|
|
44
|
-
result += `export const ${key} = ${JSON.stringify(object[key])};`;
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function envPlugin(options?: EnvPluginOptions): Plugin {
|
|
50
|
-
const currentOptions = options ?? {};
|
|
51
|
-
let env: string;
|
|
52
|
-
const serverPrefix = currentOptions.server?.prefix ?? DEFAULT_SERVER_PREFIX;
|
|
53
|
-
const clientPrefix = currentOptions.client?.prefix ?? DEFAULT_CLIENT_PREFIX;
|
|
54
|
-
const runtime = options?.server?.runtime ?? "node";
|
|
55
|
-
const runtimeCode = runtime in LOADERS ? LOADERS[runtime as keyof typeof LOADERS] : runtime;
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
name: "solid-start:env",
|
|
59
|
-
enforce: "pre",
|
|
60
|
-
configResolved(config) {
|
|
61
|
-
env = config.mode !== "production" ? "development" : "production";
|
|
62
|
-
},
|
|
63
|
-
resolveId(id) {
|
|
64
|
-
if (
|
|
65
|
-
id === SERVER_ENV ||
|
|
66
|
-
id === CLIENT_ENV ||
|
|
67
|
-
id === SERVER_RUNTIME_ENV ||
|
|
68
|
-
id === SERVER_RUNTIME_LOADER
|
|
69
|
-
) {
|
|
70
|
-
return id;
|
|
71
|
-
}
|
|
72
|
-
return undefined;
|
|
73
|
-
},
|
|
74
|
-
load(id, opts) {
|
|
75
|
-
if (id === SERVER_ENV) {
|
|
76
|
-
if (!opts?.ssr) {
|
|
77
|
-
return SERVER_ONLY_MODULE;
|
|
78
|
-
}
|
|
79
|
-
const vars = currentOptions.server?.load
|
|
80
|
-
? currentOptions.server.load(env)
|
|
81
|
-
: loadEnv(env, '.', serverPrefix);
|
|
82
|
-
return convertObjectToModule(vars);
|
|
83
|
-
}
|
|
84
|
-
if (id === CLIENT_ENV) {
|
|
85
|
-
const vars = currentOptions.client?.load
|
|
86
|
-
? currentOptions.client.load(env)
|
|
87
|
-
: loadEnv(env, '.', clientPrefix);
|
|
88
|
-
return convertObjectToModule(vars);
|
|
89
|
-
}
|
|
90
|
-
if (id === SERVER_RUNTIME_LOADER) {
|
|
91
|
-
if (!opts?.ssr) {
|
|
92
|
-
return SERVER_ONLY_MODULE;
|
|
93
|
-
}
|
|
94
|
-
return runtimeCode;
|
|
95
|
-
}
|
|
96
|
-
if (id === SERVER_RUNTIME_ENV) {
|
|
97
|
-
if (!opts?.ssr) {
|
|
98
|
-
return SERVER_ONLY_MODULE;
|
|
99
|
-
}
|
|
100
|
-
return SERVER_RUNTIME_CODE;
|
|
101
|
-
}
|
|
102
|
-
return undefined;
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
}
|
package/src/config/fs-router.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import type { ExportSpecifier } from "es-module-lexer";
|
|
2
|
-
import {
|
|
3
|
-
analyzeModule,
|
|
4
|
-
BaseFileSystemRouter,
|
|
5
|
-
cleanPath,
|
|
6
|
-
type FileSystemRouterConfig,
|
|
7
|
-
} from "./fs-routes/router.ts";
|
|
8
|
-
|
|
9
|
-
export class SolidStartClientFileRouter extends BaseFileSystemRouter {
|
|
10
|
-
toPath(src: string) {
|
|
11
|
-
const routePath = cleanPath(src, this.config)
|
|
12
|
-
// remove the initial slash
|
|
13
|
-
.slice(1)
|
|
14
|
-
.replace(/index$/, "")
|
|
15
|
-
.replace(/\[([^/]+)\]/g, (_, m) => {
|
|
16
|
-
if (m.length > 3 && m.startsWith("...")) {
|
|
17
|
-
return `*${m.slice(3)}`;
|
|
18
|
-
}
|
|
19
|
-
if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
|
|
20
|
-
return `:${m.slice(1, -1)}?`;
|
|
21
|
-
}
|
|
22
|
-
return `:${m}`;
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return routePath?.length > 0 ? `/${routePath}` : "/";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
toRoute(src: string) {
|
|
29
|
-
const path = this.toPath(src);
|
|
30
|
-
|
|
31
|
-
if (src.endsWith(".md") || src.endsWith(".mdx")) {
|
|
32
|
-
return {
|
|
33
|
-
page: true,
|
|
34
|
-
$component: {
|
|
35
|
-
src: src,
|
|
36
|
-
pick: ["$css"],
|
|
37
|
-
},
|
|
38
|
-
$$route: undefined,
|
|
39
|
-
path,
|
|
40
|
-
// filePath: src
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const [_, exports] = analyzeModule(src);
|
|
45
|
-
const hasDefault = !!exports.find(e => e.n === "default");
|
|
46
|
-
const hasRouteConfig = !!exports.find(e => e.n === "route");
|
|
47
|
-
if (hasDefault) {
|
|
48
|
-
return {
|
|
49
|
-
page: true,
|
|
50
|
-
$component: {
|
|
51
|
-
src: src,
|
|
52
|
-
pick: [
|
|
53
|
-
...exports.filter(e => e.n === e.ln && e.n !== "route").map(e => e.n),
|
|
54
|
-
"default",
|
|
55
|
-
"$css",
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
$$route: hasRouteConfig
|
|
59
|
-
? {
|
|
60
|
-
src: src,
|
|
61
|
-
pick: ["route"],
|
|
62
|
-
}
|
|
63
|
-
: undefined,
|
|
64
|
-
path,
|
|
65
|
-
// filePath: src
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
|
|
72
|
-
function createHTTPHandlers(src: string, exports: readonly ExportSpecifier[]) {
|
|
73
|
-
const handlers: Record<string, any> = {};
|
|
74
|
-
for (const exp of exports) {
|
|
75
|
-
if (HTTP_METHODS.includes(exp.n)) {
|
|
76
|
-
handlers[`$${exp.n}`] = {
|
|
77
|
-
src: src,
|
|
78
|
-
pick: [exp.n],
|
|
79
|
-
};
|
|
80
|
-
if (exp.n === "GET" && !exports.find(exp => exp.n === "HEAD")) {
|
|
81
|
-
handlers.$HEAD = {
|
|
82
|
-
src: src,
|
|
83
|
-
pick: [exp.n],
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return handlers;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
93
|
-
declare config: FileSystemRouterConfig & { dataOnly?: boolean };
|
|
94
|
-
|
|
95
|
-
constructor(config: FileSystemRouterConfig & { dataOnly?: boolean }) {
|
|
96
|
-
super(config);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
toPath(src: string) {
|
|
100
|
-
const routePath = cleanPath(src, this.config)
|
|
101
|
-
// remove the initial slash
|
|
102
|
-
.slice(1)
|
|
103
|
-
.replace(/index$/, "")
|
|
104
|
-
.replace(/\[([^/]+)\]/g, (_, m) => {
|
|
105
|
-
if (m.length > 3 && m.startsWith("...")) {
|
|
106
|
-
return `*${m.slice(3)}`;
|
|
107
|
-
}
|
|
108
|
-
if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
|
|
109
|
-
return `:${m.slice(1, -1)}?`;
|
|
110
|
-
}
|
|
111
|
-
return `:${m}`;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return routePath?.length > 0 ? `/${routePath}` : "/";
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
toRoute(src: string) {
|
|
118
|
-
const path = this.toPath(src);
|
|
119
|
-
if (src.endsWith(".md") || src.endsWith(".mdx")) {
|
|
120
|
-
return {
|
|
121
|
-
page: true,
|
|
122
|
-
$component: {
|
|
123
|
-
src: src,
|
|
124
|
-
pick: ["$css"],
|
|
125
|
-
},
|
|
126
|
-
$$route: undefined,
|
|
127
|
-
path,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const [_, exports] = analyzeModule(src);
|
|
132
|
-
const hasRouteConfig = exports.find(e => e.n === "route");
|
|
133
|
-
const hasDefault = !!exports.find(e => e.n === "default");
|
|
134
|
-
const hasAPIRoutes = !!exports.find(exp => HTTP_METHODS.includes(exp.n));
|
|
135
|
-
if (hasDefault || hasAPIRoutes) {
|
|
136
|
-
return {
|
|
137
|
-
page: hasDefault,
|
|
138
|
-
$component:
|
|
139
|
-
!this.config.dataOnly && hasDefault
|
|
140
|
-
? {
|
|
141
|
-
src: src,
|
|
142
|
-
pick: [
|
|
143
|
-
...exports
|
|
144
|
-
.filter(e => e.n === e.ln && e.n !== "route" && !HTTP_METHODS.includes(e.n))
|
|
145
|
-
.map(e => e.n),
|
|
146
|
-
"default",
|
|
147
|
-
"$css",
|
|
148
|
-
],
|
|
149
|
-
}
|
|
150
|
-
: undefined,
|
|
151
|
-
$$route: hasRouteConfig
|
|
152
|
-
? {
|
|
153
|
-
src: src,
|
|
154
|
-
pick: ["route"],
|
|
155
|
-
}
|
|
156
|
-
: undefined,
|
|
157
|
-
...createHTTPHandlers(src, exports),
|
|
158
|
-
path,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import type { EnvironmentModuleNode, FSWatcher, PluginOption, ViteDevServer } from "vite";
|
|
2
|
-
import { debounce } from "../../utils/debounce.ts";
|
|
3
|
-
import { VITE_ENVIRONMENTS } from "../constants.ts";
|
|
4
|
-
import { moduleId } from "./index.ts";
|
|
5
|
-
import type { BaseFileSystemRouter } from "./router.ts";
|
|
6
|
-
|
|
7
|
-
function setupWatcher(watcher: FSWatcher, routes: BaseFileSystemRouter): void {
|
|
8
|
-
watcher.on("unlink", path => routes.removeRoute(path));
|
|
9
|
-
watcher.on("add", path => routes.addRoute(path));
|
|
10
|
-
watcher.on("change", path => routes.updateRoute(path));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function createRoutesReloader(
|
|
14
|
-
server: ViteDevServer,
|
|
15
|
-
routes: BaseFileSystemRouter,
|
|
16
|
-
environment: "client" | "ssr",
|
|
17
|
-
) {
|
|
18
|
-
const devEnv = server.environments[environment]!;
|
|
19
|
-
if (!devEnv?.moduleGraph) return;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Debounce catches multiple route changes in a row
|
|
23
|
-
* Short timeout for inexpensive invalidations
|
|
24
|
-
*/
|
|
25
|
-
const invalidateModule = debounce((mod: EnvironmentModuleNode) => {
|
|
26
|
-
devEnv.moduleGraph.invalidateModule(mod);
|
|
27
|
-
}, 0);
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Long debounce timeout for expensive reloads
|
|
31
|
-
*/
|
|
32
|
-
const reloadModule = debounce((mod: EnvironmentModuleNode) => {
|
|
33
|
-
devEnv.reloadModule(mod);
|
|
34
|
-
}, 200);
|
|
35
|
-
|
|
36
|
-
return routes.on("reload", function handleRoutesReload(evt): void {
|
|
37
|
-
const mod = devEnv.moduleGraph.getModuleById(moduleId)!;
|
|
38
|
-
if (!mod) {
|
|
39
|
-
devEnv.hot.send({ type: "full-reload" });
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (environment === VITE_ENVIRONMENTS.client && evt.detail.type !== "update") {
|
|
44
|
-
// Client has to be reloaded when routes are added or removed
|
|
45
|
-
reloadModule(mod);
|
|
46
|
-
} else {
|
|
47
|
-
invalidateModule(mod);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const fileSystemWatcher = (
|
|
53
|
-
routers: Record<"client" | "ssr", BaseFileSystemRouter>,
|
|
54
|
-
): PluginOption => {
|
|
55
|
-
const plugin: PluginOption = {
|
|
56
|
-
name: "fs-watcher",
|
|
57
|
-
async configureServer(server: ViteDevServer) {
|
|
58
|
-
for (const environment of [VITE_ENVIRONMENTS.server, VITE_ENVIRONMENTS.client]) {
|
|
59
|
-
const router = routers[environment];
|
|
60
|
-
setupWatcher(server.watcher, router);
|
|
61
|
-
createRoutesReloader(server, router, environment);
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
return plugin;
|
|
66
|
-
};
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { relative } from "node:path";
|
|
2
|
-
import { type PluginOption } from "vite";
|
|
3
|
-
|
|
4
|
-
import { fileSystemWatcher } from "./fs-watcher.ts";
|
|
5
|
-
import type { BaseFileSystemRouter } from "./router.ts";
|
|
6
|
-
import { treeShake } from "./tree-shake.ts";
|
|
7
|
-
|
|
8
|
-
export const moduleId = "solid-start:routes";
|
|
9
|
-
|
|
10
|
-
export interface FsRoutesArgs {
|
|
11
|
-
routers: Record<"client" | "ssr", BaseFileSystemRouter>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function fsRoutes({ routers }: FsRoutesArgs): Array<PluginOption> {
|
|
15
|
-
(globalThis as any).ROUTERS = routers;
|
|
16
|
-
|
|
17
|
-
return [
|
|
18
|
-
{
|
|
19
|
-
name: "solid-start-fs-routes",
|
|
20
|
-
enforce: "pre",
|
|
21
|
-
resolveId(id) {
|
|
22
|
-
if (id === moduleId) return id;
|
|
23
|
-
},
|
|
24
|
-
async load(id) {
|
|
25
|
-
const root = this.environment.config.root;
|
|
26
|
-
const isBuild = this.environment.mode === "build";
|
|
27
|
-
|
|
28
|
-
if (id !== moduleId) return;
|
|
29
|
-
const js = jsCode();
|
|
30
|
-
|
|
31
|
-
const router = (globalThis as any).ROUTERS[this.environment.name];
|
|
32
|
-
|
|
33
|
-
const routes = await router.getRoutes();
|
|
34
|
-
|
|
35
|
-
let routesCode = JSON.stringify(routes ?? [], (k, v) => {
|
|
36
|
-
if (v === undefined) return undefined;
|
|
37
|
-
|
|
38
|
-
if (k.startsWith("$$")) {
|
|
39
|
-
const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @type {{ [key: string]: string }}
|
|
43
|
-
*/
|
|
44
|
-
const refs: Record<string, string> = {};
|
|
45
|
-
for (var pick of v.pick) {
|
|
46
|
-
refs[pick] = js.addNamedImport(pick, buildId);
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
require: `_$() => ({ ${Object.entries(refs)
|
|
50
|
-
.map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
|
|
51
|
-
.join(", ")} })$_`,
|
|
52
|
-
// src: isBuild ? relative(root, buildId) : buildId
|
|
53
|
-
};
|
|
54
|
-
} else if (k.startsWith("$")) {
|
|
55
|
-
const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
|
|
56
|
-
return {
|
|
57
|
-
src: relative(root, buildId),
|
|
58
|
-
build: isBuild ? `_$() => import('${buildId}')$_` : undefined,
|
|
59
|
-
import: `_$() => import('${buildId}')$_`,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return v;
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
|
|
66
|
-
|
|
67
|
-
const code = `
|
|
68
|
-
${js.getImportStatements()}
|
|
69
|
-
export default ${routesCode}`;
|
|
70
|
-
return code;
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
treeShake(),
|
|
74
|
-
fileSystemWatcher(routers),
|
|
75
|
-
];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function jsCode() {
|
|
79
|
-
const imports = new Map();
|
|
80
|
-
let vars = 0;
|
|
81
|
-
|
|
82
|
-
function addImport(p: any) {
|
|
83
|
-
let id = imports.get(p);
|
|
84
|
-
if (!id) {
|
|
85
|
-
id = {};
|
|
86
|
-
imports.set(p, id);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const d = "routeData" + vars++;
|
|
90
|
-
id["default"] = d;
|
|
91
|
-
return d;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function addNamedImport(name: string | number, p: any) {
|
|
95
|
-
let id = imports.get(p);
|
|
96
|
-
if (!id) {
|
|
97
|
-
id = {};
|
|
98
|
-
imports.set(p, id);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const d = "routeData" + vars++;
|
|
102
|
-
id[name] = d;
|
|
103
|
-
return d;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const getNamedExport = (p: any) => {
|
|
107
|
-
const id = imports.get(p);
|
|
108
|
-
|
|
109
|
-
delete id["default"];
|
|
110
|
-
|
|
111
|
-
return Object.keys(id).length > 0
|
|
112
|
-
? `{ ${Object.keys(id)
|
|
113
|
-
.map(k => `${k} as ${id[k]}`)
|
|
114
|
-
.join(", ")} }`
|
|
115
|
-
: "";
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const getImportStatements = () => {
|
|
119
|
-
return `${[...imports.keys()]
|
|
120
|
-
.map(
|
|
121
|
-
i =>
|
|
122
|
-
`import ${
|
|
123
|
-
imports.get(i).default
|
|
124
|
-
? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
|
|
125
|
-
: ""
|
|
126
|
-
} ${getNamedExport(i)} from '${i}';`,
|
|
127
|
-
)
|
|
128
|
-
.join("\n")}`;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
addImport,
|
|
133
|
-
addNamedImport,
|
|
134
|
-
getImportStatements,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import { init, parse } from "es-module-lexer";
|
|
2
|
-
import esbuild from "esbuild";
|
|
3
|
-
import fg from "fast-glob";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import micromatch from "micromatch";
|
|
6
|
-
import { posix } from "node:path";
|
|
7
|
-
import { pathToRegexp } from "path-to-regexp";
|
|
8
|
-
|
|
9
|
-
import { normalizePath } from "vite";
|
|
10
|
-
|
|
11
|
-
export { pathToRegexp };
|
|
12
|
-
|
|
13
|
-
export const glob = (path: string) => fg.sync(path, { absolute: true });
|
|
14
|
-
|
|
15
|
-
export type FileSystemRouterConfig = { dir: string; extensions: string[] };
|
|
16
|
-
type Route = { path: string } & Record<string, any>;
|
|
17
|
-
|
|
18
|
-
export function cleanPath(src: string, config: FileSystemRouterConfig) {
|
|
19
|
-
return src
|
|
20
|
-
.slice(config.dir.length)
|
|
21
|
-
.replace(new RegExp(`\.(${(config.extensions ?? []).join("|")})$`), "");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function analyzeModule(src: string) {
|
|
25
|
-
return parse(
|
|
26
|
-
esbuild.transformSync(fs.readFileSync(src, "utf-8"), {
|
|
27
|
-
jsx: "transform",
|
|
28
|
-
format: "esm",
|
|
29
|
-
loader: "tsx",
|
|
30
|
-
}).code,
|
|
31
|
-
src,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type RouterEvent = CustomEvent<{ route: string; type: "update" | "remove" | "add" }>;
|
|
36
|
-
|
|
37
|
-
export class BaseFileSystemRouter extends EventTarget {
|
|
38
|
-
routes: Route[];
|
|
39
|
-
|
|
40
|
-
config: FileSystemRouterConfig;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @param {} config
|
|
45
|
-
*/
|
|
46
|
-
constructor(config: FileSystemRouterConfig) {
|
|
47
|
-
super();
|
|
48
|
-
this.routes = [];
|
|
49
|
-
this.config = config;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
glob() {
|
|
53
|
-
return (
|
|
54
|
-
posix.join(fg.convertPathToPattern(this.config.dir), "**/*") +
|
|
55
|
-
`.{${this.config.extensions.join(",")}}`
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async buildRoutes(): Promise<any[]> {
|
|
60
|
-
await init;
|
|
61
|
-
for (var src of glob(this.glob())) {
|
|
62
|
-
await this.addRoute(src);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return this.routes;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
isRoute(src: string) {
|
|
69
|
-
return Boolean(micromatch(src as any, this.glob())?.length);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
toPath(src: string) {
|
|
73
|
-
throw new Error("Not implemented");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
toRoute(src: string): Route | undefined {
|
|
77
|
-
let path = this.toPath(src);
|
|
78
|
-
|
|
79
|
-
if (path === undefined) return;
|
|
80
|
-
|
|
81
|
-
const [_, exports] = analyzeModule(src);
|
|
82
|
-
|
|
83
|
-
if (!exports.find(e => e.n === "default")) {
|
|
84
|
-
console.warn("No default export", src);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
$component: {
|
|
89
|
-
src: src,
|
|
90
|
-
pick: ["default", "$css"],
|
|
91
|
-
},
|
|
92
|
-
path,
|
|
93
|
-
// filePath: src
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* To be attached by vite plugin to the vite dev server
|
|
99
|
-
*/
|
|
100
|
-
update = undefined;
|
|
101
|
-
|
|
102
|
-
_addRoute(route: Route) {
|
|
103
|
-
const idx = this.routes.findIndex(r => r.path === route.path);
|
|
104
|
-
if (idx >= 0) this.routes.splice(idx, 1);
|
|
105
|
-
this.routes.push(route);
|
|
106
|
-
|
|
107
|
-
return idx >= 0;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async addRoute(src: string) {
|
|
111
|
-
src = normalizePath(src);
|
|
112
|
-
if (this.isRoute(src)) {
|
|
113
|
-
try {
|
|
114
|
-
const route = this.toRoute(src);
|
|
115
|
-
if (route) {
|
|
116
|
-
this._addRoute(route);
|
|
117
|
-
this.reload(route.path, "add");
|
|
118
|
-
}
|
|
119
|
-
} catch (e) {
|
|
120
|
-
console.error(e);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
reload(route: string, type: "update" | "remove" | "add") {
|
|
126
|
-
this.dispatchEvent(
|
|
127
|
-
new CustomEvent("reload", {
|
|
128
|
-
detail: {
|
|
129
|
-
route,
|
|
130
|
-
type,
|
|
131
|
-
},
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async updateRoute(src_: string) {
|
|
137
|
-
const src = normalizePath(src_);
|
|
138
|
-
if (this.isRoute(src)) {
|
|
139
|
-
try {
|
|
140
|
-
const route = this.toRoute(src);
|
|
141
|
-
if (route) {
|
|
142
|
-
const updated = this._addRoute(route);
|
|
143
|
-
this.reload(route.path, updated ? "update" : "add");
|
|
144
|
-
} else {
|
|
145
|
-
this.removeRoute(src_);
|
|
146
|
-
}
|
|
147
|
-
} catch (e) {
|
|
148
|
-
console.error(e);
|
|
149
|
-
}
|
|
150
|
-
// this.update?.();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
removeRoute(src: string) {
|
|
155
|
-
src = normalizePath(src);
|
|
156
|
-
if (this.isRoute(src)) {
|
|
157
|
-
const path = this.toPath(src);
|
|
158
|
-
if (path === undefined) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const idx = this.routes.findIndex(r => r.path === path);
|
|
163
|
-
if (idx === -1) return;
|
|
164
|
-
|
|
165
|
-
this.routes.splice(idx, 1);
|
|
166
|
-
this.reload(path, "remove");
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
on(type: string, cb: (evt: RouterEvent) => void) {
|
|
171
|
-
this.addEventListener(type, cb as any);
|
|
172
|
-
return () => this.removeEventListener(type, cb as any);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
buildRoutesPromise?: Promise<any[]>;
|
|
176
|
-
|
|
177
|
-
async getRoutes() {
|
|
178
|
-
if (!this.buildRoutesPromise) {
|
|
179
|
-
this.buildRoutesPromise = this.buildRoutes();
|
|
180
|
-
}
|
|
181
|
-
await this.buildRoutesPromise;
|
|
182
|
-
return this.routes;
|
|
183
|
-
}
|
|
184
|
-
}
|