@solidjs/start 2.0.0-beta.1 → 2.0.0-beta.10

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.
Files changed (238) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/client/StartClient.d.ts +7 -0
  3. package/{src/client/StartClient.tsx → dist/client/StartClient.jsx} +7 -15
  4. package/dist/client/index.jsx +2 -0
  5. package/dist/client/mount.d.ts +1 -0
  6. package/dist/client/mount.js +1 -0
  7. package/dist/client/spa/index.d.ts +4 -0
  8. package/dist/client/spa/index.jsx +5 -0
  9. package/dist/config/boundary-modules.d.ts +14 -0
  10. package/dist/config/boundary-modules.js +41 -0
  11. package/dist/config/constants.d.ts +16 -0
  12. package/dist/config/constants.js +16 -0
  13. package/dist/config/dev-server.d.ts +4 -0
  14. package/dist/config/dev-server.js +146 -0
  15. package/dist/config/env.d.ts +19 -0
  16. package/dist/config/env.js +85 -0
  17. package/dist/config/fs-router.d.ts +37 -0
  18. package/dist/config/fs-router.js +148 -0
  19. package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
  20. package/dist/config/fs-routes/fs-watcher.js +53 -0
  21. package/dist/config/fs-routes/index.d.ts +7 -0
  22. package/dist/config/fs-routes/index.js +107 -0
  23. package/dist/config/fs-routes/router.d.ts +43 -0
  24. package/dist/config/fs-routes/router.js +146 -0
  25. package/dist/config/fs-routes/tree-shake.d.ts +2 -0
  26. package/dist/config/fs-routes/tree-shake.js +305 -0
  27. package/dist/config/index.d.ts +25 -0
  28. package/dist/config/index.js +252 -0
  29. package/dist/config/lazy.d.ts +3 -0
  30. package/dist/config/lazy.js +114 -0
  31. package/dist/config/manifest.d.ts +3 -0
  32. package/dist/config/manifest.js +109 -0
  33. package/dist/config/utils.d.ts +4 -0
  34. package/dist/config/utils.js +6 -0
  35. package/dist/config/vite-utils.d.ts +21 -0
  36. package/dist/config/vite-utils.js +85 -0
  37. package/dist/directives/bubble-function-declaration.d.ts +3 -0
  38. package/dist/directives/bubble-function-declaration.js +23 -0
  39. package/dist/directives/compile.d.ts +9 -0
  40. package/dist/directives/compile.js +40 -0
  41. package/dist/directives/generate-unique-name.d.ts +3 -0
  42. package/dist/directives/generate-unique-name.js +16 -0
  43. package/dist/directives/get-descriptive-name.d.ts +2 -0
  44. package/dist/directives/get-descriptive-name.js +37 -0
  45. package/dist/directives/get-import-identifier.d.ts +4 -0
  46. package/dist/directives/get-import-identifier.js +19 -0
  47. package/dist/directives/get-root-statement-path.d.ts +2 -0
  48. package/dist/directives/get-root-statement-path.js +12 -0
  49. package/dist/directives/index.d.ts +14 -0
  50. package/dist/directives/index.js +202 -0
  51. package/dist/directives/is-statement-top-level.d.ts +3 -0
  52. package/dist/directives/is-statement-top-level.js +9 -0
  53. package/dist/directives/paths.d.ts +9 -0
  54. package/dist/directives/paths.js +36 -0
  55. package/dist/directives/plugin.d.ts +21 -0
  56. package/dist/directives/plugin.js +302 -0
  57. package/dist/directives/remove-unused-variables.d.ts +3 -0
  58. package/dist/directives/remove-unused-variables.js +66 -0
  59. package/{src/directives/types.ts → dist/directives/types.d.ts} +5 -7
  60. package/dist/directives/types.js +1 -0
  61. package/dist/directives/xxhash32.d.ts +6 -0
  62. package/dist/directives/xxhash32.js +193 -0
  63. package/dist/fns/client.d.ts +3 -0
  64. package/dist/fns/client.js +106 -0
  65. package/dist/fns/handler.d.ts +5 -0
  66. package/dist/fns/handler.js +305 -0
  67. package/dist/fns/registration.d.ts +3 -0
  68. package/dist/fns/registration.js +15 -0
  69. package/dist/fns/serialization.d.ts +6 -0
  70. package/dist/fns/serialization.js +208 -0
  71. package/dist/fns/server.d.ts +7 -0
  72. package/dist/fns/server.js +38 -0
  73. package/dist/fns/shared.d.ts +17 -0
  74. package/dist/fns/shared.js +105 -0
  75. package/dist/http/http.d.ts +81 -0
  76. package/dist/http/http.js +129 -0
  77. package/dist/http/index.d.ts +2 -0
  78. package/dist/http/index.js +6 -0
  79. package/{src/index.tsx → dist/index.d.ts} +0 -2
  80. package/dist/index.jsx +6 -0
  81. package/dist/middleware/index.d.ts +39 -0
  82. package/dist/middleware/index.js +60 -0
  83. package/dist/router.d.ts +6 -0
  84. package/dist/router.jsx +29 -0
  85. package/dist/server/StartServer.d.ts +9 -0
  86. package/dist/server/StartServer.jsx +34 -0
  87. package/dist/server/assets/PatchVirtualDevStyles.d.ts +4 -0
  88. package/{src/server/assets/PatchVirtualDevStyles.tsx → dist/server/assets/PatchVirtualDevStyles.jsx} +7 -10
  89. package/dist/server/assets/index.d.ts +2 -0
  90. package/dist/server/assets/index.js +52 -0
  91. package/dist/server/assets/render.d.ts +19 -0
  92. package/dist/server/assets/render.jsx +14 -0
  93. package/dist/server/collect-styles.d.ts +3 -0
  94. package/dist/server/collect-styles.js +57 -0
  95. package/dist/server/fetchEvent.d.ts +7 -0
  96. package/dist/server/fetchEvent.js +26 -0
  97. package/dist/server/handler.d.ts +6 -0
  98. package/dist/server/handler.js +218 -0
  99. package/dist/server/index.d.ts +9 -0
  100. package/{src/server/index.tsx → dist/server/index.jsx} +4 -19
  101. package/dist/server/manifest/client-manifest.d.ts +9 -0
  102. package/dist/server/manifest/client-manifest.js +6 -0
  103. package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
  104. package/dist/server/manifest/dev-client-manifest.js +24 -0
  105. package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
  106. package/dist/server/manifest/dev-ssr-manifest.js +23 -0
  107. package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
  108. package/dist/server/manifest/prod-client-manifest.js +26 -0
  109. package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
  110. package/dist/server/manifest/prod-ssr-manifest.js +85 -0
  111. package/dist/server/manifest/ssr-manifest.d.ts +4 -0
  112. package/dist/server/manifest/ssr-manifest.js +6 -0
  113. package/dist/server/routes.d.ts +23 -0
  114. package/dist/server/routes.js +74 -0
  115. package/dist/server/spa/StartServer.d.ts +9 -0
  116. package/dist/server/spa/StartServer.jsx +25 -0
  117. package/dist/server/spa/handler.d.ts +8 -0
  118. package/dist/server/spa/handler.js +20 -0
  119. package/{src/server/spa/index.tsx → dist/server/spa/index.d.ts} +0 -1
  120. package/dist/server/spa/index.jsx +5 -0
  121. package/dist/server/types.d.ts +75 -0
  122. package/dist/server/types.js +1 -0
  123. package/dist/server/util.d.ts +2 -0
  124. package/dist/server/util.js +8 -0
  125. package/dist/server/web-stream.d.ts +9 -0
  126. package/dist/server/web-stream.js +26 -0
  127. package/dist/shared/ErrorBoundary.d.ts +3 -0
  128. package/dist/shared/ErrorBoundary.jsx +36 -0
  129. package/dist/shared/GET.d.ts +5 -0
  130. package/dist/shared/GET.js +8 -0
  131. package/dist/shared/HttpHeader.d.ts +10 -0
  132. package/dist/shared/HttpHeader.jsx +38 -0
  133. package/dist/shared/HttpStatusCode.d.ts +9 -0
  134. package/dist/shared/HttpStatusCode.js +18 -0
  135. package/dist/shared/clientOnly.d.ts +12 -0
  136. package/dist/shared/clientOnly.js +27 -0
  137. package/dist/shared/dev-overlay/CodeView.d.ts +7 -0
  138. package/dist/shared/dev-overlay/CodeView.jsx +62 -0
  139. package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +9 -0
  140. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +226 -0
  141. package/dist/shared/dev-overlay/createStackFrame.d.ts +9 -0
  142. package/dist/shared/dev-overlay/createStackFrame.js +56 -0
  143. package/dist/shared/dev-overlay/download.d.ts +1 -0
  144. package/dist/shared/dev-overlay/download.js +6 -0
  145. package/dist/shared/dev-overlay/get-source-map.d.ts +2 -0
  146. package/dist/shared/dev-overlay/get-source-map.js +25 -0
  147. package/dist/shared/dev-overlay/icons.d.ts +28 -0
  148. package/dist/shared/dev-overlay/icons.jsx +150 -0
  149. package/dist/shared/dev-overlay/index.d.ts +5 -0
  150. package/dist/shared/dev-overlay/index.jsx +39 -0
  151. package/dist/shared/lazy.d.ts +3 -0
  152. package/dist/shared/lazy.js +42 -0
  153. package/dist/shared/serverFunction.d.ts +6 -0
  154. package/dist/shared/serverFunction.js +8 -0
  155. package/dist/utils/debounce.d.ts +4 -0
  156. package/dist/utils/debounce.js +10 -0
  157. package/env.d.ts +12 -0
  158. package/package.json +10 -5
  159. package/scripts/build.js +0 -15
  160. package/scripts/validate-imports.js +0 -316
  161. package/src/client/mount.ts +0 -1
  162. package/src/client/spa/index.tsx +0 -9
  163. package/src/config/constants.ts +0 -19
  164. package/src/config/dev-server.ts +0 -161
  165. package/src/config/env.ts +0 -105
  166. package/src/config/fs-router.ts +0 -162
  167. package/src/config/fs-routes/fs-watcher.ts +0 -66
  168. package/src/config/fs-routes/index.ts +0 -136
  169. package/src/config/fs-routes/router.ts +0 -184
  170. package/src/config/fs-routes/tree-shake.ts +0 -324
  171. package/src/config/index.ts +0 -239
  172. package/src/config/lazy.ts +0 -132
  173. package/src/config/manifest.ts +0 -120
  174. package/src/config/utils.ts +0 -5
  175. package/src/config/vite-utils.ts +0 -113
  176. package/src/directives/bubble-function-declaration.ts +0 -33
  177. package/src/directives/compile.ts +0 -54
  178. package/src/directives/generate-unique-name.ts +0 -22
  179. package/src/directives/get-descriptive-name.ts +0 -39
  180. package/src/directives/get-import-identifier.ts +0 -34
  181. package/src/directives/get-root-statement-path.ts +0 -14
  182. package/src/directives/index.ts +0 -233
  183. package/src/directives/is-statement-top-level.ts +0 -13
  184. package/src/directives/paths.ts +0 -63
  185. package/src/directives/plugin.ts +0 -389
  186. package/src/directives/remove-unused-variables.ts +0 -70
  187. package/src/directives/xxhash32.ts +0 -214
  188. package/src/env.d.ts +0 -17
  189. package/src/fns/client.ts +0 -141
  190. package/src/fns/handler.spec.ts +0 -85
  191. package/src/fns/handler.ts +0 -287
  192. package/src/fns/registration.ts +0 -19
  193. package/src/fns/serialization.ts +0 -250
  194. package/src/fns/server.ts +0 -46
  195. package/src/fns/shared.ts +0 -116
  196. package/src/http/index.ts +0 -216
  197. package/src/internal.d.ts +0 -14
  198. package/src/middleware/index.ts +0 -92
  199. package/src/router.tsx +0 -37
  200. package/src/server/StartServer.tsx +0 -58
  201. package/src/server/assets/index.ts +0 -70
  202. package/src/server/assets/render.tsx +0 -46
  203. package/src/server/collect-styles.ts +0 -70
  204. package/src/server/fetchEvent.spec.ts +0 -85
  205. package/src/server/fetchEvent.ts +0 -36
  206. package/src/server/handler.ts +0 -261
  207. package/src/server/manifest/client-manifest.ts +0 -8
  208. package/src/server/manifest/dev-client-manifest.ts +0 -21
  209. package/src/server/manifest/dev-ssr-manifest.ts +0 -23
  210. package/src/server/manifest/prod-client-manifest.ts +0 -21
  211. package/src/server/manifest/prod-ssr-manifest.ts +0 -109
  212. package/src/server/manifest/ssr-manifest.ts +0 -10
  213. package/src/server/routes.ts +0 -126
  214. package/src/server/spa/StartServer.tsx +0 -42
  215. package/src/server/spa/handler.ts +0 -29
  216. package/src/server/types.ts +0 -82
  217. package/src/server/util.ts +0 -12
  218. package/src/shared/ErrorBoundary.tsx +0 -52
  219. package/src/shared/GET.ts +0 -8
  220. package/src/shared/HttpHeader.tsx +0 -42
  221. package/src/shared/HttpStatusCode.ts +0 -27
  222. package/src/shared/clientOnly.ts +0 -44
  223. package/src/shared/dev-overlay/CodeView.tsx +0 -90
  224. package/src/shared/dev-overlay/DevOverlayDialog.tsx +0 -316
  225. package/src/shared/dev-overlay/createStackFrame.ts +0 -74
  226. package/src/shared/dev-overlay/download.ts +0 -6
  227. package/src/shared/dev-overlay/env.d.ts +0 -4
  228. package/src/shared/dev-overlay/get-source-map.ts +0 -33
  229. package/src/shared/dev-overlay/icons.tsx +0 -456
  230. package/src/shared/dev-overlay/index.tsx +0 -63
  231. package/src/shared/lazy.ts +0 -52
  232. package/src/shared/serverFunction.ts +0 -10
  233. package/src/utils/debounce.ts +0 -10
  234. package/src/virtual.d.ts +0 -27
  235. package/tsconfig.json +0 -24
  236. package/vitest.config.ts +0 -9
  237. /package/{src/client/index.tsx → dist/client/index.d.ts} +0 -0
  238. /package/{src → dist}/shared/dev-overlay/styles.css +0 -0
