@solidjs/start 2.0.0-beta.9 → 2.0.0-rc.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 (126) hide show
  1. package/CHANGELOG.md +149 -1
  2. package/dist/config/app-root-alias.d.ts +7 -0
  3. package/dist/config/app-root-alias.js +58 -0
  4. package/dist/config/constants.d.ts +2 -0
  5. package/dist/config/constants.js +2 -0
  6. package/dist/config/env.js +13 -10
  7. package/dist/config/fs-routes/index.js +3 -3
  8. package/dist/config/fs-routes/tree-shake.d.ts +27 -0
  9. package/dist/config/fs-routes/tree-shake.js +226 -33
  10. package/dist/config/index.d.ts +154 -5
  11. package/dist/config/index.js +23 -10
  12. package/dist/config/lazy.js +7 -2
  13. package/dist/config/manifest.d.ts +3 -0
  14. package/dist/config/manifest.js +26 -4
  15. package/dist/directives/remove-unused-variables.js +15 -3
  16. package/dist/directives/xxhash32.js +5 -13
  17. package/dist/fns/client.js +14 -5
  18. package/dist/fns/error-handler.d.ts +34 -0
  19. package/dist/fns/error-handler.js +10 -0
  20. package/dist/fns/handler.d.ts +1 -1
  21. package/dist/fns/handler.js +58 -12
  22. package/dist/fns/plugins.d.ts +34 -0
  23. package/dist/fns/plugins.js +33 -0
  24. package/dist/fns/serialization.d.ts +15 -0
  25. package/dist/fns/serialization.js +36 -6
  26. package/dist/middleware/index.js +4 -1
  27. package/dist/server/StartServer.jsx +1 -1
  28. package/dist/server/assets/render.jsx +1 -1
  29. package/dist/server/collect-styles.d.ts +3 -1
  30. package/dist/server/collect-styles.js +8 -5
  31. package/dist/server/fetchEvent.d.ts +10 -0
  32. package/dist/server/fetchEvent.js +10 -0
  33. package/dist/server/handler.d.ts +3 -4
  34. package/dist/server/handler.js +22 -56
  35. package/dist/server/index.d.ts +3 -1
  36. package/dist/server/index.jsx +1 -0
  37. package/dist/server/manifest/dev-client-manifest.js +1 -1
  38. package/dist/server/manifest/dev-ssr-manifest.js +1 -1
  39. package/dist/server/spa/StartServer.jsx +1 -1
  40. package/dist/server/spa/handler.d.ts +2 -3
  41. package/dist/server/spa/handler.js +2 -2
  42. package/dist/server/strip-path-base.d.ts +1 -0
  43. package/dist/server/strip-path-base.js +10 -0
  44. package/dist/server/types.d.ts +12 -1
  45. package/dist/server/web-stream.d.ts +9 -0
  46. package/dist/server/web-stream.js +29 -0
  47. package/dist/shared/ErrorBoundary.jsx +3 -3
  48. package/dist/shared/clientOnly.js +3 -1
  49. package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.jsx +3 -3
  50. package/dist/shared/dev-toolbar/error-viewer/create-stack-frame.js +90 -0
  51. package/dist/shared/{dev-overlay/DevOverlayDialog.d.ts → dev-toolbar/error-viewer/index.d.ts} +3 -2
  52. package/dist/shared/{dev-overlay/DevOverlayDialog.jsx → dev-toolbar/error-viewer/index.jsx} +66 -77
  53. package/dist/shared/dev-toolbar/error-viewer/styles.css +224 -0
  54. package/dist/shared/dev-toolbar/functions/BlobViewer.css +4 -0
  55. package/dist/shared/dev-toolbar/functions/BlobViewer.d.ts +6 -0
  56. package/dist/shared/dev-toolbar/functions/BlobViewer.jsx +37 -0
  57. package/dist/shared/dev-toolbar/functions/FormDataViewer.d.ts +5 -0
  58. package/dist/shared/dev-toolbar/functions/FormDataViewer.jsx +23 -0
  59. package/dist/shared/dev-toolbar/functions/HeadersViewer.css +8 -0
  60. package/dist/shared/dev-toolbar/functions/HeadersViewer.d.ts +6 -0
  61. package/dist/shared/dev-toolbar/functions/HeadersViewer.jsx +15 -0
  62. package/dist/shared/dev-toolbar/functions/HexViewer.css +34 -0
  63. package/dist/shared/dev-toolbar/functions/HexViewer.d.ts +11 -0
  64. package/dist/shared/dev-toolbar/functions/HexViewer.jsx +70 -0
  65. package/dist/shared/dev-toolbar/functions/SerovalValue.css +5 -0
  66. package/dist/shared/dev-toolbar/functions/SerovalValue.d.ts +7 -0
  67. package/dist/shared/dev-toolbar/functions/SerovalValue.jsx +10 -0
  68. package/dist/shared/dev-toolbar/functions/SerovalViewer.css +70 -0
  69. package/dist/shared/dev-toolbar/functions/SerovalViewer.d.ts +6 -0
  70. package/dist/shared/dev-toolbar/functions/SerovalViewer.jsx +796 -0
  71. package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.d.ts +5 -0
  72. package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.jsx +22 -0
  73. package/dist/shared/dev-toolbar/functions/index.d.ts +13 -0
  74. package/dist/shared/dev-toolbar/functions/index.jsx +216 -0
  75. package/dist/shared/dev-toolbar/functions/styles.css +109 -0
  76. package/dist/shared/dev-toolbar/functions/tracker.d.ts +19 -0
  77. package/dist/shared/dev-toolbar/functions/tracker.js +29 -0
  78. package/dist/shared/{dev-overlay → dev-toolbar}/icons.d.ts +9 -0
  79. package/dist/shared/{dev-overlay → dev-toolbar}/icons.jsx +19 -1
  80. package/dist/shared/dev-toolbar/index.css +88 -0
  81. package/dist/shared/dev-toolbar/index.d.ts +6 -0
  82. package/dist/shared/dev-toolbar/index.jsx +179 -0
  83. package/dist/shared/ui/Badge.css +33 -0
  84. package/dist/shared/ui/Badge.d.ts +7 -0
  85. package/dist/shared/ui/Badge.jsx +7 -0
  86. package/dist/shared/ui/Button.css +32 -0
  87. package/dist/shared/ui/Button.d.ts +4 -0
  88. package/dist/shared/ui/Button.jsx +4 -0
  89. package/dist/shared/ui/Cascade.css +29 -0
  90. package/dist/shared/ui/Cascade.d.ts +4 -0
  91. package/dist/shared/ui/Cascade.jsx +4 -0
  92. package/dist/shared/ui/Dialog.css +25 -0
  93. package/dist/shared/ui/Dialog.d.ts +5 -0
  94. package/dist/shared/ui/Dialog.jsx +5 -0
  95. package/dist/shared/ui/IconButton.css +39 -0
  96. package/dist/shared/ui/IconButton.d.ts +4 -0
  97. package/dist/shared/ui/IconButton.jsx +4 -0
  98. package/dist/shared/ui/Placeholder.css +12 -0
  99. package/dist/shared/ui/Placeholder.d.ts +6 -0
  100. package/dist/shared/ui/Placeholder.jsx +4 -0
  101. package/dist/shared/ui/Section.css +18 -0
  102. package/dist/shared/ui/Section.d.ts +9 -0
  103. package/dist/shared/ui/Section.jsx +10 -0
  104. package/dist/shared/ui/Select.css +37 -0
  105. package/dist/shared/ui/Select.d.ts +4 -0
  106. package/dist/shared/ui/Select.jsx +4 -0
  107. package/dist/shared/ui/Table.css +22 -0
  108. package/dist/shared/ui/Table.d.ts +11 -0
  109. package/dist/shared/ui/Table.jsx +13 -0
  110. package/dist/shared/ui/Tabs.css +51 -0
  111. package/dist/shared/ui/Tabs.d.ts +6 -0
  112. package/dist/shared/ui/Tabs.jsx +6 -0
  113. package/dist/shared/ui/Text.css +73 -0
  114. package/dist/shared/ui/Text.d.ts +12 -0
  115. package/dist/shared/ui/Text.jsx +17 -0
  116. package/package.json +36 -29
  117. package/dist/shared/dev-overlay/createStackFrame.js +0 -56
  118. package/dist/shared/dev-overlay/index.d.ts +0 -5
  119. package/dist/shared/dev-overlay/index.jsx +0 -39
  120. package/dist/shared/dev-overlay/styles.css +0 -292
  121. /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.d.ts +0 -0
  122. /package/dist/shared/{dev-overlay/createStackFrame.d.ts → dev-toolbar/error-viewer/create-stack-frame.d.ts} +0 -0
  123. /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.d.ts +0 -0
  124. /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.js +0 -0
  125. /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.d.ts +0 -0
  126. /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.js +0 -0
