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

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 (231) hide show
  1. package/CHANGELOG.md +13 -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/constants.d.ts +16 -0
  10. package/dist/config/constants.js +16 -0
  11. package/dist/config/dev-server.d.ts +2 -0
  12. package/dist/config/dev-server.js +128 -0
  13. package/dist/config/env.d.ts +19 -0
  14. package/dist/config/env.js +81 -0
  15. package/dist/config/fs-router.d.ts +37 -0
  16. package/dist/config/fs-router.js +141 -0
  17. package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
  18. package/dist/config/fs-routes/fs-watcher.js +53 -0
  19. package/dist/config/fs-routes/index.d.ts +7 -0
  20. package/dist/config/fs-routes/index.js +107 -0
  21. package/dist/config/fs-routes/router.d.ts +42 -0
  22. package/dist/config/fs-routes/router.js +148 -0
  23. package/dist/config/fs-routes/tree-shake.d.ts +2 -0
  24. package/dist/config/fs-routes/tree-shake.js +305 -0
  25. package/dist/config/index.d.ts +25 -0
  26. package/dist/config/index.js +224 -0
  27. package/dist/config/lazy.d.ts +3 -0
  28. package/dist/config/lazy.js +114 -0
  29. package/dist/config/manifest.d.ts +3 -0
  30. package/dist/config/manifest.js +109 -0
  31. package/dist/config/utils.d.ts +4 -0
  32. package/dist/config/utils.js +6 -0
  33. package/dist/config/vite-utils.d.ts +21 -0
  34. package/dist/config/vite-utils.js +85 -0
  35. package/dist/directives/bubble-function-declaration.d.ts +3 -0
  36. package/dist/directives/bubble-function-declaration.js +23 -0
  37. package/dist/directives/compile.d.ts +9 -0
  38. package/dist/directives/compile.js +40 -0
  39. package/dist/directives/generate-unique-name.d.ts +3 -0
  40. package/dist/directives/generate-unique-name.js +16 -0
  41. package/dist/directives/get-descriptive-name.d.ts +2 -0
  42. package/dist/directives/get-descriptive-name.js +37 -0
  43. package/dist/directives/get-import-identifier.d.ts +4 -0
  44. package/dist/directives/get-import-identifier.js +19 -0
  45. package/dist/directives/get-root-statement-path.d.ts +2 -0
  46. package/dist/directives/get-root-statement-path.js +12 -0
  47. package/dist/directives/index.d.ts +14 -0
  48. package/dist/directives/index.js +170 -0
  49. package/dist/directives/is-statement-top-level.d.ts +3 -0
  50. package/dist/directives/is-statement-top-level.js +9 -0
  51. package/dist/directives/paths.d.ts +9 -0
  52. package/dist/directives/paths.js +36 -0
  53. package/dist/directives/plugin.d.ts +21 -0
  54. package/dist/directives/plugin.js +302 -0
  55. package/dist/directives/remove-unused-variables.d.ts +3 -0
  56. package/dist/directives/remove-unused-variables.js +66 -0
  57. package/{src/directives/types.ts → dist/directives/types.d.ts} +5 -7
  58. package/dist/directives/types.js +1 -0
  59. package/dist/directives/xxhash32.d.ts +6 -0
  60. package/dist/directives/xxhash32.js +193 -0
  61. package/dist/fns/client.d.ts +3 -0
  62. package/dist/fns/client.js +106 -0
  63. package/dist/fns/handler.d.ts +5 -0
  64. package/dist/fns/handler.js +269 -0
  65. package/dist/fns/registration.d.ts +2 -0
  66. package/dist/fns/registration.js +12 -0
  67. package/dist/fns/serialization.d.ts +6 -0
  68. package/dist/fns/serialization.js +208 -0
  69. package/dist/fns/server.d.ts +7 -0
  70. package/dist/fns/server.js +38 -0
  71. package/dist/fns/shared.d.ts +17 -0
  72. package/dist/fns/shared.js +105 -0
  73. package/dist/http/index.d.ts +81 -0
  74. package/dist/http/index.js +129 -0
  75. package/{src/index.tsx → dist/index.d.ts} +0 -2
  76. package/dist/index.jsx +6 -0
  77. package/dist/middleware/index.d.ts +38 -0
  78. package/dist/middleware/index.js +59 -0
  79. package/dist/router.d.ts +6 -0
  80. package/dist/router.jsx +29 -0
  81. package/dist/server/StartServer.d.ts +9 -0
  82. package/dist/server/StartServer.jsx +34 -0
  83. package/dist/server/assets/PatchVirtualDevStyles.d.ts +4 -0
  84. package/{src/server/assets/PatchVirtualDevStyles.tsx → dist/server/assets/PatchVirtualDevStyles.jsx} +7 -10
  85. package/dist/server/assets/index.d.ts +2 -0
  86. package/dist/server/assets/index.js +52 -0
  87. package/dist/server/assets/render.d.ts +19 -0
  88. package/dist/server/assets/render.jsx +14 -0
  89. package/dist/server/collect-styles.d.ts +3 -0
  90. package/dist/server/collect-styles.js +57 -0
  91. package/dist/server/fetchEvent.d.ts +7 -0
  92. package/dist/server/fetchEvent.js +26 -0
  93. package/dist/server/handler.d.ts +64 -0
  94. package/dist/server/handler.js +222 -0
  95. package/dist/server/index.d.ts +9 -0
  96. package/{src/server/index.tsx → dist/server/index.jsx} +4 -19
  97. package/dist/server/manifest/client-manifest.d.ts +9 -0
  98. package/dist/server/manifest/client-manifest.js +6 -0
  99. package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
  100. package/dist/server/manifest/dev-client-manifest.js +24 -0
  101. package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
  102. package/dist/server/manifest/dev-ssr-manifest.js +23 -0
  103. package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
  104. package/dist/server/manifest/prod-client-manifest.js +26 -0
  105. package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
  106. package/dist/server/manifest/prod-ssr-manifest.js +85 -0
  107. package/dist/server/manifest/ssr-manifest.d.ts +4 -0
  108. package/dist/server/manifest/ssr-manifest.js +6 -0
  109. package/dist/server/routes.d.ts +23 -0
  110. package/dist/server/routes.js +74 -0
  111. package/dist/server/spa/StartServer.d.ts +9 -0
  112. package/dist/server/spa/StartServer.jsx +25 -0
  113. package/dist/server/spa/handler.d.ts +36 -0
  114. package/dist/server/spa/handler.js +20 -0
  115. package/{src/server/spa/index.tsx → dist/server/spa/index.d.ts} +0 -1
  116. package/dist/server/spa/index.jsx +5 -0
  117. package/dist/server/types.d.ts +75 -0
  118. package/dist/server/types.js +1 -0
  119. package/dist/server/util.d.ts +2 -0
  120. package/dist/server/util.js +8 -0
  121. package/dist/shared/ErrorBoundary.d.ts +3 -0
  122. package/dist/shared/ErrorBoundary.jsx +36 -0
  123. package/dist/shared/GET.d.ts +5 -0
  124. package/dist/shared/GET.js +8 -0
  125. package/dist/shared/HttpHeader.d.ts +10 -0
  126. package/dist/shared/HttpHeader.jsx +38 -0
  127. package/dist/shared/HttpStatusCode.d.ts +9 -0
  128. package/dist/shared/HttpStatusCode.js +18 -0
  129. package/dist/shared/clientOnly.d.ts +12 -0
  130. package/dist/shared/clientOnly.js +27 -0
  131. package/dist/shared/dev-overlay/CodeView.d.ts +7 -0
  132. package/dist/shared/dev-overlay/CodeView.jsx +62 -0
  133. package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +9 -0
  134. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +226 -0
  135. package/dist/shared/dev-overlay/createStackFrame.d.ts +9 -0
  136. package/dist/shared/dev-overlay/createStackFrame.js +56 -0
  137. package/dist/shared/dev-overlay/download.d.ts +1 -0
  138. package/dist/shared/dev-overlay/download.js +6 -0
  139. package/dist/shared/dev-overlay/get-source-map.d.ts +2 -0
  140. package/dist/shared/dev-overlay/get-source-map.js +25 -0
  141. package/dist/shared/dev-overlay/icons.d.ts +28 -0
  142. package/dist/shared/dev-overlay/icons.jsx +150 -0
  143. package/dist/shared/dev-overlay/index.d.ts +5 -0
  144. package/dist/shared/dev-overlay/index.jsx +39 -0
  145. package/dist/shared/lazy.d.ts +3 -0
  146. package/dist/shared/lazy.js +42 -0
  147. package/dist/shared/serverFunction.d.ts +6 -0
  148. package/dist/shared/serverFunction.js +8 -0
  149. package/dist/utils/debounce.d.ts +4 -0
  150. package/dist/utils/debounce.js +10 -0
  151. package/package.json +7 -2
  152. package/scripts/build.js +0 -15
  153. package/scripts/validate-imports.js +0 -316
  154. package/src/client/mount.ts +0 -1
  155. package/src/client/spa/index.tsx +0 -9
  156. package/src/config/constants.ts +0 -19
  157. package/src/config/dev-server.ts +0 -161
  158. package/src/config/env.ts +0 -105
  159. package/src/config/fs-router.ts +0 -162
  160. package/src/config/fs-routes/fs-watcher.ts +0 -66
  161. package/src/config/fs-routes/index.ts +0 -136
  162. package/src/config/fs-routes/router.ts +0 -184
  163. package/src/config/fs-routes/tree-shake.ts +0 -324
  164. package/src/config/index.ts +0 -239
  165. package/src/config/lazy.ts +0 -132
  166. package/src/config/manifest.ts +0 -120
  167. package/src/config/utils.ts +0 -5
  168. package/src/config/vite-utils.ts +0 -113
  169. package/src/directives/bubble-function-declaration.ts +0 -33
  170. package/src/directives/compile.ts +0 -54
  171. package/src/directives/generate-unique-name.ts +0 -22
  172. package/src/directives/get-descriptive-name.ts +0 -39
  173. package/src/directives/get-import-identifier.ts +0 -34
  174. package/src/directives/get-root-statement-path.ts +0 -14
  175. package/src/directives/index.ts +0 -233
  176. package/src/directives/is-statement-top-level.ts +0 -13
  177. package/src/directives/paths.ts +0 -63
  178. package/src/directives/plugin.ts +0 -389
  179. package/src/directives/remove-unused-variables.ts +0 -70
  180. package/src/directives/xxhash32.ts +0 -214
  181. package/src/env.d.ts +0 -17
  182. package/src/fns/client.ts +0 -141
  183. package/src/fns/handler.spec.ts +0 -85
  184. package/src/fns/handler.ts +0 -287
  185. package/src/fns/registration.ts +0 -19
  186. package/src/fns/serialization.ts +0 -250
  187. package/src/fns/server.ts +0 -46
  188. package/src/fns/shared.ts +0 -116
  189. package/src/http/index.ts +0 -216
  190. package/src/internal.d.ts +0 -14
  191. package/src/middleware/index.ts +0 -92
  192. package/src/router.tsx +0 -37
  193. package/src/server/StartServer.tsx +0 -58
  194. package/src/server/assets/index.ts +0 -70
  195. package/src/server/assets/render.tsx +0 -46
  196. package/src/server/collect-styles.ts +0 -70
  197. package/src/server/fetchEvent.spec.ts +0 -85
  198. package/src/server/fetchEvent.ts +0 -36
  199. package/src/server/handler.ts +0 -261
  200. package/src/server/manifest/client-manifest.ts +0 -8
  201. package/src/server/manifest/dev-client-manifest.ts +0 -21
  202. package/src/server/manifest/dev-ssr-manifest.ts +0 -23
  203. package/src/server/manifest/prod-client-manifest.ts +0 -21
  204. package/src/server/manifest/prod-ssr-manifest.ts +0 -109
  205. package/src/server/manifest/ssr-manifest.ts +0 -10
  206. package/src/server/routes.ts +0 -126
  207. package/src/server/spa/StartServer.tsx +0 -42
  208. package/src/server/spa/handler.ts +0 -29
  209. package/src/server/types.ts +0 -82
  210. package/src/server/util.ts +0 -12
  211. package/src/shared/ErrorBoundary.tsx +0 -52
  212. package/src/shared/GET.ts +0 -8
  213. package/src/shared/HttpHeader.tsx +0 -42
  214. package/src/shared/HttpStatusCode.ts +0 -27
  215. package/src/shared/clientOnly.ts +0 -44
  216. package/src/shared/dev-overlay/CodeView.tsx +0 -90
  217. package/src/shared/dev-overlay/DevOverlayDialog.tsx +0 -316
  218. package/src/shared/dev-overlay/createStackFrame.ts +0 -74
  219. package/src/shared/dev-overlay/download.ts +0 -6
  220. package/src/shared/dev-overlay/env.d.ts +0 -4
  221. package/src/shared/dev-overlay/get-source-map.ts +0 -33
  222. package/src/shared/dev-overlay/icons.tsx +0 -456
  223. package/src/shared/dev-overlay/index.tsx +0 -63
  224. package/src/shared/lazy.ts +0 -52
  225. package/src/shared/serverFunction.ts +0 -10
  226. package/src/utils/debounce.ts +0 -10
  227. package/src/virtual.d.ts +0 -27
  228. package/tsconfig.json +0 -24
  229. package/vitest.config.ts +0 -9
  230. /package/{src/client/index.tsx → dist/client/index.d.ts} +0 -0
  231. /package/{src → dist}/shared/dev-overlay/styles.css +0 -0
