rwsdk 0.2.0 → 0.3.1

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 (63) hide show
  1. package/dist/lib/constants.d.mts +6 -1
  2. package/dist/lib/constants.mjs +6 -1
  3. package/dist/lib/smokeTests/browser.mjs +5 -21
  4. package/dist/lib/smokeTests/codeUpdates.d.mts +1 -1
  5. package/dist/lib/smokeTests/codeUpdates.mjs +41 -5
  6. package/dist/lib/smokeTests/development.d.mts +1 -1
  7. package/dist/lib/smokeTests/development.mjs +4 -10
  8. package/dist/lib/smokeTests/release.d.mts +1 -1
  9. package/dist/lib/smokeTests/release.mjs +4 -9
  10. package/dist/lib/smokeTests/runSmokeTests.mjs +2 -2
  11. package/dist/lib/smokeTests/templates/SmokeTest.template.js +3 -2
  12. package/dist/lib/testUtils/stubEnvVars.d.mts +2 -0
  13. package/dist/lib/testUtils/stubEnvVars.mjs +11 -0
  14. package/dist/runtime/imports/client.js +4 -9
  15. package/dist/runtime/imports/worker.js +2 -1
  16. package/dist/runtime/register/ssr.js +2 -1
  17. package/dist/runtime/requestInfo/worker.js +9 -1
  18. package/dist/runtime/worker.d.ts +0 -3
  19. package/dist/runtime/worker.js +1 -10
  20. package/dist/scripts/debug-sync.mjs +0 -23
  21. package/dist/scripts/smoke-test.mjs +0 -10
  22. package/dist/vite/buildApp.d.mts +15 -0
  23. package/dist/vite/buildApp.mjs +53 -0
  24. package/dist/vite/configPlugin.d.mts +4 -4
  25. package/dist/vite/configPlugin.mjs +70 -76
  26. package/dist/vite/constants.d.mts +2 -0
  27. package/dist/vite/constants.mjs +12 -0
  28. package/dist/vite/createDirectiveLookupPlugin.d.mts +0 -6
  29. package/dist/vite/createDirectiveLookupPlugin.mjs +69 -145
  30. package/dist/vite/createViteAwareResolver.d.mts +4 -0
  31. package/dist/vite/createViteAwareResolver.mjs +208 -0
  32. package/dist/vite/directiveModulesDevPlugin.d.mts +8 -0
  33. package/dist/vite/directiveModulesDevPlugin.mjs +87 -0
  34. package/dist/vite/directivesFilteringPlugin.d.mts +6 -0
  35. package/dist/vite/directivesFilteringPlugin.mjs +31 -0
  36. package/dist/vite/directivesPlugin.mjs +32 -42
  37. package/dist/vite/getViteEsbuild.d.mts +1 -0
  38. package/dist/vite/getViteEsbuild.mjs +12 -0
  39. package/dist/vite/injectVitePreamblePlugin.d.mts +3 -2
  40. package/dist/vite/injectVitePreamblePlugin.mjs +8 -2
  41. package/dist/vite/linkerPlugin.d.mts +4 -0
  42. package/dist/vite/linkerPlugin.mjs +41 -0
  43. package/dist/vite/manifestPlugin.d.mts +2 -2
  44. package/dist/vite/manifestPlugin.mjs +20 -37
  45. package/dist/vite/moveStaticAssetsPlugin.mjs +2 -1
  46. package/dist/vite/prismaPlugin.mjs +1 -1
  47. package/dist/vite/reactConditionsResolverPlugin.mjs +15 -16
  48. package/dist/vite/redwoodPlugin.d.mts +0 -1
  49. package/dist/vite/redwoodPlugin.mjs +27 -9
  50. package/dist/vite/runDirectivesScan.d.mts +7 -0
  51. package/dist/vite/runDirectivesScan.mjs +156 -0
  52. package/dist/vite/ssrBridgePlugin.mjs +21 -14
  53. package/dist/vite/transformClientComponents.d.mts +0 -1
  54. package/dist/vite/transformClientComponents.mjs +1 -9
  55. package/dist/vite/transformJsxScriptTagsPlugin.d.mts +4 -3
  56. package/dist/vite/transformJsxScriptTagsPlugin.mjs +66 -84
  57. package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +67 -41
  58. package/dist/vite/transformServerFunctions.d.mts +1 -1
  59. package/dist/vite/transformServerFunctions.mjs +11 -12
  60. package/dist/vite/virtualPlugin.mjs +8 -0
  61. package/package.json +7 -1
  62. package/dist/runtime/clientNavigation.d.ts +0 -9
  63. package/dist/runtime/clientNavigation.js +0 -88