@@ -1,7 +1,52 @@
1
1
  // All credit for this work goes to the amazing Next.js team.
2
2
  // https://github.com/vercel/next.js/blob/canary/packages/next/build/babel/plugins/next-ssg-transform.ts
3
3
  // This is adapted to work with routeData functions. It can be run in two modes, one which preserves the routeData and the Component in the same file, and one which creates a
4
- import { basename } from "pathe";
4
+ import { basename, extname } from "pathe";
5
+ const PICKABLE_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
6
+ /**
7
+ * Builds the module id used to import a subset of a route file's exports.
8
+ *
9
+ * The `pick` list has to live in the query so that the same file can be
10
+ * instantiated once per export subset (the client picks `default`/`$css`,
11
+ * the server picks its HTTP handlers). That query would otherwise leave the
12
+ * id ending in `?pick=GET`, which silently excludes route files from any
13
+ * plugin whose filter is anchored on the file extension -- a very common
14
+ * default, e.g. unplugin-macros' `/\.[cm]?[jt]sx?$/`.
15
+ *
16
+ * The trailing `lang.<ext>` marker is the same convention Vue SFCs use
17
+ * (`?vue&type=script&lang.ts`) and puts a real extension back at the end of
18
+ * the id, so those filters match again.
19
+ *
20
+ * @see https://github.com/solidjs/solid-start/issues/1918
21
+ */
22
+ export function toPickId(src, pick) {
23
+ const query = pick.map(p => `pick=${p}`).join("&");
24
+ const ext = extname(src).slice(1);
25
+ return PICKABLE_EXTENSIONS.includes(ext) ? `${src}?${query}&lang.${ext}` : `${src}?${query}`;
26
+ }
27
+ /**
28
+ * Matches the tail that {@link toPickId} appends, as it appears in a chunk
29
+ * name. Rolldown derives a chunk name from the module id by taking the
30
+ * basename minus its extension, so `index.tsx?pick=default&pick=$css&lang.tsx`
31
+ * arrives here as `index.tsx?pick=default&pick=$css&lang`.
32
+ */
33
+ const PICK_CHUNK_NAME_RE = /\.[cm]?[jt]sx?\?pick=[^?]*&lang$/;
34
+ const INVALID_CHAR_RE = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
35
+ const DRIVE_LETTER_RE = /^[a-z]:/i;
36
+ /**
37
+ * Rolldown's default chunk name sanitizer, plus a pass that drops the
38
+ * `?pick=...&lang` tail so route chunks keep the short, stable filenames they
39
+ * had before the `lang` marker was introduced (`index-<hash>.js`, not
40
+ * `index.tsx_pick_default_pick__css_lang-<hash>.js`). Client chunk filenames
41
+ * are public URLs, so this is not purely cosmetic.
42
+ *
43
+ * @see https://github.com/rollup/rollup/blob/master/src/utils/sanitizeFileName.ts
44
+ */
45
+ export function sanitizeChunkFileName(name) {
46
+ const stripped = name.replace(PICK_CHUNK_NAME_RE, "");
47
+ const driveLetter = DRIVE_LETTER_RE.exec(stripped)?.[0] ?? "";
48
+ return driveLetter + stripped.slice(driveLetter.length).replace(INVALID_CHAR_RE, "_");
49
+ }
5
50
  function treeShakeTransform({ types: t }) {
6
51
  function getIdentifier(path) {
7
52
  const parentPath = path.parentPath;
@@ -20,13 +65,28 @@ function treeShakeTransform({ types: t }) {
20
65
  }
21
66
  return path.node.id && path.node.id.type === "Identifier" ? path.get("id") : null;
22
67
  }
23
- function isIdentifierReferenced(ident) {
68
+ function isTypeOnlyReference(path) {
69
+ return path.getAncestry().some(parent => {
70
+ if (parent.isTSType())
71
+ return true;
72
+ if (parent.isExportNamedDeclaration())
73
+ return parent.node.exportKind === "type";
74
+ if (parent.isExportSpecifier())
75
+ return parent.node.exportKind === "type";
76
+ return false;
77
+ });
78
+ }
79
+ function runtimeReferences(binding) {
80
+ return binding.referencePaths.filter(ref => !isTypeOnlyReference(ref));
81
+ }
82
+ function isIdentifierReferenced(ident, includeTypes = false) {
24
83
  const b = ident.scope.getBinding(ident.node.name);
25
- if (b?.referenced) {
84
+ if (b) {
85
+ const references = b.constantViolations.concat(includeTypes ? b.referencePaths : runtimeReferences(b));
86
+ if (!references.length)
87
+ return false;
26
88
  if (b.path.type === "FunctionDeclaration") {
27
- return !b.constantViolations
28
- .concat(b.referencePaths)
29
- .every(ref => ref.findParent(p => p === b.path));
89
+ return !references.every(ref => ref.findParent(p => p === b.path));
30
90
  }
31
91
  return true;
32
92
  }
@@ -34,13 +94,13 @@ function treeShakeTransform({ types: t }) {
34
94
  }
35
95
  function markFunction(path, state) {
36
96
  const ident = getIdentifier(path);
37
- if (ident && ident.node && isIdentifierReferenced(ident)) {
97
+ if (ident && ident.node && isIdentifierReferenced(ident, true)) {
38
98
  state.refs.add(ident);
39
99
  }
40
100
  }
41
101
  function markImport(path, state) {
42
102
  const local = path.get("local");
43
- if (isIdentifierReferenced(local)) {
103
+ if (isIdentifierReferenced(local, true)) {
44
104
  state.refs.add(local);
45
105
  }
46
106
  }
@@ -49,12 +109,13 @@ function treeShakeTransform({ types: t }) {
49
109
  Program: {
50
110
  enter(path, state) {
51
111
  state.refs = new Set();
112
+ state.candidates = new Set();
52
113
  state.done = false;
53
114
  path.traverse({
54
115
  VariableDeclarator(variablePath, variableState) {
55
116
  if (variablePath.node.id.type === "Identifier") {
56
117
  const local = variablePath.get("id");
57
- if (isIdentifierReferenced(local)) {
118
+ if (isIdentifierReferenced(local, true)) {
58
119
  variableState.refs.add(local);
59
120
  }
60
121
  }
@@ -69,7 +130,7 @@ function treeShakeTransform({ types: t }) {
69
130
  : (() => {
70
131
  throw new Error("invariant");
71
132
  })());
72
- if (isIdentifierReferenced(local)) {
133
+ if (isIdentifierReferenced(local, true)) {
73
134
  variableState.refs.add(local);
74
135
  }
75
136
  });
@@ -88,29 +149,46 @@ function treeShakeTransform({ types: t }) {
88
149
  else {
89
150
  return;
90
151
  }
91
- if (isIdentifierReferenced(local)) {
152
+ if (isIdentifierReferenced(local, true)) {
92
153
  variableState.refs.add(local);
93
154
  }
94
155
  });
95
156
  }
96
157
  },
97
158
  ExportDefaultDeclaration(exportNamedPath) {
98
- // if opts.keep is true, we don't remove the routeData export
99
159
  if (state.opts.pick && !state.opts.pick.includes("default")) {
100
- exportNamedPath.remove();
160
+ const decl = exportNamedPath.node.declaration;
161
+ // A named function/class declaration creates a module-scope
162
+ // binding that picked exports may reference, so only strip
163
+ // the `export default`; the sweep below removes the
164
+ // declaration again if nothing references it.
165
+ if ((t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) && decl.id) {
166
+ const [newPath] = exportNamedPath.replaceWith(decl);
167
+ const id = newPath.get("id");
168
+ state.refs.add(id);
169
+ state.candidates.add(id);
170
+ }
171
+ else {
172
+ exportNamedPath.remove();
173
+ }
101
174
  }
102
175
  },
103
176
  ExportNamedDeclaration(exportNamedPath) {
104
- // if opts.keep is false, we don't remove the routeData export
177
+ // No pick list means nothing gets pruned.
105
178
  if (!state.opts.pick) {
106
179
  return;
107
180
  }
181
+ // Only module-level exports are route exports; `export` inside a
182
+ // TS namespace/module block is unrelated to the pick list.
183
+ if (!exportNamedPath.parentPath.isProgram()) {
184
+ return;
185
+ }
108
186
  const specifiers = exportNamedPath.get("specifiers");
109
187
  if (specifiers.length) {
110
188
  specifiers.forEach(s => {
111
- if (t.isIdentifier(s.node.exported)
112
- ? s.node.exported.name
113
- : state.opts.pick.includes(s.node.exported.value)) {
189
+ const exported = s.node.exported;
190
+ const exportedName = t.isIdentifier(exported) ? exported.name : exported.value;
191
+ if (!state.opts.pick.includes(exportedName)) {
114
192
  s.remove();
115
193
  }
116
194
  });
@@ -124,24 +202,51 @@ function treeShakeTransform({ types: t }) {
124
202
  return;
125
203
  }
126
204
  switch (decl.node.type) {
127
- case "FunctionDeclaration": {
205
+ case "FunctionDeclaration":
206
+ case "ClassDeclaration": {
128
207
  const name = decl.node.id?.name;
129
208
  if (name && state.opts.pick && !state.opts.pick.includes(name)) {
130
- exportNamedPath.remove();
209
+ // Keep the declaration in module scope since picked
210
+ // exports may reference it; the sweep below removes it
211
+ // again if unreferenced.
212
+ const [newPath] = exportNamedPath.replaceWith(decl.node);
213
+ const id = newPath.get("id");
214
+ state.refs.add(id);
215
+ state.candidates.add(id);
131
216
  }
132
217
  break;
133
218
  }
134
219
  case "VariableDeclaration": {
135
- const inner = decl.get("declarations");
136
- inner.forEach(d => {
137
- if (d.node.id.type !== "Identifier") {
138
- return;
139
- }
140
- const name = d.node.id.name;
141
- if (state.opts.pick && !state.opts.pick.includes(name)) {
142
- d.remove();
143
- }
220
+ const declNode = decl.node;
221
+ // Destructuring declarators are conservatively treated as
222
+ // picked (matching the previous behavior of leaving them
223
+ // untouched).
224
+ const isPicked = (d) => d.id.type !== "Identifier" || state.opts.pick.includes(d.id.name);
225
+ if (declNode.declarations.every(isPicked)) {
226
+ break;
227
+ }
228
+ // Split into one declaration per declarator (preserving
229
+ // evaluation order) and export only the picked ones.
230
+ // Unpicked bindings are kept since picked exports may
231
+ // reference them; the sweep below removes them again if
232
+ // unreferenced.
233
+ const statements = declNode.declarations.map(d => {
234
+ const single = t.variableDeclaration(declNode.kind, [d]);
235
+ single.declare = declNode.declare;
236
+ return isPicked(d) ? t.exportNamedDeclaration(single, []) : single;
144
237
  });
238
+ const newPaths = exportNamedPath.replaceWithMultiple(statements);
239
+ for (const p of newPaths) {
240
+ if (!p.isVariableDeclaration())
241
+ continue;
242
+ for (const d of p.get("declarations")) {
243
+ if (d.node.id.type === "Identifier") {
244
+ const id = d.get("id");
245
+ state.refs.add(id);
246
+ state.candidates.add(id);
247
+ }
248
+ }
249
+ }
145
250
  break;
146
251
  }
147
252
  default: {
@@ -152,6 +257,8 @@ function treeShakeTransform({ types: t }) {
152
257
  FunctionDeclaration: markFunction,
153
258
  FunctionExpression: markFunction,
154
259
  ArrowFunctionExpression: markFunction,
260
+ ClassDeclaration: markFunction,
261
+ ClassExpression: markFunction,
155
262
  ImportSpecifier: markImport,
156
263
  ImportDefaultSpecifier: markImport,
157
264
  ImportNamespaceSpecifier: markImport,
@@ -163,11 +270,95 @@ function treeShakeTransform({ types: t }) {
163
270
  }
164
271
  },
165
272
  }, state);
273
+ // References alone cannot distinguish live bindings from dead cycles.
274
+ // Build a graph of localized exports and retain only those reachable
275
+ // from runtime code outside that graph.
276
+ path.scope.crawl();
277
+ const tracked = new Map();
278
+ const candidateOwners = new Map();
279
+ const addOwner = (owners, binding, owner) => {
280
+ const paths = owners.get(binding) ?? new Set();
281
+ paths.add(owner);
282
+ owners.set(binding, paths);
283
+ };
284
+ for (const identifier of state.refs) {
285
+ if (identifier.node?.type !== "Identifier" || !identifier.parentPath)
286
+ continue;
287
+ const binding = identifier.scope.getBinding(identifier.node.name);
288
+ if (binding)
289
+ addOwner(tracked, binding, identifier.parentPath);
290
+ }
291
+ for (const identifier of state.candidates) {
292
+ if (!identifier.parentPath)
293
+ continue;
294
+ const binding = identifier.scope.getBinding(identifier.node.name);
295
+ if (!binding)
296
+ continue;
297
+ addOwner(tracked, binding, identifier.parentPath);
298
+ addOwner(candidateOwners, binding, identifier.parentPath);
299
+ }
300
+ const dependencies = new Map();
301
+ const live = new Set();
302
+ for (const [binding, owners] of tracked) {
303
+ dependencies.set(binding, new Set());
304
+ if ([...owners].some(owner => owner.findParent(parent => parent.isExportNamedDeclaration() || parent.isExportDefaultDeclaration()))) {
305
+ live.add(binding);
306
+ }
307
+ }
308
+ const ownerBindings = new Map();
309
+ for (const [binding, owners] of tracked) {
310
+ for (const owner of owners) {
311
+ ownerBindings.set(owner, binding);
312
+ }
313
+ }
314
+ const owningBinding = (reference) => {
315
+ const owner = reference.find(parent => ownerBindings.has(parent));
316
+ return owner && ownerBindings.get(owner);
317
+ };
318
+ for (const target of tracked.keys()) {
319
+ const references = target.constantViolations.concat(runtimeReferences(target));
320
+ for (const reference of references) {
321
+ const source = owningBinding(reference);
322
+ if (source)
323
+ dependencies.get(source)?.add(target);
324
+ else
325
+ live.add(target);
326
+ }
327
+ }
328
+ const pending = [...live];
329
+ while (pending.length) {
330
+ const source = pending.pop();
331
+ for (const dependency of dependencies.get(source) ?? []) {
332
+ if (live.has(dependency))
333
+ continue;
334
+ live.add(dependency);
335
+ pending.push(dependency);
336
+ }
337
+ }
338
+ const deadCandidates = new Set([...candidateOwners.keys()].filter(candidate => !live.has(candidate)));
339
+ path.traverse({
340
+ VariableDeclarator(variablePath) {
341
+ if (variablePath.node.id.type !== "Identifier")
342
+ return;
343
+ const binding = variablePath.scope.getBinding(variablePath.node.id.name);
344
+ if (binding && deadCandidates.has(binding))
345
+ variablePath.remove();
346
+ },
347
+ });
348
+ for (const [candidate, owners] of candidateOwners) {
349
+ if (!deadCandidates.has(candidate))
350
+ continue;
351
+ for (const owner of owners) {
352
+ if (!owner.removed && !owner.isVariableDeclarator())
353
+ owner.remove();
354
+ }
355
+ }
166
356
  const refs = state.refs;
357
+ const refNodes = new Set([...refs].map(ref => ref.node));
167
358
  let count = 0;
168
359
  const sweepFunction = (sweepPath) => {
169
360
  const ident = getIdentifier(sweepPath);
170
- if (ident && ident.node && refs.has(ident) && !isIdentifierReferenced(ident)) {
361
+ if (ident && ident.node && refNodes.has(ident.node) && !isIdentifierReferenced(ident)) {
171
362
  ++count;
172
363
  if (t.isAssignmentExpression(sweepPath.parentPath) ||
173
364
  t.isVariableDeclarator(sweepPath.parentPath)) {
@@ -180,7 +371,7 @@ function treeShakeTransform({ types: t }) {
180
371
  };
181
372
  function sweepImport(sweepPath) {
182
373
  const local = sweepPath.get("local");
183
- if (refs.has(local) && !isIdentifierReferenced(local)) {
374
+ if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
184
375
  ++count;
185
376
  sweepPath.remove();
186
377
  if (sweepPath.parent.specifiers.length === 0) {
@@ -195,7 +386,7 @@ function treeShakeTransform({ types: t }) {
195
386
  VariableDeclarator(variablePath) {
196
387
  if (variablePath.node.id.type === "Identifier") {
197
388
  const local = variablePath.get("id");
198
- if (refs.has(local) && !isIdentifierReferenced(local)) {
389
+ if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
199
390
  ++count;
200
391
  variablePath.remove();
201
392
  }
@@ -212,7 +403,7 @@ function treeShakeTransform({ types: t }) {
212
403
  : (() => {
213
404
  throw new Error("invariant");
214
405
  })());
215
- if (refs.has(local) && !isIdentifierReferenced(local)) {
406
+ if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
216
407
  ++count;
217
408
  p.remove();
218
409
  }
@@ -236,7 +427,7 @@ function treeShakeTransform({ types: t }) {
236
427
  else {
237
428
  return;
238
429
  }
239
- if (refs.has(local) && !isIdentifierReferenced(local)) {
430
+ if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
240
431
  ++count;
241
432
  e.remove();
242
433
  }
@@ -249,6 +440,8 @@ function treeShakeTransform({ types: t }) {
249
440
  FunctionDeclaration: sweepFunction,
250
441
  FunctionExpression: sweepFunction,
251
442
  ArrowFunctionExpression: sweepFunction,
443
+ ClassDeclaration: sweepFunction,
444
+ ClassExpression: sweepFunction,
252
445
  ImportSpecifier: sweepImport,
253
446
  ImportDefaultSpecifier: sweepImport,
254
447
  ImportNamespaceSpecifier: sweepImport,
@@ -1,25 +1,174 @@
1
- import type { PluginOption } from "vite";
1
+ import type { PluginOption, FilterPattern } from "vite";
2
2
  import { type Options as SolidOptions } from "vite-plugin-solid";
3
3
  import { type ServerFunctionsOptions } from "../directives/index.ts";
4
4
  import { type EnvPluginOptions } from "./env.ts";
5
+ /**
6
+ * Configuration options for SolidStart. (previously in `app.config.ts`)
7
+ *
8
+ * @see https://docs.solidjs.com/solid-start/v2/migrating-from-v1#move-framework-configuration-into-viteconfigts
9
+ */
5
10
  export interface SolidStartOptions {
11
+ /**
12
+ * Path to the root of the application (where `app.tsx` / `app.jsx` lives).
13
+ *
14
+ * @default "./src"
15
+ */
16
+ appRoot?: string;
17
+ /**
18
+ * Options related to the css crawling logic
19
+ */
20
+ css?: {
21
+ /**
22
+ * Filter files included during css crawling in development.
23
+ */
24
+ filter?: {
25
+ include?: FilterPattern;
26
+ exclude?: FilterPattern;
27
+ };
28
+ };
29
+ /**
30
+ * Options forwarded to `vite-plugin-solid`.
31
+ *
32
+ * @see https://github.com/solidjs/vite-plugin-solid#api
33
+ */
6
34
  solid?: Partial<SolidOptions>;
35
+ /**
36
+ * Enable or disable server-side rendering.
37
+ *
38
+ * - `true` — SSR (default)
39
+ * - `false` — client-side rendering only (SPA mode)
40
+ *
41
+ * @default true
42
+ */
7
43
  ssr?: boolean;
44
+ /**
45
+ * Show the SolidStart development overlay (error overlay, etc.) in development.
46
+ *
47
+ * @default true
48
+ */
49
+ devOverlay?: boolean;
50
+ /**
51
+ * Experimental features.
52
+ */
53
+ experimental?: {
54
+ /**
55
+ * Enable islands architecture mode.
56
+ *
57
+ * Currently fixed to `false` (not yet fully supported).
58
+ *
59
+ * @default false
60
+ */
61
+ islands?: false;
62
+ };
63
+ /**
64
+ * Directory containing file-system routes, relative to {@link appRoot}.
65
+ *
66
+ * @default "./routes"
67
+ */
8
68
  routeDir?: string;
69
+ /**
70
+ * File extensions that should be treated as routes.
71
+ *
72
+ * @default ["js", "jsx", "ts", "tsx"]
73
+ */
9
74
  extensions?: string[];
75
+ /**
76
+ * Path to an optional middleware module.
77
+ *
78
+ * The module should export a middleware created with `createMiddleware`
79
+ * from `@solidjs/start/middleware`.
80
+ *
81
+ * @example "src/middleware/index.ts"
82
+ */
10
83
  middleware?: string;
84
+ /**
85
+ * Serialization settings for server-function / action payloads
86
+ * that cross the server-client boundary.
87
+ */
11
88
  serialization?: {
12
89
  /**
13
90
  * The serialization mode to use for server functions/actions.
14
- * The "js" mode uses a custom binary format that is more efficient than JSON, but requires a custom deserializer (with `eval()`) on the client.
15
- * A strong CSP should block `eval()` executions, which would prevent the "js" mode from working.
16
- * The "json" mode uses JSON for serialization, which is less efficient but can be deserialized with `JSON.parse` on the client.
91
+ *
92
+ * - `"js"` — Uses a custom binary format (Seroval) that is more efficient
93
+ * than JSON, but requires a custom deserializer (with `eval()`) on the client.
94
+ * A strong CSP that blocks `eval()` will prevent this mode from working.
95
+ * - `"json"` — Uses JSON for serialization. Less efficient / larger payloads,
96
+ * but can be deserialized with `JSON.parse` on the client and is CSP-friendly.
17
97
  *
18
98
  * @default "json"
19
99
  */
20
100
  mode?: "js" | "json";
101
+ /**
102
+ * Path to a module whose default export is an array of custom Seroval
103
+ * plugins, used to serialize values Seroval doesn't understand natively
104
+ * (ORM id types, decimals, `Temporal`, and other custom classes).
105
+ *
106
+ * Build plugins with `createPlugin` from `seroval`. The module is bundled
107
+ * into both the client and the server so that both ends of a server
108
+ * function agree on the format, so it must not import server-only code.
109
+ *
110
+ * SolidStart's built-in plugins take precedence: Seroval uses the first
111
+ * plugin whose `test()` passes, and these are appended after the built-ins.
112
+ *
113
+ * A plugin's `deserialize` rebuilds the value under {@link mode} `"json"`.
114
+ * `serialize` is only used by `mode: "js"`, where the payload is evaluated
115
+ * on the client and may therefore reference globals only, not the plugin
116
+ * module's own imports.
117
+ *
118
+ * Only applies to server-function and action payloads. The SSR hydration
119
+ * payload is serialized by `solid-js/web` and is unaffected.
120
+ *
121
+ * @example "src/seroval-plugins.ts"
122
+ */
123
+ plugins?: string;
21
124
  };
125
+ /**
126
+ * Configures plugin behavior per build environment
127
+ */
22
128
  env?: EnvPluginOptions;
23
- serverFunctions?: Pick<ServerFunctionsOptions, "filter">;
129
+ /**
130
+ * Options for server functions: which files the `"use server"` transform
131
+ * processes (inclusion / exclusion filters), and what happens when a server
132
+ * function throws.
133
+ */
134
+ serverFunctions?: Pick<ServerFunctionsOptions, "filter"> & {
135
+ /**
136
+ * Path to a module whose default export handles whatever a server function
137
+ * throws, before it reaches the client. Use it to report failures to a
138
+ * monitoring service, or to replace an error carrying internal detail with
139
+ * one that is safe to send.
140
+ *
141
+ * Only server function calls made over the network run through it. A
142
+ * server function called during rendering runs in process and throws
143
+ * straight to its caller, and errors from API routes never reach it
144
+ * either.
145
+ *
146
+ * The handler may be asynchronous. SolidStart awaits its return value
147
+ * before serializing the response, allowing a monitoring service to flush
148
+ * first. The resolved value decides what the client sees:
149
+ *
150
+ * - `undefined` (or `null`) sends what was thrown, unchanged.
151
+ * - A `Response` is passed through unchanged, which keeps a thrown
152
+ * `redirect()` working.
153
+ * - Any other value is sent in place of what was thrown, and the client
154
+ * call rejects with it.
155
+ * - If the handler throws or rejects, what the server function threw is
156
+ * sent unchanged.
157
+ *
158
+ * Control flow reaches the export the same way errors do, so a handler
159
+ * that replaces everything it sees turns redirects into errors.
160
+ *
161
+ * Whatever is sent gets serialized to the client along with its own
162
+ * properties, so an error meant to be safe to expose must not carry
163
+ * internal detail.
164
+ *
165
+ * Type the export as `ServerFunctionErrorHandler` from
166
+ * `@solidjs/start/server`. The module is bundled into the server only, so
167
+ * it may import server-only code such as a monitoring SDK.
168
+ *
169
+ * @example "src/server-fn-error.ts"
170
+ */
171
+ onError?: string;
172
+ };
24
173
  }
25
174
  export declare function solidStart(options?: SolidStartOptions): Array<PluginOption>;