@@ -0,0 +1,16 @@
1
+ import * as t from "@babel/types";
2
+ export function generateUniqueName(path, name) {
3
+ let uid;
4
+ let i = 1;
5
+ do {
6
+ uid = name + "_" + i;
7
+ i++;
8
+ } while (path.scope.hasLabel(uid) ||
9
+ path.scope.hasBinding(uid) ||
10
+ path.scope.hasGlobal(uid) ||
11
+ path.scope.hasReference(uid));
12
+ const program = path.scope.getProgramParent();
13
+ program.references[uid] = true;
14
+ program.uids[uid] = true;
15
+ return t.identifier(uid);
16
+ }
@@ -0,0 +1,2 @@
1
+ import type { NodePath } from "@babel/core";
2
+ export declare function getDescriptiveName(path: NodePath, defaultName: string): string;
@@ -0,0 +1,37 @@
1
+ export function getDescriptiveName(path, defaultName) {
2
+ let current = path;
3
+ while (current) {
4
+ switch (current.node.type) {
5
+ case "FunctionDeclaration":
6
+ case "FunctionExpression": {
7
+ if (current.node.id) {
8
+ return current.node.id.name;
9
+ }
10
+ break;
11
+ }
12
+ case "VariableDeclarator": {
13
+ if (current.node.id.type === "Identifier") {
14
+ return current.node.id.name;
15
+ }
16
+ break;
17
+ }
18
+ case "ClassPrivateMethod":
19
+ case "ClassMethod":
20
+ case "ObjectMethod": {
21
+ switch (current.node.key.type) {
22
+ case "Identifier":
23
+ return current.node.key.name;
24
+ case "PrivateName":
25
+ return current.node.key.id.name;
26
+ default:
27
+ break;
28
+ }
29
+ break;
30
+ }
31
+ default:
32
+ break;
33
+ }
34
+ current = current.parentPath;
35
+ }
36
+ return defaultName;
37
+ }
@@ -0,0 +1,4 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ import type { ImportDefinition } from "./types.ts";
4
+ export declare function getImportIdentifier(imports: Map<string, t.Identifier>, path: babel.NodePath, registration: ImportDefinition): t.Identifier;
@@ -0,0 +1,19 @@
1
+ import * as t from "@babel/types";
2
+ import { generateUniqueName } from "./generate-unique-name.js";
3
+ export function getImportIdentifier(imports, path, registration) {
4
+ const name = registration.kind === "named" ? registration.name : "default";
5
+ const target = `${registration.source}[${name}]`;
6
+ const current = imports.get(target);
7
+ if (current) {
8
+ return current;
9
+ }
10
+ const programParent = path.scope.getProgramParent();
11
+ const uid = generateUniqueName(programParent.path, name);
12
+ programParent.registerDeclaration(programParent.path.unshiftContainer("body", t.importDeclaration([
13
+ registration.kind === "named"
14
+ ? t.importSpecifier(uid, t.identifier(registration.name))
15
+ : t.importDefaultSpecifier(uid),
16
+ ], t.stringLiteral(registration.source)))[0]);
17
+ imports.set(target, uid);
18
+ return uid;
19
+ }
@@ -0,0 +1,2 @@
1
+ import type * as babel from "@babel/core";
2
+ export declare function getRootStatementPath(path: babel.NodePath): babel.NodePath;
@@ -0,0 +1,12 @@
1
+ import * as t from "@babel/types";
2
+ export function getRootStatementPath(path) {
3
+ let current = path.parentPath;
4
+ while (current) {
5
+ const next = current.parentPath;
6
+ if (next && t.isProgram(next.node)) {
7
+ return current;
8
+ }
9
+ current = next;
10
+ }
11
+ return path;
12
+ }
@@ -0,0 +1,14 @@
1
+ import { type FilterPattern, type Plugin } from "vite";
2
+ export interface ServerFunctionsFilter {
3
+ include?: FilterPattern;
4
+ exclude?: FilterPattern;
5
+ }
6
+ export interface ServerFunctionsOptions {
7
+ manifest: string;
8
+ runtime: {
9
+ server: string;
10
+ client: string;
11
+ };
12
+ filter?: ServerFunctionsFilter;
13
+ }
14
+ export declare function serverFunctionsPlugin(options: ServerFunctionsOptions): Plugin[];
@@ -0,0 +1,170 @@
1
+ import { createFilter, } from "vite";
2
+ import { compile } from "./compile.js";
3
+ const DEFAULT_INCLUDE = "src/**/*.{jsx,tsx,ts,js,mjs,cjs}";
4
+ const DEFAULT_EXCLUDE = "node_modules/**/*.{jsx,tsx,ts,js,mjs,cjs}";
5
+ const DIRECTIVE = "use server";
6
+ function createManifest() {
7
+ return {
8
+ server: new Set(),
9
+ client: new Set(),
10
+ };
11
+ }
12
+ function createDeferredPromise() {
13
+ let resolve;
14
+ let reject;
15
+ return {
16
+ reference: new Promise((res, rej) => {
17
+ resolve = res;
18
+ reject = rej;
19
+ }),
20
+ resolve(value) {
21
+ resolve(value);
22
+ },
23
+ reject(value) {
24
+ reject(value);
25
+ },
26
+ };
27
+ }
28
+ class Debouncer {
29
+ source;
30
+ promise;
31
+ timeout;
32
+ constructor(source) {
33
+ this.source = source;
34
+ this.promise = createDeferredPromise();
35
+ this.defer();
36
+ }
37
+ defer() {
38
+ if (this.timeout) {
39
+ clearTimeout(this.timeout);
40
+ this.timeout = undefined;
41
+ }
42
+ this.timeout = setTimeout(() => {
43
+ this.promise.resolve(this.source());
44
+ }, 1000);
45
+ }
46
+ }
47
+ function mergeManifestRecord(source, target) {
48
+ const current = source.size;
49
+ for (const entry of target) {
50
+ source.add(entry);
51
+ }
52
+ return {
53
+ invalidPreload: current !== source.size,
54
+ invalidated: [...source],
55
+ };
56
+ }
57
+ function invalidateModule(moduleGraph, path) {
58
+ const target = moduleGraph.getModuleById(path);
59
+ if (target) {
60
+ moduleGraph.invalidateModule(target);
61
+ }
62
+ }
63
+ function invalidateModules(server, result, manifest) {
64
+ if (server) {
65
+ if (result.invalidPreload) {
66
+ invalidateModule(server.environments.client.moduleGraph, manifest);
67
+ invalidateModule(server.environments.ssr.moduleGraph, manifest);
68
+ }
69
+ }
70
+ }
71
+ export function serverFunctionsPlugin(options) {
72
+ const filter = createFilter(options.filter?.include || DEFAULT_INCLUDE, options.filter?.exclude || DEFAULT_EXCLUDE);
73
+ let env;
74
+ const manifest = createManifest();
75
+ const preload = {
76
+ server: undefined,
77
+ client: undefined,
78
+ };
79
+ let currentServer;
80
+ const clientOptions = {
81
+ directive: DIRECTIVE,
82
+ definitions: {
83
+ register: {
84
+ kind: "named",
85
+ name: "createServerReference",
86
+ source: options.runtime.client,
87
+ },
88
+ clone: {
89
+ kind: "named",
90
+ name: "cloneServerReference",
91
+ source: options.runtime.client,
92
+ },
93
+ },
94
+ };
95
+ const serverOptions = {
96
+ directive: DIRECTIVE,
97
+ definitions: {
98
+ register: {
99
+ kind: "named",
100
+ name: "createServerReference",
101
+ source: options.runtime.server,
102
+ },
103
+ clone: {
104
+ kind: "named",
105
+ name: "cloneServerReference",
106
+ source: options.runtime.server,
107
+ },
108
+ },
109
+ };
110
+ return [
111
+ {
112
+ name: "solid-start:server-functions/setup",
113
+ enforce: "pre",
114
+ configResolved(config) {
115
+ env = config.mode !== "production" ? "development" : "production";
116
+ },
117
+ configureServer(server) {
118
+ currentServer = server;
119
+ },
120
+ },
121
+ {
122
+ name: "solid-start:server-functions/preload",
123
+ enforce: "pre",
124
+ resolveId(source) {
125
+ if (source === options.manifest) {
126
+ return { id: options.manifest, moduleSideEffects: true };
127
+ }
128
+ return null;
129
+ },
130
+ async load(id, opts) {
131
+ const mode = opts?.ssr ? "server" : "client";
132
+ if (id === options.manifest) {
133
+ const current = new Debouncer(() => [...manifest[mode]].map(entry => `import "${entry}";`).join("\n"));
134
+ preload[mode] = current;
135
+ const result = await current.promise.reference;
136
+ return result;
137
+ }
138
+ return null;
139
+ },
140
+ },
141
+ {
142
+ name: "solid-start:server-functions/compiler",
143
+ enforce: 'pre',
144
+ async transform(code, fileId, opts) {
145
+ const mode = opts?.ssr ? "server" : "client";
146
+ const [id] = fileId.split("?");
147
+ if (!filter(id)) {
148
+ return null;
149
+ }
150
+ const result = await compile(id, code, {
151
+ ...(mode === "server" ? serverOptions : clientOptions),
152
+ mode,
153
+ env,
154
+ });
155
+ if (result.valid) {
156
+ const preloader = preload[mode];
157
+ if (preloader) {
158
+ preloader.defer();
159
+ }
160
+ invalidateModules(currentServer, mergeManifestRecord(manifest.server, new Set([id])), options.manifest);
161
+ return {
162
+ code: result.code || "",
163
+ map: result.map,
164
+ };
165
+ }
166
+ return null;
167
+ },
168
+ },
169
+ ];
170
+ }
@@ -0,0 +1,3 @@
1
+ import type * as babel from "@babel/core";
2
+ import type * as t from "@babel/types";
3
+ export declare function isStatementTopLevel(path: babel.NodePath<t.Statement>): boolean;
@@ -0,0 +1,9 @@
1
+ export function isStatementTopLevel(path) {
2
+ let blockParent = path.scope.getBlockParent();
3
+ const programParent = path.scope.getProgramParent();
4
+ // a FunctionDeclaration binding refers to itself as the block parent
5
+ if (blockParent.path === path) {
6
+ blockParent = blockParent.parent;
7
+ }
8
+ return programParent === blockParent;
9
+ }
@@ -0,0 +1,9 @@
1
+ import type * as t from "@babel/types";
2
+ type TypeFilter<V extends t.Node> = (node: t.Node) => node is V;
3
+ export declare function isPathValid<V extends t.Node>(path: unknown, key: TypeFilter<V>): path is babel.NodePath<V>;
4
+ export type NestedExpression = t.ParenthesizedExpression | t.TypeCastExpression | t.TSAsExpression | t.TSSatisfiesExpression | t.TSNonNullExpression | t.TSInstantiationExpression | t.TSTypeAssertion;
5
+ export declare function isNestedExpression(node: t.Node): node is NestedExpression;
6
+ type TypeCheck<K> = K extends TypeFilter<infer U> ? U : never;
7
+ export declare function unwrapNode<K extends (value: t.Node) => boolean>(node: t.Node, key: K): TypeCheck<K> | undefined;
8
+ export declare function unwrapPath<V extends t.Node>(path: unknown, key: TypeFilter<V>): babel.NodePath<V> | undefined;
9
+ export {};
@@ -0,0 +1,36 @@
1
+ export function isPathValid(path, key) {
2
+ const node = path.node;
3
+ return node ? key(node) : false;
4
+ }
5
+ export function isNestedExpression(node) {
6
+ switch (node.type) {
7
+ case "ParenthesizedExpression":
8
+ case "TypeCastExpression":
9
+ case "TSAsExpression":
10
+ case "TSSatisfiesExpression":
11
+ case "TSNonNullExpression":
12
+ case "TSTypeAssertion":
13
+ case "TSInstantiationExpression":
14
+ return true;
15
+ default:
16
+ return false;
17
+ }
18
+ }
19
+ export function unwrapNode(node, key) {
20
+ if (key(node)) {
21
+ return node;
22
+ }
23
+ if (isNestedExpression(node)) {
24
+ return unwrapNode(node.expression, key);
25
+ }
26
+ return undefined;
27
+ }
28
+ export function unwrapPath(path, key) {
29
+ if (isPathValid(path, key)) {
30
+ return path;
31
+ }
32
+ if (isPathValid(path, isNestedExpression)) {
33
+ return unwrapPath(path.get("expression"), key);
34
+ }
35
+ return undefined;
36
+ }
@@ -0,0 +1,21 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ import type { ImportDefinition } from "./types.ts";
4
+ export interface StateContext {
5
+ env: "production" | "development";
6
+ mode: "server" | "client";
7
+ directive: string;
8
+ hash: string;
9
+ count: number;
10
+ imports: Map<string, t.Identifier>;
11
+ valid: boolean;
12
+ definitions: {
13
+ register: ImportDefinition;
14
+ clone: ImportDefinition;
15
+ };
16
+ }
17
+ interface State extends babel.PluginPass {
18
+ opts: StateContext;
19
+ }
20
+ export declare function directivesPlugin(): babel.PluginObj<State>;
21
+ export {};
@@ -0,0 +1,302 @@
1
+ import * as t from "@babel/types";
2
+ import { bubbleFunctionDeclaration } from "./bubble-function-declaration.js";
3
+ import { generateUniqueName } from "./generate-unique-name.js";
4
+ import { getDescriptiveName } from "./get-descriptive-name.js";
5
+ import { getImportIdentifier } from "./get-import-identifier.js";
6
+ import { getRootStatementPath } from "./get-root-statement-path.js";
7
+ import { isStatementTopLevel } from "./is-statement-top-level.js";
8
+ import { isPathValid, unwrapPath } from "./paths.js";
9
+ import { removeUnusedVariables } from "./remove-unused-variables.js";
10
+ function isValidFunction(node) {
11
+ return t.isArrowFunctionExpression(node) || t.isFunctionExpression(node);
12
+ }
13
+ function isDirectiveValid(ctx, directives) {
14
+ for (let i = 0, len = directives.length; i < len; i++) {
15
+ if (directives[i].value.value === ctx.directive) {
16
+ return true;
17
+ }
18
+ }
19
+ return false;
20
+ }
21
+ function cleanDirectives(path, target) {
22
+ const newDirectives = [];
23
+ for (let i = 0, len = path.node.directives.length; i < len; i++) {
24
+ const current = path.node.directives[i];
25
+ if (current.value.value !== target) {
26
+ newDirectives.push(current);
27
+ }
28
+ }
29
+ path.node.directives = newDirectives;
30
+ }
31
+ function cleanFunctionDirectives(ctx, path) {
32
+ const body = path.get("body");
33
+ if (isPathValid(body, t.isBlockStatement)) {
34
+ cleanDirectives(body, ctx.directive);
35
+ }
36
+ }
37
+ function isFunctionDirectiveValid(ctx, path) {
38
+ const body = path.get("body");
39
+ if (isPathValid(body, t.isBlockStatement)) {
40
+ return isDirectiveValid(ctx, body.node.directives);
41
+ }
42
+ return false;
43
+ }
44
+ function createID(ctx, name) {
45
+ const base = `${ctx.hash}-${ctx.count++}`;
46
+ if (ctx.env === "development") {
47
+ return `${base}-${name}`;
48
+ }
49
+ return base;
50
+ }
51
+ function transformFunction(ctx, path, direct) {
52
+ if (!direct) {
53
+ if (!isFunctionDirectiveValid(ctx, path)) {
54
+ return;
55
+ }
56
+ cleanFunctionDirectives(ctx, path);
57
+ }
58
+ // First, get root statement
59
+ const rootStatement = getRootStatementPath(path);
60
+ // Create a unique ID for the function
61
+ const fnID = createID(ctx, getDescriptiveName(path, "anonymous"));
62
+ if (ctx.mode === "server") {
63
+ // Create a "source" function on the root-level
64
+ const sourceReference = t.callExpression(getImportIdentifier(ctx.imports, path, ctx.definitions.register), [t.stringLiteral(fnID), path.node]);
65
+ const sourceID = generateUniqueName(path, "serverFn");
66
+ rootStatement.insertBefore(t.variableDeclaration("const", [t.variableDeclarator(sourceID, sourceReference)]));
67
+ // Clone the source function to replace the server function
68
+ path.replaceWith(t.callExpression(getImportIdentifier(ctx.imports, path, ctx.definitions.clone), [sourceID]));
69
+ }
70
+ else {
71
+ // Otherwise, clone the function based on its ID
72
+ path.replaceWith(t.callExpression(getImportIdentifier(ctx.imports, path, ctx.definitions.clone), [
73
+ t.stringLiteral(fnID),
74
+ ]));
75
+ }
76
+ path.scope.crawl();
77
+ }
78
+ function traceBinding(path, name) {
79
+ const current = path.scope.getBinding(name);
80
+ if (!current) {
81
+ return undefined;
82
+ }
83
+ switch (current.kind) {
84
+ case "const":
85
+ case "let":
86
+ case "var": {
87
+ if (isPathValid(current.path, t.isVariableDeclarator)) {
88
+ // Check if left is identifier
89
+ const left = unwrapPath(current.path.get("id"), t.isIdentifier);
90
+ if (left) {
91
+ const right = unwrapPath(current.path.get("init"), t.isIdentifier);
92
+ if (right) {
93
+ return traceBinding(path, right.node.name);
94
+ }
95
+ // Only valid for functions
96
+ const func = unwrapPath(current.path.get("init"), isValidFunction);
97
+ if (func) {
98
+ return current;
99
+ }
100
+ }
101
+ }
102
+ return undefined;
103
+ }
104
+ case "hoisted":
105
+ case "local":
106
+ case "module":
107
+ case "param":
108
+ case "unknown":
109
+ return undefined;
110
+ }
111
+ }
112
+ function transformBindingForServer(ctx, binding) {
113
+ if (isPathValid(binding.path, t.isVariableDeclarator)) {
114
+ const right = unwrapPath(binding.path.get("init"), isValidFunction);
115
+ if (right) {
116
+ transformFunction(ctx, right, true);
117
+ }
118
+ }
119
+ }
120
+ function transformModuleLevelDirective(ctx, program) {
121
+ cleanDirectives(program, ctx.directive);
122
+ program.traverse({
123
+ FunctionDeclaration(child) {
124
+ // We only need to move top-level functions
125
+ if (isStatementTopLevel(child)) {
126
+ bubbleFunctionDeclaration(child);
127
+ }
128
+ },
129
+ });
130
+ program.scope.crawl();
131
+ if (ctx.mode === "server") {
132
+ // Trace bindings
133
+ const bindings = new Set();
134
+ program.traverse({
135
+ ExportDefaultDeclaration(path) {
136
+ const id = unwrapPath(path.get("declaration"), t.isIdentifier);
137
+ if (id) {
138
+ const binding = traceBinding(path, id.node.name);
139
+ if (binding) {
140
+ bindings.add(binding);
141
+ }
142
+ }
143
+ },
144
+ ExportNamedDeclaration(path) {
145
+ if (path.node.source || path.node.exportKind === "type") {
146
+ return;
147
+ }
148
+ for (const specifier of path.get("specifiers")) {
149
+ if (isPathValid(specifier, t.isExportSpecifier)) {
150
+ const binding = traceBinding(specifier, specifier.node.local.name);
151
+ if (binding) {
152
+ bindings.add(binding);
153
+ }
154
+ }
155
+ }
156
+ const declarations = path.get("declaration");
157
+ if (isPathValid(declarations, t.isVariableDeclaration)) {
158
+ for (const declaration of declarations.get("declarations")) {
159
+ // Check if left is identifier
160
+ const left = unwrapPath(declaration.get("id"), t.isIdentifier);
161
+ if (left) {
162
+ const binding = traceBinding(left, left.node.name);
163
+ if (binding) {
164
+ bindings.add(binding);
165
+ }
166
+ }
167
+ }
168
+ }
169
+ },
170
+ });
171
+ for (const binding of bindings) {
172
+ transformBindingForServer(ctx, binding);
173
+ }
174
+ }
175
+ else {
176
+ // Trace bindings
177
+ const uniqueBindings = new Set();
178
+ const exportedBindings = new Map();
179
+ program.traverse({
180
+ ExportDefaultDeclaration(path) {
181
+ const id = unwrapPath(path.get("declaration"), t.isIdentifier);
182
+ if (id) {
183
+ const binding = traceBinding(path, id.node.name);
184
+ if (binding) {
185
+ uniqueBindings.add(binding);
186
+ exportedBindings.set("default", binding);
187
+ }
188
+ }
189
+ },
190
+ ExportNamedDeclaration(path) {
191
+ if (path.node.source || path.node.exportKind === "type") {
192
+ return;
193
+ }
194
+ for (const specifier of path.get("specifiers")) {
195
+ if (isPathValid(specifier, t.isExportSpecifier)) {
196
+ const binding = traceBinding(specifier, specifier.node.local.name);
197
+ if (binding) {
198
+ const key = t.isIdentifier(specifier.node.exported)
199
+ ? specifier.node.exported.name
200
+ : specifier.node.exported.value;
201
+ uniqueBindings.add(binding);
202
+ exportedBindings.set(key, binding);
203
+ }
204
+ }
205
+ }
206
+ const declarations = path.get("declaration");
207
+ if (isPathValid(declarations, t.isVariableDeclaration)) {
208
+ for (const declaration of declarations.get("declarations")) {
209
+ // Check if left is identifier
210
+ const left = unwrapPath(declaration.get("id"), t.isIdentifier);
211
+ if (left) {
212
+ const binding = traceBinding(left, left.node.name);
213
+ if (binding) {
214
+ uniqueBindings.add(binding);
215
+ exportedBindings.set(left.node.name, binding);
216
+ }
217
+ }
218
+ }
219
+ }
220
+ },
221
+ });
222
+ // generate ids for each unique binding
223
+ const sourceIDs = new Map();
224
+ for (const binding of uniqueBindings) {
225
+ if (isPathValid(binding.path, t.isVariableDeclarator)) {
226
+ const init = unwrapPath(binding.path.get("init"), isValidFunction);
227
+ if (init) {
228
+ sourceIDs.set(binding, createID(ctx, getDescriptiveName(init, "anonymous")));
229
+ }
230
+ }
231
+ }
232
+ // clear body
233
+ program.node.body = [];
234
+ const declarations = [];
235
+ const specifiers = [];
236
+ const declarationMap = new Map();
237
+ // Declare all client functions
238
+ for (const [exported, binding] of exportedBindings) {
239
+ let currentIdentifier = declarationMap.get(binding);
240
+ if (!currentIdentifier) {
241
+ currentIdentifier = generateUniqueName(program, "fn");
242
+ const fnID = sourceIDs.get(binding);
243
+ if (fnID) {
244
+ declarations.push(t.variableDeclarator(currentIdentifier, t.callExpression(getImportIdentifier(ctx.imports, program, ctx.definitions.clone), [
245
+ t.stringLiteral(fnID),
246
+ ])));
247
+ declarationMap.set(binding, currentIdentifier);
248
+ }
249
+ }
250
+ if (currentIdentifier) {
251
+ specifiers.push(t.exportSpecifier(currentIdentifier, t.stringLiteral(exported)));
252
+ }
253
+ }
254
+ const body = [];
255
+ if (declarations.length > 0) {
256
+ body.push(t.variableDeclaration("const", declarations));
257
+ }
258
+ if (specifiers.length > 0) {
259
+ body.push(t.exportNamedDeclaration(null, specifiers, null));
260
+ }
261
+ program.pushContainer("body", body);
262
+ }
263
+ }
264
+ export function directivesPlugin() {
265
+ return {
266
+ name: "solid-start:directives",
267
+ visitor: {
268
+ Program(program, ctx) {
269
+ const isModuleLevel = isDirectiveValid(ctx.opts, program.node.directives);
270
+ if (isModuleLevel) {
271
+ transformModuleLevelDirective(ctx.opts, program);
272
+ ctx.opts.valid = true;
273
+ }
274
+ else {
275
+ // First, bubble up function declarations
276
+ program.traverse({
277
+ FunctionDeclaration(child) {
278
+ // if (isFunctionDirectiveValid(ctx.opts, child)) {
279
+ bubbleFunctionDeclaration(child);
280
+ // }
281
+ },
282
+ });
283
+ program.scope.crawl();
284
+ // Now we transform each function
285
+ program.traverse({
286
+ ArrowFunctionExpression(path) {
287
+ transformFunction(ctx.opts, path, false);
288
+ },
289
+ FunctionExpression(path) {
290
+ transformFunction(ctx.opts, path, false);
291
+ },
292
+ });
293
+ program.scope.crawl();
294
+ if (ctx.opts.count > 0) {
295
+ ctx.opts.valid = true;
296
+ removeUnusedVariables(program);
297
+ }
298
+ }
299
+ },
300
+ },
301
+ };
302
+ }
@@ -0,0 +1,3 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ export declare function removeUnusedVariables(program: babel.NodePath<t.Program>): void;