@@ -1,19 +1,16 @@
1
1
  import { Project, Node, SyntaxKind, } from "ts-morph";
2
- import { readFile } from "node:fs/promises";
3
- import { pathExists } from "fs-extra";
4
2
  import debug from "debug";
3
+ import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
5
4
  const log = debug("rwsdk:vite:transform-jsx-script-tags");
6
- let manifestCache;
7
- const readManifest = async (manifestPath) => {
8
- if (manifestCache === undefined) {
9
- const exists = await pathExists(manifestPath);
10
- if (!exists) {
11
- throw new Error(`RedwoodSDK expected client manifest to exist at ${manifestPath}. This is likely a bug. Please report it at https://github.com/redwoodjs/sdk/issues/new`);
12
- }
13
- manifestCache = JSON.parse(await readFile(manifestPath, "utf-8"));
5
+ function transformAssetPath(importPath, projectRootDir) {
6
+ if (process.env.VITE_IS_DEV_SERVER === "1") {
7
+ return importPath;
14
8
  }
15
- return manifestCache;
16
- };
9
+ const normalizedImportPath = normalizeModulePath(importPath, projectRootDir);
10
+ return `rwsdk_asset:${normalizedImportPath}`;
11
+ }
12
+ // Note: This plugin only runs during discovery phase (Phase 1)
13
+ // Manifest reading and asset linking happens later in Phase 5
17
14
  function hasJsxFunctions(text) {
18
15
  return (text.includes('jsx("script"') ||
19
16
  text.includes("jsx('script'") ||
@@ -28,7 +25,7 @@ function hasJsxFunctions(text) {
28
25
  text.includes('jsxDEV("link"') ||
29
26
  text.includes("jsxDEV('link'"));
30
27
  }
31
- function transformScriptImports(scriptContent, manifest) {
28
+ function transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir) {
32
29
  const scriptProject = new Project({ useInMemoryFileSystem: true });
33
30
  try {
34
31
  const wrappedContent = `function __wrapper() {${scriptContent}}`;
@@ -49,12 +46,10 @@ function transformScriptImports(scriptContent, manifest) {
49
46
  if (importPath.startsWith("/")) {
50
47
  log("Found dynamic import with root-relative path: %s", importPath);
51
48
  entryPoints.push(importPath);
52
- const path = importPath.slice(1);
53
- if (manifest[path]) {
54
- const transformedSrc = `/${manifest[path].file}`;
55
- args[0].setLiteralValue(transformedSrc);
56
- hasChanges = true;
57
- }
49
+ clientEntryPoints.add(importPath);
50
+ const transformedImportPath = transformAssetPath(importPath, projectRootDir);
51
+ args[0].setLiteralValue(transformedImportPath);
52
+ hasChanges = true;
58
53
  }
59
54
  }
60
55
  }
@@ -73,7 +68,7 @@ function transformScriptImports(scriptContent, manifest) {
73
68
  return { content: undefined, hasChanges: false, entryPoints: [] };
74
69
  }
75
70
  }
76
- export async function transformJsxScriptTagsCode(code, manifest = {}) {
71
+ export async function transformJsxScriptTagsCode(code, clientEntryPoints, manifest = {}, projectRootDir) {
77
72
  // context(justinvdm, 15 Jun 2025): Optimization to exit early
78
73
  // to avoidunnecessary ts-morph parsing
79
74
  if (!hasJsxFunctions(code)) {
@@ -124,7 +119,7 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
124
119
  let hasStringLiteralChildren = false;
125
120
  let hasSrc = false;
126
121
  let isPreload = false;
127
- let hrefValue = null;
122
+ let hrefProp;
128
123
  for (const prop of properties) {
129
124
  if (Node.isPropertyAssignment(prop)) {
130
125
  const propName = prop.getName();
@@ -142,15 +137,13 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
142
137
  const srcValue = initializer.getLiteralValue();
143
138
  if (srcValue.startsWith("/")) {
144
139
  entryPoints.push(srcValue);
145
- const path = srcValue.slice(1);
146
- if (manifest[path]) {
147
- const transformedSrc = `/${manifest[path].file}`;
148
- modifications.push({
149
- type: "literalValue",
150
- node: initializer,
151
- value: transformedSrc,
152
- });
153
- }
140
+ clientEntryPoints.add(srcValue);
141
+ const transformedSrc = transformAssetPath(srcValue, projectRootDir);
142
+ modifications.push({
143
+ type: "literalValue",
144
+ node: initializer,
145
+ value: transformedSrc,
146
+ });
154
147
  }
155
148
  }
156
149
  }
@@ -160,7 +153,7 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
160
153
  Node.isNoSubstitutionTemplateLiteral(initializer))) {
161
154
  hasStringLiteralChildren = true;
162
155
  const scriptContent = initializer.getLiteralValue();
163
- const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, manifest);
156
+ const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir);
164
157
  entryPoints.push(...dynamicEntryPoints);
165
158
  if (contentHasChanges && transformedContent) {
166
159
  const isTemplateLiteral = Node.isNoSubstitutionTemplateLiteral(initializer);
@@ -174,21 +167,35 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
174
167
  });
175
168
  }