@@ -0,0 +1,148 @@
1
+ import { analyzeModule, BaseFileSystemRouter, cleanPath, } from "./fs-routes/router.js";
2
+ export class SolidStartClientFileRouter extends BaseFileSystemRouter {
3
+ toPath(src) {
4
+ const routePath = cleanPath(src, this.config)
5
+ // remove the initial slash
6
+ .slice(1)
7
+ .replace(/index$/, "")
8
+ .replace(/\[([^/]+)\]/g, (_, m) => {
9
+ if (m.length > 3 && m.startsWith("...")) {
10
+ return `*${m.slice(3)}`;
11
+ }
12
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
13
+ return `:${m.slice(1, -1)}?`;
14
+ }
15
+ return `:${m}`;
16
+ });
17
+ return routePath?.length > 0 ? `/${routePath}` : "/";
18
+ }
19
+ toRoute(src) {
20
+ const path = this.toPath(src);
21
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
22
+ return {
23
+ page: true,
24
+ $component: {
25
+ src: src,
26
+ pick: ["$css"],
27
+ },
28
+ $$route: undefined,
29
+ path,
30
+ // filePath: src
31
+ };
32
+ }
33
+ const exports = analyzeModule(src);
34
+ const exportNames = exports.map(getExportName);
35
+ const localExportNames = exports.map(getLocalExportName).filter(name => name !== undefined);
36
+ const hasDefault = exportNames.includes("default");
37
+ const hasRouteConfig = exportNames.includes("route");
38
+ if (hasDefault) {
39
+ return {
40
+ page: true,
41
+ $component: {
42
+ src: src,
43
+ pick: [...localExportNames.filter(name => name !== "route"), "default", "$css"],
44
+ },
45
+ $$route: hasRouteConfig
46
+ ? {
47
+ src: src,
48
+ pick: ["route"],
49
+ }
50
+ : undefined,
51
+ path,
52
+ // filePath: src
53
+ };
54
+ }
55
+ }
56
+ }
57
+ const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
58
+ function getExportName(entry) {
59
+ return entry.exportName.name ?? "default";
60
+ }
61
+ function getLocalExportName(entry) {
62
+ const name = getExportName(entry);
63
+ if (name === "default")
64
+ return;
65
+ return name === (entry.localName.name ?? entry.importName.name ?? name) ? name : undefined;
66
+ }
67
+ function createHTTPHandlers(src, exports) {
68
+ const handlers = {};
69
+ for (const exp of exports) {
70
+ if (HTTP_METHODS.includes(exp)) {
71
+ handlers[`$${exp}`] = {
72
+ src: src,
73
+ pick: [exp],
74
+ };
75
+ if (exp === "GET" && !exports.includes("HEAD")) {
76
+ handlers.$HEAD = {
77
+ src: src,
78
+ pick: [exp],
79
+ };
80
+ }
81
+ }
82
+ }
83
+ return handlers;
84
+ }
85
+ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
86
+ constructor(config) {
87
+ super(config);
88
+ }
89
+ toPath(src) {
90
+ const routePath = cleanPath(src, this.config)
91
+ // remove the initial slash
92
+ .slice(1)
93
+ .replace(/index$/, "")
94
+ .replace(/\[([^/]+)\]/g, (_, m) => {
95
+ if (m.length > 3 && m.startsWith("...")) {
96
+ return `*${m.slice(3)}`;
97
+ }
98
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
99
+ return `:${m.slice(1, -1)}?`;
100
+ }
101
+ return `:${m}`;
102
+ });
103
+ return routePath?.length > 0 ? `/${routePath}` : "/";
104
+ }
105
+ toRoute(src) {
106
+ const path = this.toPath(src);
107
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
108
+ return {
109
+ page: true,
110
+ $component: {
111
+ src: src,
112
+ pick: ["$css"],
113
+ },
114
+ $$route: undefined,
115
+ path,
116
+ };
117
+ }
118
+ const exports = analyzeModule(src);
119
+ const exportNames = exports.map(getExportName);
120
+ const localExportNames = exports.map(getLocalExportName).filter(name => name !== undefined);
121
+ const hasRouteConfig = exportNames.includes("route");
122
+ const hasDefault = exportNames.includes("default");
123
+ const hasAPIRoutes = exportNames.some(name => HTTP_METHODS.includes(name));
124
+ if (hasDefault || hasAPIRoutes) {
125
+ return {
126
+ page: hasDefault,
127
+ $component: !this.config.dataOnly && hasDefault
128
+ ? {
129
+ src: src,
130
+ pick: [
131
+ ...localExportNames.filter(name => name !== "route" && !HTTP_METHODS.includes(name)),
132
+ "default",
133
+ "$css",
134
+ ],
135
+ }
136
+ : undefined,
137
+ $$route: hasRouteConfig
138
+ ? {
139
+ src: src,
140
+ pick: ["route"],
141
+ }
142
+ : undefined,
143
+ ...createHTTPHandlers(src, exportNames),
144
+ path,
145
+ };
146
+ }
147
+ }
148
+ }
@@ -0,0 +1,3 @@
1
+ import type { PluginOption } from "vite";
2
+ import type { BaseFileSystemRouter } from "./router.ts";
3
+ export declare const fileSystemWatcher: (routers: Record<"client" | "ssr", BaseFileSystemRouter>) => PluginOption;
@@ -0,0 +1,53 @@
1
+ import { debounce } from "../../utils/debounce.js";
2
+ import { VITE_ENVIRONMENTS } from "../constants.js";
3
+ import { moduleId } from "./index.js";
4
+ function setupWatcher(watcher, routes) {
5
+ watcher.on("unlink", path => routes.removeRoute(path));
6
+ watcher.on("add", path => routes.addRoute(path));
7
+ watcher.on("change", path => routes.updateRoute(path));
8
+ }
9
+ function createRoutesReloader(server, routes, environment) {
10
+ const devEnv = server.environments[environment];
11
+ if (!devEnv?.moduleGraph)
12
+ return;
13
+ /**
14
+ * Debounce catches multiple route changes in a row
15
+ * Short timeout for inexpensive invalidations
16
+ */
17
+ const invalidateModule = debounce((mod) => {
18
+ devEnv.moduleGraph.invalidateModule(mod);
19
+ }, 0);
20
+ /**
21
+ * Long debounce timeout for expensive reloads
22
+ */
23
+ const reloadModule = debounce((mod) => {
24
+ devEnv.reloadModule(mod);
25
+ }, 200);
26
+ return routes.on("reload", function handleRoutesReload(evt) {
27
+ const mod = devEnv.moduleGraph.getModuleById(moduleId);
28
+ if (!mod) {
29
+ devEnv.hot.send({ type: "full-reload" });
30
+ return;
31
+ }
32
+ if (environment === VITE_ENVIRONMENTS.client && evt.detail.type !== "update") {
33
+ // Client has to be reloaded when routes are added or removed
34
+ reloadModule(mod);
35
+ }
36
+ else {
37
+ invalidateModule(mod);
38
+ }
39
+ });
40
+ }
41
+ export const fileSystemWatcher = (routers) => {
42
+ const plugin = {
43
+ name: "fs-watcher",
44
+ async configureServer(server) {
45
+ for (const environment of [VITE_ENVIRONMENTS.server, VITE_ENVIRONMENTS.client]) {
46
+ const router = routers[environment];
47
+ setupWatcher(server.watcher, router);
48
+ createRoutesReloader(server, router, environment);
49
+ }
50
+ },
51
+ };
52
+ return plugin;
53
+ };
@@ -0,0 +1,7 @@
1
+ import { type PluginOption } from "vite";
2
+ import type { BaseFileSystemRouter } from "./router.ts";
3
+ export declare const moduleId = "solid-start:routes";
4
+ export interface FsRoutesArgs {
5
+ routers: Record<"client" | "ssr", BaseFileSystemRouter>;
6
+ }
7
+ export declare function fsRoutes({ routers }: FsRoutesArgs): Array<PluginOption>;
@@ -0,0 +1,107 @@
1
+ import { relative } from "node:path";
2
+ import { fileSystemWatcher } from "./fs-watcher.js";
3
+ import { treeShake } from "./tree-shake.js";
4
+ export const moduleId = "solid-start:routes";
5
+ export function fsRoutes({ routers }) {
6
+ globalThis.ROUTERS = routers;
7
+ return [
8
+ {
9
+ name: "solid-start-fs-routes",
10
+ enforce: "pre",
11
+ resolveId(id) {
12
+ if (id === moduleId)
13
+ return id;
14
+ },
15
+ async load(id) {
16
+ const root = this.environment.config.root;
17
+ const isBuild = this.environment.mode === "build";
18
+ if (id !== moduleId)
19
+ return;
20
+ const js = jsCode();
21
+ const router = globalThis.ROUTERS[this.environment.name];
22
+ const routes = await router.getRoutes();
23
+ let routesCode = JSON.stringify(routes ?? [], (k, v) => {
24
+ if (v === undefined)
25
+ return undefined;
26
+ if (k.startsWith("$$")) {
27
+ const buildId = `${v.src}?${v.pick.map((p) => `pick=${p}`).join("&")}`;
28
+ /**
29
+ * @type {{ [key: string]: string }}
30
+ */
31
+ const refs = {};
32
+ for (var pick of v.pick) {
33
+ refs[pick] = js.addNamedImport(pick, buildId);
34
+ }
35
+ return {
36
+ require: `_$() => ({ ${Object.entries(refs)
37
+ .map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
38
+ .join(", ")} })$_`,
39
+ // src: isBuild ? relative(root, buildId) : buildId
40
+ };
41
+ }
42
+ else if (k.startsWith("$")) {
43
+ const buildId = `${v.src}?${v.pick.map((p) => `pick=${p}`).join("&")}`;
44
+ return {
45
+ src: relative(root, buildId),
46
+ build: isBuild ? `_$() => import('${buildId}')$_` : undefined,
47
+ import: `_$() => import('${buildId}')$_`,
48
+ };
49
+ }
50
+ return v;
51
+ });
52
+ routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
53
+ const code = `
54
+ ${js.getImportStatements()}
55
+ export default ${routesCode}`;
56
+ return code;
57
+ },
58
+ },
59
+ treeShake(),
60
+ fileSystemWatcher(routers),
61
+ ];
62
+ }
63
+ function jsCode() {
64
+ const imports = new Map();
65
+ let vars = 0;
66
+ function addImport(p) {
67
+ let id = imports.get(p);
68
+ if (!id) {
69
+ id = {};
70
+ imports.set(p, id);
71
+ }
72
+ const d = "routeData" + vars++;
73
+ id["default"] = d;
74
+ return d;
75
+ }
76
+ function addNamedImport(name, p) {
77
+ let id = imports.get(p);
78
+ if (!id) {
79
+ id = {};
80
+ imports.set(p, id);
81
+ }
82
+ const d = "routeData" + vars++;
83
+ id[name] = d;
84
+ return d;
85
+ }
86
+ const getNamedExport = (p) => {
87
+ const id = imports.get(p);
88
+ delete id["default"];
89
+ return Object.keys(id).length > 0
90
+ ? `{ ${Object.keys(id)
91
+ .map(k => `${k} as ${id[k]}`)
92
+ .join(", ")} }`
93
+ : "";
94
+ };
95
+ const getImportStatements = () => {
96
+ return `${[...imports.keys()]
97
+ .map(i => `import ${imports.get(i).default
98
+ ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
99
+ : ""} ${getNamedExport(i)} from '${i}';`)
100
+ .join("\n")}`;
101
+ };
102
+ return {
103
+ addImport,
104
+ addNamedImport,
105
+ getImportStatements,
106
+ };
107
+ }
@@ -0,0 +1,43 @@
1
+ import { type StaticExportEntry } from "oxc-parser";
2
+ import { pathToRegexp } from "path-to-regexp";
3
+ export { pathToRegexp };
4
+ export declare const glob: (path: string) => string[];
5
+ export type FileSystemRouterConfig = {
6
+ dir: string;
7
+ extensions: string[];
8
+ };
9
+ type Route = {
10
+ path: string;
11
+ } & Record<string, any>;
12
+ export declare function cleanPath(src: string, config: FileSystemRouterConfig): string;
13
+ export declare function analyzeModule(src: string): StaticExportEntry[];
14
+ type RouterEvent = CustomEvent<{
15
+ route: string;
16
+ type: "update" | "remove" | "add";
17
+ }>;
18
+ export declare class BaseFileSystemRouter extends EventTarget {
19
+ routes: Route[];
20
+ config: FileSystemRouterConfig;
21
+ /**
22
+ *
23
+ * @param {} config
24
+ */
25
+ constructor(config: FileSystemRouterConfig);
26
+ glob(): string;
27
+ buildRoutes(): Promise<any[]>;
28
+ isRoute(src: string): boolean;
29
+ toPath(src: string): void;
30
+ toRoute(src: string): Route | undefined;
31
+ /**
32
+ * To be attached by vite plugin to the vite dev server
33
+ */
34
+ update: undefined;
35
+ _addRoute(route: Route): boolean;
36
+ addRoute(src: string): Promise<void>;
37
+ reload(route: string, type: "update" | "remove" | "add"): void;
38
+ updateRoute(src_: string): Promise<void>;
39
+ removeRoute(src: string): void;
40
+ on(type: string, cb: (evt: RouterEvent) => void): () => void;
41
+ buildRoutesPromise?: Promise<any[]>;
42
+ getRoutes(): Promise<Route[]>;
43
+ }
@@ -0,0 +1,146 @@
1
+ import fg from "fast-glob";
2
+ import fs from "node:fs";
3
+ import micromatch from "micromatch";
4
+ import { posix } from "node:path";
5
+ import { parseSync } from "oxc-parser";
6
+ import { pathToRegexp } from "path-to-regexp";
7
+ import { normalizePath } from "vite";
8
+ export { pathToRegexp };
9
+ export const glob = (path) => fg.sync(path, { absolute: true });
10
+ export function cleanPath(src, config) {
11
+ return src
12
+ .slice(config.dir.length)
13
+ .replace(new RegExp(`\.(${(config.extensions ?? []).join("|")})$`), "");
14
+ }
15
+ export function analyzeModule(src) {
16
+ const result = parseSync(src, fs.readFileSync(src, "utf-8"), { lang: "tsx" });
17
+ const error = result.errors[0];
18
+ if (error)
19
+ throw new SyntaxError(`Failed to parse ${src}:\n${error.codeframe || error.message}`);
20
+ return result.module.staticExports.flatMap(({ entries }) => entries.filter(entry => !entry.isType && entry.exportName.kind !== "None"));
21
+ }
22
+ export class BaseFileSystemRouter extends EventTarget {
23
+ routes;
24
+ config;
25
+ /**
26
+ *
27
+ * @param {} config
28
+ */
29
+ constructor(config) {
30
+ super();
31
+ this.routes = [];
32
+ this.config = config;
33
+ }
34
+ glob() {
35
+ return (posix.join(fg.convertPathToPattern(this.config.dir), "**/*") +
36
+ `.{${this.config.extensions.join(",")}}`);
37
+ }
38
+ async buildRoutes() {
39
+ for (var src of glob(this.glob())) {
40
+ await this.addRoute(src);
41
+ }
42
+ return this.routes;
43
+ }
44
+ isRoute(src) {
45
+ return Boolean(micromatch(src, this.glob())?.length);
46
+ }
47
+ toPath(src) {
48
+ throw new Error("Not implemented");
49
+ }
50
+ toRoute(src) {
51
+ let path = this.toPath(src);
52
+ if (path === undefined)
53
+ return;
54
+ const exports = analyzeModule(src);
55
+ if (!exports.find(entry => entry.exportName.kind === "Default")) {
56
+ console.warn("No default export", src);
57
+ }
58
+ return {
59
+ $component: {
60
+ src: src,
61
+ pick: ["default", "$css"],
62
+ },
63
+ path,
64
+ // filePath: src
65
+ };
66
+ }
67
+ /**
68
+ * To be attached by vite plugin to the vite dev server
69
+ */
70
+ update = undefined;
71
+ _addRoute(route) {
72
+ const idx = this.routes.findIndex(r => r.path === route.path);
73
+ if (idx >= 0)
74
+ this.routes.splice(idx, 1);
75
+ this.routes.push(route);
76
+ return idx >= 0;
77
+ }
78
+ async addRoute(src) {
79
+ src = normalizePath(src);
80
+ if (this.isRoute(src)) {
81
+ try {
82
+ const route = this.toRoute(src);
83
+ if (route) {
84
+ this._addRoute(route);
85
+ this.reload(route.path, "add");
86
+ }
87
+ }
88
+ catch (e) {
89
+ console.error(e);
90
+ }
91
+ }
92
+ }
93
+ reload(route, type) {
94
+ this.dispatchEvent(new CustomEvent("reload", {
95
+ detail: {
96
+ route,
97
+ type,
98
+ },
99
+ }));
100
+ }
101
+ async updateRoute(src_) {
102
+ const src = normalizePath(src_);
103
+ if (this.isRoute(src)) {
104
+ try {
105
+ const route = this.toRoute(src);
106
+ if (route) {
107
+ const updated = this._addRoute(route);
108
+ this.reload(route.path, updated ? "update" : "add");
109
+ }
110
+ else {
111
+ this.removeRoute(src_);
112
+ }
113
+ }
114
+ catch (e) {
115
+ console.error(e);
116
+ }
117
+ // this.update?.();
118
+ }
119
+ }
120
+ removeRoute(src) {
121
+ src = normalizePath(src);
122
+ if (this.isRoute(src)) {
123
+ const path = this.toPath(src);
124
+ if (path === undefined) {
125
+ return;
126
+ }
127
+ const idx = this.routes.findIndex(r => r.path === path);
128
+ if (idx === -1)
129
+ return;
130
+ this.routes.splice(idx, 1);
131
+ this.reload(path, "remove");
132
+ }
133
+ }
134
+ on(type, cb) {
135
+ this.addEventListener(type, cb);
136
+ return () => this.removeEventListener(type, cb);
137
+ }
138
+ buildRoutesPromise;
139
+ async getRoutes() {
140
+ if (!this.buildRoutesPromise) {
141
+ this.buildRoutesPromise = this.buildRoutes();
142
+ }
143
+ await this.buildRoutesPromise;
144
+ return this.routes;
145
+ }
146
+ }
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from "vite";
2
+ export declare function treeShake(): Plugin;