176
169
  }
177
- if (tagName === "link") {
178
- if (propName === "rel" &&
179
- (Node.isStringLiteral(initializer) ||
180
- Node.isNoSubstitutionTemplateLiteral(initializer))) {
181
- const relValue = initializer.getLiteralValue();
182
- if (relValue === "preload" || relValue === "modulepreload") {
183
- isPreload = true;
184
- }
185
- }
186
- if (propName === "href" &&
187
- (Node.isStringLiteral(initializer) ||
188
- Node.isNoSubstitutionTemplateLiteral(initializer))) {
189
- hrefValue = initializer.getLiteralValue();
170
+ if (tagName === "link" &&
171
+ propName === "rel" &&
172
+ initializer &&
173
+ (Node.isStringLiteral(initializer) ||
174
+ Node.isNoSubstitutionTemplateLiteral(initializer))) {
175
+ const relValue = initializer.getLiteralValue();
176
+ if (relValue === "preload" || relValue === "modulepreload") {
177
+ isPreload = true;
190
178
  }
191
179
  }
180
+ if (tagName === "link" && propName === "href") {
181
+ hrefProp = prop;
182
+ }
183
+ }
184
+ }
185
+ if (isPreload && hrefProp) {
186
+ const initializer = hrefProp.getInitializer();
187
+ if (initializer &&
188
+ (Node.isStringLiteral(initializer) ||
189
+ Node.isNoSubstitutionTemplateLiteral(initializer))) {
190
+ const hrefValue = initializer.getLiteralValue();
191
+ if (hrefValue.startsWith("/")) {
192
+ const transformedHref = transformAssetPath(hrefValue, projectRootDir);
193
+ modifications.push({
194
+ type: "literalValue",
195
+ node: initializer,
196
+ value: transformedHref,
197
+ });
198
+ }
192
199
  }
193
200
  }
194
201
  if (tagName === "script" &&
@@ -205,43 +212,8 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
205
212
  needsRequestInfoImportRef.value = true;
206
213
  }
207
214
  }
208
- if (tagName === "link" &&
209
- isPreload &&
210
- hrefValue &&
211
- hrefValue.startsWith("/") &&
212
- manifest[hrefValue.slice(1)]) {
213
- const path = hrefValue.slice(1);
214
- for (const prop of properties) {
215
- if (Node.isPropertyAssignment(prop) &&
216
- prop.getName() === "href") {
217
- const initializer = prop.getInitializer();
218
- if (Node.isStringLiteral(initializer) ||
219
- Node.isNoSubstitutionTemplateLiteral(initializer)) {
220
- const transformedHref = manifest[path].file;
221
- const originalText = initializer.getText();
222
- const isTemplateLiteral = Node.isNoSubstitutionTemplateLiteral(initializer);
223
- const quote = isTemplateLiteral
224
- ? "`"
225
- : originalText.charAt(0);
226
- let replacementText;
227
- if (isTemplateLiteral) {
228
- replacementText = `\`/${transformedHref}\``;
229
- }
230
- else if (quote === '"') {
231
- replacementText = `"/${transformedHref}"`;
232
- }
233
- else {
234
- replacementText = `'/${transformedHref}'`;
235
- }
236
- modifications.push({
237
- type: "replaceText",
238
- node: initializer,
239
- text: replacementText,
240
- });
241
- }
242
- }
243
- }
244
- }
215
+ // Note: Link preload href transformations happen in Phase 5 (Asset Linking)
216
+ // During discovery phase, we only transform script tags
245
217
  }
246
218
  }
247
219
  if (entryPoints.length > 0) {
@@ -339,7 +311,7 @@ ${mod.callExprText}
339
311
  }
340
312
  return;
341
313
  }
342
- export const transformJsxScriptTagsPlugin = ({ manifestPath, }) => {
314
+ export const transformJsxScriptTagsPlugin = ({ clientEntryPoints, projectRootDir, }) => {
343
315
  let isBuild = false;
344
316
  return {
345
317
  name: "rwsdk:vite:transform-jsx-script-tags",
@@ -347,14 +319,24 @@ export const transformJsxScriptTagsPlugin = ({ manifestPath, }) => {
347
319
  isBuild = config.command === "build";
348
320
  },
349
321
  async transform(code, id) {
322
+ // Skip during directive scanning to avoid performance issues
323
+ if (process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE) {
324
+ return;
325
+ }
326
+ if (isBuild &&
327
+ this.environment?.name === "worker" &&
328
+ process.env.RWSDK_BUILD_PASS !== "worker") {
329
+ return null;
330
+ }
350
331
  if (this.environment?.name === "worker" &&
351
332
  id.endsWith(".tsx") &&
352
333
  !id.includes("node_modules") &&
353
334
  hasJsxFunctions(code)) {
354
335
  log("Transforming JSX script tags in %s", id);
355
336
  process.env.VERBOSE && log("Code:\n%s", code);
356
- const manifest = isBuild ? await readManifest(manifestPath) : {};
357
- const result = await transformJsxScriptTagsCode(code, manifest);
337
+ // During discovery phase, never use manifest - it doesn't exist yet
338
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, {}, // Empty manifest during discovery
339
+ projectRootDir);
358
340
  if (result) {
359
341
  log("Transformed JSX script tags in %s", id);
360
342
  process.env.VERBOSE &&
@@ -1,10 +1,15 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
2
  import { transformJsxScriptTagsCode } from "./transformJsxScriptTagsPlugin.mjs";
3
3
  import jsBeautify from "js-beautify";
4
+ import stubEnvVars from "../lib/testUtils/stubEnvVars.mjs";
4
5
  // Helper function to normalize code formatting for test comparisons
5
6
  function normalizeCode(code) {
6
7
  return jsBeautify(code, { indent_size: 2 });
7
8
  }
9
+ stubEnvVars();
10
+ beforeEach(() => {
11
+ process.env.RWSDK_BUILD_PASS = "worker";
12
+ });
8
13
  describe("transformJsxScriptTagsCode", () => {
9
14
  const mockManifest = {
10
15
  "src/client.tsx": { file: "assets/client-a1b2c3d4.js" },
@@ -18,13 +23,14 @@ describe("transformJsxScriptTagsCode", () => {
18
23
  type: "module"
19
24
  })
20
25
  `;
21
- const result = await transformJsxScriptTagsCode(code, mockManifest);
26
+ const clientEntryPoints = new Set();
27
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/Users/justin/rw/forks/workers-sdk/sdk/sdk");
22
28
  const expected = `import { requestInfo } from "rwsdk/worker";
23
29
 
24
30
  (
25
31
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
26
32
  jsx("script", {
27
- src: "/assets/client-a1b2c3d4.js",
33
+ src: "rwsdk_asset:/src/client.tsx",
28
34
  type: "module",
29
35
  nonce: requestInfo.rw.nonce
30
36
  })
@@ -38,14 +44,15 @@ nonce: requestInfo.rw.nonce
38
44
  children: "import('/src/client.tsx').then(module => { console.log(module); })"
39
45
  })
40
46
  `;
41
- const result = await transformJsxScriptTagsCode(code, mockManifest);
47
+ const clientEntryPoints = new Set();
48
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
42
49
  const expected = `import { requestInfo } from "rwsdk/worker";
43
50
 
44
51
  (
45
52
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
46
53
  jsx("script", {
47
54
  type: "module",
48
- children: "import('/assets/client-a1b2c3d4.js').then(module => { console.log(module); })",
55
+ children: "import('rwsdk_asset:/src/client.tsx').then(module => { console.log(module); })",
49
56
  nonce: requestInfo.rw.nonce
50
57
  })
51
58
  )`;
@@ -55,12 +62,13 @@ nonce: requestInfo.rw.nonce
55
62
  const code = `
56
63
  jsx("script", { type: "module", children: "import('/src/client.tsx')" })
57
64
  `;
58
- const result = await transformJsxScriptTagsCode(code, mockManifest);
65
+ const clientEntryPoints = new Set();
66
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
59
67
  const expected = `import { requestInfo } from "rwsdk/worker";
60
68
 
61
69
  (
62
70
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
63
- jsx("script", { type: "module", children: "import('/assets/client-a1b2c3d4.js')",
71
+ jsx("script", { type: "module", children: "import('rwsdk_asset:/src/client.tsx')",
64
72
  nonce: requestInfo.rw.nonce
65
73
  })
66
74
  )`;
@@ -80,7 +88,8 @@ nonce: requestInfo.rw.nonce
80
88
  \`
81
89
  })
82
90
  `;
83
- const result = await transformJsxScriptTagsCode(code, mockManifest);
91
+ const clientEntryPoints = new Set();
92
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
84
93
  const expected = `import { requestInfo } from "rwsdk/worker";
85
94
 
86
95
  (
@@ -90,7 +99,7 @@ type: "module",
90
99
  children: \`
91
100
  // Some comments here
92
101
  const init = async () => {
93
- await import('/assets/entry-e5f6g7h8.js');
102
+ await import('rwsdk_asset:/src/entry.js');
94
103
  console.log('initialized');
95
104
  };
96
105
  init();
@@ -110,7 +119,8 @@ import('/src/entry.js');
110
119
  \`
111
120
  })
112
121
  `;
113
- const result = await transformJsxScriptTagsCode(code, mockManifest);
122
+ const clientEntryPoints = new Set();
123
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
114
124
  const expected = `import { requestInfo } from "rwsdk/worker";
115
125
 
116
126
  (
@@ -119,8 +129,8 @@ import('/src/entry.js');
119
129
  jsx("script", {
120
130
  type: "module",
121
131
  children: \`
122
- import('/assets/client-a1b2c3d4.js');
123
- import('/assets/entry-e5f6g7h8.js');
132
+ import('rwsdk_asset:/src/client.tsx');
133
+ import('rwsdk_asset:/src/entry.js');
124
134
  \`,
125
135
  nonce: requestInfo.rw.nonce
126
136
  })
@@ -135,14 +145,17 @@ nonce: requestInfo.rw.nonce
135
145
  as: "script"
136
146
  })
137
147
  `;
138
- const result = await transformJsxScriptTagsCode(code, mockManifest);
139
- expect(result?.code).toEqual(`
148
+ const clientEntryPoints = new Set();
149
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
150
+ const expected = `
140
151
  jsx("link", {
141
152
  rel: "preload",
142
- href: "/assets/client-a1b2c3d4.js",
153
+ href: "rwsdk_asset:/src/client.tsx",
143
154
  as: "script"
144
155
  })
145
- `);
156
+ `;
157
+ expect(normalizeCode(result?.code || "")).toEqual(normalizeCode(expected));
158
+ expect(clientEntryPoints.size).toBe(0); // Make sure it doesn't incorrectly add to entry points
146
159
  });
147
160
  it("transforms link href attributes with modulepreload rel", async () => {
148
161
  const code = `
@@ -151,13 +164,15 @@ nonce: requestInfo.rw.nonce
151
164
  rel: "modulepreload"
152
165
  })
153
166
  `;
154
- const result = await transformJsxScriptTagsCode(code, mockManifest);
155
- expect(result?.code).toEqual(`
167
+ const clientEntryPoints = new Set();
168
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
169
+ const expected = `
156
170
  jsx("link", {
157
- href: "/assets/client-a1b2c3d4.js",
171
+ href: "rwsdk_asset:/src/client.tsx",
158
172
  rel: "modulepreload"
159
173
  })
160
- `);
174
+ `;
175
+ expect(normalizeCode(result?.code || "")).toEqual(normalizeCode(expected));
161
176
  });
162
177
  it("transforms real-world Document component example", async () => {
163
178
  const code = `
@@ -169,7 +184,7 @@ nonce: requestInfo.rw.nonce
169
184
  jsx("meta", { charSet: "utf-8" }),
170
185
  jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
171
186
  jsx("title", { children: "@redwoodjs/starter-standard" }),
172
- jsx("link", { rel: "modulepreload", href: "/src/client.tsx", as: "script" })
187
+ jsx("link", { rel: "modulepreload", href: "rwsdk_asset:/src/client.tsx", as: "script" })
173
188
  ]
174
189
  }),
175
190
  jsx("body", {
@@ -181,7 +196,8 @@ nonce: requestInfo.rw.nonce
181
196
  ]
182
197
  })
183
198
  `;
184
- const result = await transformJsxScriptTagsCode(code, mockManifest);
199
+ const clientEntryPoints = new Set();
200
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
185
201
  const expected = `import { requestInfo } from "rwsdk/worker";
186
202
 
187
203
  jsx("html", {
@@ -192,7 +208,7 @@ children: [
192
208
  jsx("meta", { charSet: "utf-8" }),
193
209
  jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
194
210
  jsx("title", { children: "@redwoodjs/starter-standard" }),
195
- jsx("link", { rel: "modulepreload", href: "/assets/client-a1b2c3d4.js", as: "script" })
211
+ jsx("link", { rel: "modulepreload", href: "rwsdk_asset:/src/client.tsx", as: "script" })
196
212
  ]
197
213
  }),
198
214
  jsx("body", {
@@ -200,7 +216,7 @@ children: [
200
216
  jsx("div", { id: "root", children: props.children }),
201
217
  (
202
218
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
203
- jsx("script", { children: "import(\\"/assets/client-a1b2c3d4.js\\")",
219
+ jsx("script", { children: "import(\\"rwsdk_asset:/src/client.tsx\\")",
204
220
  nonce: requestInfo.rw.nonce
205
221
  })
206
222
  )
@@ -214,7 +230,8 @@ nonce: requestInfo.rw.nonce
214
230
  const code = `
215
231
  jsx("div", { children: "No scripts or links here" })
216
232
  `;
217
- const result = await transformJsxScriptTagsCode(code, mockManifest);
233
+ const clientEntryPoints = new Set();
234
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
218
235
  expect(result).toBeUndefined();
219
236
  });
220
237
  it("handles paths not found in manifest", async () => {
@@ -224,13 +241,14 @@ nonce: requestInfo.rw.nonce
224
241
  type: "module"
225
242
  })
226
243
  `;
227
- const result = await transformJsxScriptTagsCode(code, mockManifest);
244
+ const clientEntryPoints = new Set();
245
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
228
246
  const expected = `import { requestInfo } from "rwsdk/worker";
229
247
 
230
248
  (
231
249
  (requestInfo.rw.scriptsToBeLoaded.add("/src/non-existent.js")),
232
250
  jsx("script", {
233
- src: "/src/non-existent.js",
251
+ src: "rwsdk_asset:/src/non-existent.js",
234
252
  type: "module",
235
253
  nonce: requestInfo.rw.nonce
236
254
  })
@@ -244,13 +262,14 @@ nonce: requestInfo.rw.nonce
244
262
  type: "module"
245
263
  })
246
264
  `;
247
- const result = await transformJsxScriptTagsCode(code, mockManifest);
265
+ const clientEntryPoints = new Set();
266
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
248
267
  const expected = `import { requestInfo } from "rwsdk/worker";
249
268
 
250
269
  (
251
270
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
252
271
  jsx("script", {
253
- src: "/assets/client-a1b2c3d4.js",
272
+ src: "rwsdk_asset:/src/client.tsx",
254
273
  type: "module",
255
274
  nonce: requestInfo.rw.nonce
256
275
  })
@@ -264,7 +283,8 @@ nonce: requestInfo.rw.nonce
264
283
  children: "console.log('hello world')"
265
284
  })
266
285
  `;
267
- const result = await transformJsxScriptTagsCode(code, {});
286
+ const clientEntryPoints = new Set();
287
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
268
288
  expect(result?.code).toEqual(`import { requestInfo } from "rwsdk/worker";
269
289
 
270
290
  jsx("script", {
@@ -281,7 +301,8 @@ nonce: requestInfo.rw.nonce
281
301
  dangerouslySetInnerHTML: { __html: "console.log('hello world')" }
282
302
  })
283
303
  `;
284
- const result = await transformJsxScriptTagsCode(code, {});
304
+ const clientEntryPoints = new Set();
305
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
285
306
  expect(result?.code).toEqual(undefined);
286
307
  });
287
308
  it("does not add nonce to script tags that already have nonce", async () => {
@@ -292,7 +313,8 @@ nonce: requestInfo.rw.nonce
292
313
  nonce: "existing-nonce"
293
314
  })
294
315
  `;
295
- const result = await transformJsxScriptTagsCode(code, {});
316
+ const clientEntryPoints = new Set();
317
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
296
318
  expect(result?.code).toEqual(undefined);
297
319
  });
298
320
  it("uses existing requestInfo import if already present", async () => {
@@ -305,7 +327,8 @@ nonce: requestInfo.rw.nonce
305
327
  children: "console.log('hello world')"
306
328
  })
307
329
  `;
308
- const result = await transformJsxScriptTagsCode(code, {});
330
+ const clientEntryPoints = new Set();
331
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
309
332
  expect(result?.code).toEqual(`
310
333
  import { foo } from 'bar';
311
334
  import { requestInfo, someOtherThing } from "rwsdk/worker";
@@ -331,7 +354,8 @@ nonce: requestInfo.rw.nonce
331
354
  children: "console.log('hello world')"
332
355
  })
333
356
  `;
334
- const result = await transformJsxScriptTagsCode(code, {});
357
+ const clientEntryPoints = new Set();
358
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
335
359
  expect(result?.code).toEqual(`
336
360
  import { foo } from 'bar';
337
361
  import { someOtherThing, requestInfo } from "rwsdk/worker";
@@ -351,13 +375,14 @@ nonce: requestInfo.rw.nonce
351
375
  })
352
376
  `;
353
377
  // Call without providing manifest (simulating dev mode)
354
- const result = await transformJsxScriptTagsCode(code);
378
+ const clientEntryPoints = new Set();
379
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
355
380
  const expected = `import { requestInfo } from "rwsdk/worker";
356
381
 
357
382
  (
358
383
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
359
384
  jsx("script", {
360
- src: "/src/client.tsx",
385
+ src: "rwsdk_asset:/src/client.tsx",
361
386
  type: "module",
362
387
  nonce: requestInfo.rw.nonce
363
388
  })
@@ -433,7 +458,7 @@ export const Document = ({
433
458
  lineNumber: 22,
434
459
  columnNumber: 4
435
460
  }, this),
436
- /* @__PURE__ */ jsxDEV("link", { rel: "modulepreload", href: "/src/client.tsx" }, void 0, false, {
461
+ /* @__PURE__ */ jsxDEV("link", { rel: "modulepreload", href: "rwsdk_asset:/src/client.tsx" }, void 0, false, {
437
462
  fileName: "/Users/justin/rw/blotter/rwsdk-guestbook/src/app/document/Document.tsx",
438
463
  lineNumber: 23,
439
464
  columnNumber: 4
@@ -470,7 +495,8 @@ export const Document = ({
470
495
  columnNumber: 2
471
496
  }, this);
472
497
  `;
473
- const result = await transformJsxScriptTagsCode(code, mockManifest);
498
+ const clientEntryPoints = new Set();
499
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
474
500
  // For this complex test, we'll just verify the key transformations
475
501
  const expected = `
476
502
  import { jsxDEV } from "react/jsx-dev-runtime";
@@ -534,7 +560,7 @@ children
534
560
  ),
535
561
  (
536
562
  (requestInfo.rw.scriptsToBeLoaded.add("/theme-script.js")),
537
- /* @__PURE__ */ jsxDEV("script", { src: "/theme-script.js",
563
+ /* @__PURE__ */ jsxDEV("script", { src: "rwsdk_asset:/theme-script.js",
538
564
  nonce: requestInfo.rw.nonce
539
565
  }, void 0, false, {
540
566
  fileName: "/Users/justin/rw/blotter/rwsdk-guestbook/src/app/document/Document.tsx",
@@ -547,7 +573,7 @@ children
547
573
  lineNumber: 22,
548
574
  columnNumber: 4
549
575
  }, this),
550
- /* @__PURE__ */ jsxDEV("link", { rel: "modulepreload", href: "/assets/client-a1b2c3d4.js" }, void 0, false, {
576
+ /* @__PURE__ */ jsxDEV("link", { rel: "modulepreload", href: "rwsdk_asset:/src/client.tsx" }, void 0, false, {
551
577
  fileName: "/Users/justin/rw/blotter/rwsdk-guestbook/src/app/document/Document.tsx",
552
578
  lineNumber: 23,
553
579
  columnNumber: 4
@@ -570,7 +596,7 @@ children
570
596
  }, this),
571
597
  (
572
598
  (requestInfo.rw.scriptsToBeLoaded.add("/src/client.tsx")),
573
- /* @__PURE__ */ jsxDEV("script", { children: "import(\\"/assets/client-a1b2c3d4.js\\")",
599
+ /* @__PURE__ */ jsxDEV("script", { children: "import(\\"rwsdk_asset:/src/client.tsx\\")",
574
600
  nonce: requestInfo.rw.nonce
575
601
  }, void 0, false, {
576
602
  fileName: "/Users/justin/rw/blotter/rwsdk-guestbook/src/app/document/Document.tsx",
@@ -12,5 +12,5 @@ type ExportInfoCompat = {
12
12
  };
13
13
  export declare const findExportedFunctions: (code: string, normalizedId?: string) => Set<string>;
14
14
  export declare const findExportInfo: (code: string, normalizedId?: string) => ExportInfoCompat;
15
- export declare const transformServerFunctions: (code: string, normalizedId: string, environment: "client" | "worker" | "ssr", serverFiles?: Set<string>, addServerModule?: (environment: string, id: string) => void) => TransformResult | undefined;
15
+ export declare const transformServerFunctions: (code: string, normalizedId: string, environment: "client" | "worker" | "ssr", serverFiles?: Set<string>) => TransformResult | undefined;
16
16
  export type { TransformResult };
@@ -84,19 +84,15 @@ function hasDefaultExport(code, normalizedId) {
84
84
  }
85
85
  return false;
86
86
  }
87
- export const transformServerFunctions = (code, normalizedId, environment, serverFiles, addServerModule) => {
88
- process.env.VERBOSE &&
89
- log("Transform server functions called for normalizedId=%s, environment=%s", normalizedId, environment);
87
+ export const transformServerFunctions = (code, normalizedId, environment, serverFiles) => {
90
88
  if (!hasDirective(code, "use server")) {
91
- log("Skipping: no 'use server' directive in id=%s", normalizedId);
92
- process.env.VERBOSE &&
93
- log(":VERBOSE: Returning code unchanged for id=%s:\n%s", normalizedId, code);
94
89
  return;
95
90
  }
96
- log("Processing 'use server' module: normalizedId=%s, environment=%s", normalizedId, environment);
97
- addServerModule?.(environment, normalizedId);
91
+ process.env.VERBOSE &&
92
+ log("Processing 'use server' module: normalizedId=%s, environment=%s", normalizedId, environment);
98
93
  if (environment === "ssr" || environment === "client") {
99
- log(`Transforming for ${environment} environment: normalizedId=%s`, normalizedId);
94
+ process.env.VERBOSE &&
95
+ log(`Transforming for ${environment} environment: normalizedId=%s`, normalizedId);
100
96
  const exportInfo = findExportInfo(code, normalizedId);
101
97
  const allExports = new Set([
102
98
  ...exportInfo.localFunctions,
@@ -126,7 +122,8 @@ export const transformServerFunctions = (code, normalizedId, environment, server
126
122
  s.append(`\nexport default createServerReference(${JSON.stringify(normalizedId)}, "default");\n`);
127
123
  log(`Added ${environment} server reference for default export in normalizedId=%s`, normalizedId);
128
124
  }
129
- log(`${environment} transformation complete for normalizedId=%s`, normalizedId);
125
+ process.env.VERBOSE &&
126
+ log(`${environment} transformation complete for normalizedId=%s`, normalizedId);
130
127
  return {
131
128
  code: s.toString(),
132
129
  map: s.generateMap({
@@ -137,7 +134,8 @@ export const transformServerFunctions = (code, normalizedId, environment, server
137
134
  };
138
135
  }
139
136
  else if (environment === "worker") {
140
- log("Transforming for worker environment: normalizedId=%s", normalizedId);
137
+ process.env.VERBOSE &&
138
+ log("Transforming for worker environment: normalizedId=%s", normalizedId);
141
139
  const exportInfo = findExportInfo(code, normalizedId);
142
140
  const s = new MagicString(code);
143
141
  // Remove "use server" directive first
@@ -281,7 +279,8 @@ export const transformServerFunctions = (code, normalizedId, environment, server
281
279
  if (registrationCalls.length > 0) {
282
280
  s.append(registrationCalls.join("\n") + "\n");
283
281
  }
284
- log("Worker transformation complete for normalizedId=%s", normalizedId);
282
+ process.env.VERBOSE &&
283
+ log("Worker transformation complete for normalizedId=%s", normalizedId);
285
284
  return {
286
285
  code: s.toString(),
287
286
  map: s.generateMap({
@@ -4,12 +4,20 @@ export const virtualPlugin = (name, load) => {
4
4
  return {
5
5
  name: `rwsdk:virtual-${name}`,
6
6
  resolveId(source, _importer, _options) {
7
+ // Skip during directive scanning to avoid performance issues
8
+ if (process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE) {
9
+ return;
10
+ }
7
11
  if (source === name || source.startsWith(`${name}?`)) {
8
12
  return `\0${source}`;
9
13
  }
10
14
  return;
11
15
  },
12
16
  load(id, options) {
17
+ // Skip during directive scanning to avoid performance issues
18
+ if (process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE) {
19
+ return;
20
+ }
13
21
  if (id === `\0${name}` || id.startsWith(`\0${name}?`)) {
14
22
  return load.apply(this, [id, options]);
15
23
  }