rwsdk 0.2.0-alpha.9 → 0.3.0

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 (93) 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/client/client.d.ts +10 -0
  15. package/dist/runtime/{client.js → client/client.js} +13 -10
  16. package/dist/runtime/{clientNavigation.test.js → client/navigation.test.js} +1 -1
  17. package/dist/runtime/client/setWebpackRequire.d.ts +1 -0
  18. package/dist/runtime/client/setWebpackRequire.js +2 -0
  19. package/dist/runtime/{client.d.ts → client/types.d.ts} +4 -10
  20. package/dist/runtime/client/types.js +1 -0
  21. package/dist/runtime/entries/client.d.ts +2 -2
  22. package/dist/runtime/entries/client.js +2 -2
  23. package/dist/runtime/imports/client.d.ts +3 -3
  24. package/dist/runtime/imports/client.js +11 -15
  25. package/dist/runtime/imports/ssr.d.ts +3 -3
  26. package/dist/runtime/imports/ssr.js +3 -3
  27. package/dist/runtime/imports/worker.d.ts +3 -3
  28. package/dist/runtime/imports/worker.js +5 -4
  29. package/dist/runtime/lib/manifest.d.ts +11 -2
  30. package/dist/runtime/lib/manifest.js +1 -1
  31. package/dist/runtime/lib/memoizeOnId.d.ts +1 -0
  32. package/dist/runtime/lib/memoizeOnId.js +11 -0
  33. package/dist/runtime/lib/realtime/client.d.ts +1 -1
  34. package/dist/runtime/lib/realtime/client.js +1 -1
  35. package/dist/runtime/lib/router.d.ts +3 -3
  36. package/dist/runtime/lib/router.js +77 -33
  37. package/dist/runtime/register/ssr.d.ts +1 -1
  38. package/dist/runtime/register/ssr.js +4 -3
  39. package/dist/runtime/render/preloads.d.ts +6 -0
  40. package/dist/runtime/render/preloads.js +40 -0
  41. package/dist/runtime/render/renderRscThenableToHtmlStream.js +2 -1
  42. package/dist/runtime/render/stylesheets.js +1 -1
  43. package/dist/runtime/requestInfo/types.d.ts +3 -1
  44. package/dist/runtime/requestInfo/worker.js +9 -1
  45. package/dist/runtime/worker.d.ts +0 -3
  46. package/dist/runtime/worker.js +2 -11
  47. package/dist/scripts/debug-sync.mjs +142 -39
  48. package/dist/scripts/smoke-test.mjs +0 -10
  49. package/dist/scripts/worker-run.mjs +8 -3
  50. package/dist/vite/buildApp.d.mts +15 -0
  51. package/dist/vite/buildApp.mjs +53 -0
  52. package/dist/vite/configPlugin.d.mts +4 -2
  53. package/dist/vite/configPlugin.mjs +69 -62
  54. package/dist/vite/createDirectiveLookupPlugin.d.mts +0 -6
  55. package/dist/vite/createDirectiveLookupPlugin.mjs +61 -145
  56. package/dist/vite/directiveModulesDevPlugin.d.mts +8 -0
  57. package/dist/vite/directiveModulesDevPlugin.mjs +62 -0
  58. package/dist/vite/directivesFilteringPlugin.d.mts +6 -0
  59. package/dist/vite/directivesFilteringPlugin.mjs +31 -0
  60. package/dist/vite/directivesPlugin.mjs +28 -42
  61. package/dist/vite/getViteEsbuild.d.mts +1 -0
  62. package/dist/vite/getViteEsbuild.mjs +12 -0
  63. package/dist/vite/hasOwnReactVitePlugin.d.mts +3 -0
  64. package/dist/vite/hasOwnReactVitePlugin.mjs +14 -0
  65. package/dist/vite/injectVitePreamblePlugin.d.mts +3 -2
  66. package/dist/vite/injectVitePreamblePlugin.mjs +4 -2
  67. package/dist/vite/linkerPlugin.d.mts +4 -0
  68. package/dist/vite/linkerPlugin.mjs +41 -0
  69. package/dist/vite/manifestPlugin.d.mts +2 -2
  70. package/dist/vite/manifestPlugin.mjs +12 -37
  71. package/dist/vite/miniflareHMRPlugin.mjs +17 -2
  72. package/dist/vite/moveStaticAssetsPlugin.mjs +2 -1
  73. package/dist/vite/prismaPlugin.mjs +1 -1
  74. package/dist/vite/reactConditionsResolverPlugin.d.mts +3 -4
  75. package/dist/vite/reactConditionsResolverPlugin.mjs +74 -56
  76. package/dist/vite/redwoodPlugin.d.mts +1 -1
  77. package/dist/vite/redwoodPlugin.mjs +36 -12
  78. package/dist/vite/runDirectivesScan.d.mts +7 -0
  79. package/dist/vite/runDirectivesScan.mjs +152 -0
  80. package/dist/vite/ssrBridgePlugin.mjs +13 -14
  81. package/dist/vite/transformClientComponents.d.mts +0 -1
  82. package/dist/vite/transformClientComponents.mjs +1 -9
  83. package/dist/vite/transformJsxScriptTagsPlugin.d.mts +4 -3
  84. package/dist/vite/transformJsxScriptTagsPlugin.mjs +151 -158
  85. package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +393 -136
  86. package/dist/vite/transformServerFunctions.d.mts +1 -1
  87. package/dist/vite/transformServerFunctions.mjs +11 -12
  88. package/package.json +28 -4
  89. /package/dist/runtime/{imports → client}/ClientOnly.d.ts +0 -0
  90. /package/dist/runtime/{imports → client}/ClientOnly.js +0 -0
  91. /package/dist/runtime/{clientNavigation.d.ts → client/navigation.d.ts} +0 -0
  92. /package/dist/runtime/{clientNavigation.js → client/navigation.js} +0 -0
  93. /package/dist/runtime/{clientNavigation.test.d.ts → client/navigation.test.d.ts} +0 -0
@@ -1,19 +1,16 @@
1
- import { Project, Node, SyntaxKind } from "ts-morph";
2
- import { readFile } from "node:fs/promises";
3
- import { pathExists } from "fs-extra";
1
+ import { Project, Node, SyntaxKind, } from "ts-morph";
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,23 +25,18 @@ function hasJsxFunctions(text) {
28
25
  text.includes('jsxDEV("link"') ||
29
26
  text.includes("jsxDEV('link'"));
30
27
  }
31
- // Transform import statements in script content using ts-morph
32
- function transformScriptImports(scriptContent, manifest) {
28
+ function transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir) {
33
29
  const scriptProject = new Project({ useInMemoryFileSystem: true });
34
30
  try {
35
- // Wrap in a function to make it valid JavaScript
36
31
  const wrappedContent = `function __wrapper() {${scriptContent}}`;
37
32
  const scriptFile = scriptProject.createSourceFile("script.js", wrappedContent);
38
33
  let hasChanges = false;
39
34
  const entryPoints = [];
40
- // Find all CallExpressions that look like import("path")
41
35
  scriptFile
42
36
  .getDescendantsOfKind(SyntaxKind.CallExpression)
43
37
  .forEach((callExpr) => {
44
38
  const expr = callExpr.getExpression();
45
- // Check for both "import()" and "await import()" patterns
46
39
  const isImport = expr.getText() === "import";
47
- // Check for await import pattern
48
40
  const isAwaitImport = expr.getKind() === SyntaxKind.PropertyAccessExpression &&
49
41
  expr.getText().endsWith(".import");
50
42
  if (isImport || isAwaitImport) {
@@ -54,35 +46,29 @@ function transformScriptImports(scriptContent, manifest) {
54
46
  if (importPath.startsWith("/")) {
55
47
  log("Found dynamic import with root-relative path: %s", importPath);
56
48
  entryPoints.push(importPath);
57
- const path = importPath.slice(1); // Remove leading slash
58
- if (manifest[path]) {
59
- const transformedSrc = `/${manifest[path].file}`;
60
- args[0].setLiteralValue(transformedSrc);
61
- hasChanges = true;
62
- }
49
+ clientEntryPoints.add(importPath);
50
+ const transformedImportPath = transformAssetPath(importPath, projectRootDir);
51
+ args[0].setLiteralValue(transformedImportPath);
52
+ hasChanges = true;
63
53
  }
64
54
  }
65
55
  }
66
56
  });
67
57
  if (hasChanges) {
68
- // Extract the transformed content from inside the wrapper function
69
58
  const fullText = scriptFile.getFullText();
70
- // Find content between the first { and the last }
71
59
  const startPos = fullText.indexOf("{") + 1;
72
60
  const endPos = fullText.lastIndexOf("}");
73
61
  const transformedContent = fullText.substring(startPos, endPos);
74
62
  return { content: transformedContent, hasChanges: true, entryPoints };
75
63
  }
76
- // Return the original content when no changes are made
77
64
  return { content: scriptContent, hasChanges: false, entryPoints };
78
65
  }
79
66
  catch (error) {
80
- // If parsing fails, fall back to the original content
81
67
  console.warn("Failed to parse inline script content:", error);
82
68
  return { content: undefined, hasChanges: false, entryPoints: [] };
83
69
  }
84
70
  }
85
- export async function transformJsxScriptTagsCode(code, manifest = {}) {
71
+ export async function transformJsxScriptTagsCode(code, clientEntryPoints, manifest = {}, projectRootDir) {
86
72
  // context(justinvdm, 15 Jun 2025): Optimization to exit early
87
73
  // to avoidunnecessary ts-morph parsing
88
74
  if (!hasJsxFunctions(code)) {
@@ -90,17 +76,15 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
90
76
  }
91
77
  const project = new Project({ useInMemoryFileSystem: true });
92
78
  const sourceFile = project.createSourceFile("temp.tsx", code);
93
- let hasModifications = false;
79
+ const modifications = [];
94
80
  const needsRequestInfoImportRef = { value: false };
95
- // Check for existing imports up front
81
+ const entryPointsPerCallExpr = new Map();
96
82
  let hasRequestInfoImport = false;
97
83
  let sdkWorkerImportDecl;
98
- // Scan for imports only once
99
84
  sourceFile.getImportDeclarations().forEach((importDecl) => {
100
85
  const moduleSpecifier = importDecl.getModuleSpecifierValue();
101
86
  if (moduleSpecifier === "rwsdk/worker") {
102
87
  sdkWorkerImportDecl = importDecl;
103
- // Check if requestInfo is already imported
104
88
  if (importDecl
105
89
  .getNamedImports()
106
90
  .some((namedImport) => namedImport.getName() === "requestInfo")) {
@@ -108,163 +92,128 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
108
92
  }
109
93
  }
110
94
  });
111
- // Look for jsx function calls (jsx, jsxs, jsxDEV)
112
95
  sourceFile
113
96
  .getDescendantsOfKind(SyntaxKind.CallExpression)
114
97
  .forEach((callExpr) => {
115
98
  const expression = callExpr.getExpression();
116
99
  const expressionText = expression.getText();
117
- // Only process jsx/jsxs/jsxDEV calls
118
100
  if (expressionText !== "jsx" &&
119
101
  expressionText !== "jsxs" &&
120
102
  expressionText !== "jsxDEV") {
121
103
  return;
122
104
  }
123
- // Get arguments of the jsx call
124
105
  const args = callExpr.getArguments();
125
106
  if (args.length < 2)
126
107
  return;
127
- // First argument should be the element type
128
108
  const elementType = args[0];
129
109
  if (!Node.isStringLiteral(elementType))
130
110
  return;
131
111
  const tagName = elementType.getLiteralValue();
132
112
  const entryPoints = [];
133
- // Process script and link tags
134
113
  if (tagName === "script" || tagName === "link") {
135
- // Second argument should be the props object
136
114
  const propsArg = args[1];
137
- // Handle object literals with properties
138
115
  if (Node.isObjectLiteralExpression(propsArg)) {
139
116
  const properties = propsArg.getProperties();
140
- // Variables to track script attributes
141
117
  let hasDangerouslySetInnerHTML = false;
142
118
  let hasNonce = false;
143
119
  let hasStringLiteralChildren = false;
144
120
  let hasSrc = false;
145
- // Variables to track link attributes
146
121
  let isPreload = false;
147
- let hrefValue = null;
122
+ let hrefProp;
148
123
  for (const prop of properties) {
149
124
  if (Node.isPropertyAssignment(prop)) {
150
125
  const propName = prop.getName();
151
126
  const initializer = prop.getInitializer();
152
- // Check for existing nonce
153
127
  if (propName === "nonce") {
154
128
  hasNonce = true;
155
129
  }
156
- // Check for dangerouslySetInnerHTML
157
130
  if (propName === "dangerouslySetInnerHTML") {
158
131
  hasDangerouslySetInnerHTML = true;
159
132
  }
160
- // Check for src attribute
161
133
  if (tagName === "script" && propName === "src") {
162
134
  hasSrc = true;
163
- // Also process src for manifest transformation if needed
164
135
  if (Node.isStringLiteral(initializer) ||
165
136
  Node.isNoSubstitutionTemplateLiteral(initializer)) {
166
137
  const srcValue = initializer.getLiteralValue();
167
138
  if (srcValue.startsWith("/")) {
168
139
  entryPoints.push(srcValue);
169
- const path = srcValue.slice(1); // Remove leading slash
170
- if (manifest[path]) {
171
- const transformedSrc = `/${manifest[path].file}`;
172
- initializer.setLiteralValue(transformedSrc);
173
- hasModifications = true;
174
- }
140
+ clientEntryPoints.add(srcValue);
141
+ const transformedSrc = transformAssetPath(srcValue, projectRootDir);
142
+ modifications.push({
143
+ type: "literalValue",
144
+ node: initializer,
145
+ value: transformedSrc,
146
+ });
175
147
  }
176
148
  }
177
149
  }
178
- // Check for string literal children
179
150
  if (tagName === "script" &&
180
151
  propName === "children" &&
181
152
  (Node.isStringLiteral(initializer) ||
182
153
  Node.isNoSubstitutionTemplateLiteral(initializer))) {
183
154
  hasStringLiteralChildren = true;
184
155
  const scriptContent = initializer.getLiteralValue();
185
- // Transform import statements in script content using ts-morph
186
- const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, manifest);
156
+ const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir);
187
157
  entryPoints.push(...dynamicEntryPoints);
188
158
  if (contentHasChanges && transformedContent) {
189
- // Get the raw text with quotes to determine the exact format
190
159
  const isTemplateLiteral = Node.isNoSubstitutionTemplateLiteral(initializer);
191
- if (isTemplateLiteral) {
192
- // Simply wrap the transformed content in backticks
193
- initializer.replaceWithText("`" + transformedContent + "`");
194
- }
195
- else {
196
- initializer.replaceWithText(JSON.stringify(transformedContent));
197
- }
198
- hasModifications = true;
160
+ const replacementText = isTemplateLiteral
161
+ ? "`" + transformedContent + "`"
162
+ : JSON.stringify(transformedContent);
163
+ modifications.push({
164
+ type: "replaceText",
165
+ node: initializer,
166
+ text: replacementText,
167
+ });
199
168
  }
200
169
  }
201
- // For link tags, first check if it's a preload/modulepreload
202
- if (tagName === "link") {
203
- if (propName === "rel" &&
204
- (Node.isStringLiteral(initializer) ||
205
- Node.isNoSubstitutionTemplateLiteral(initializer))) {
206
- const relValue = initializer.getLiteralValue();
207
- if (relValue === "preload" || relValue === "modulepreload") {
208
- isPreload = true;
209
- }
210
- }
211
- if (propName === "href" &&
212
- (Node.isStringLiteral(initializer) ||
213
- Node.isNoSubstitutionTemplateLiteral(initializer))) {
214
- 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;
215
178
  }
216
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
+ }
217
199
  }
218
200
  }
219
- // Add nonce to script tags if needed
220
201
  if (tagName === "script" &&
221
202
  !hasNonce &&
222
203
  !hasDangerouslySetInnerHTML &&
223
204
  (hasStringLiteralChildren || hasSrc)) {
224
- // Add nonce property to the props object
225
- propsArg.addPropertyAssignment({
205
+ modifications.push({
206
+ type: "addProperty",
207
+ node: propsArg,
226
208
  name: "nonce",
227
209
  initializer: "requestInfo.rw.nonce",
228
210
  });
229
211
  if (!hasRequestInfoImport) {
230
212
  needsRequestInfoImportRef.value = true;
231
213
  }
232
- hasModifications = true;
233
- }
234
- // Transform href if this is a preload link
235
- if (tagName === "link" &&
236
- isPreload &&
237
- hrefValue &&
238
- hrefValue.startsWith("/") &&
239
- manifest[hrefValue.slice(1)]) {
240
- const path = hrefValue.slice(1); // Remove leading slash
241
- for (const prop of properties) {
242
- if (Node.isPropertyAssignment(prop) &&
243
- prop.getName() === "href") {
244
- const initializer = prop.getInitializer();
245
- if (Node.isStringLiteral(initializer) ||
246
- Node.isNoSubstitutionTemplateLiteral(initializer)) {
247
- const transformedHref = manifest[path].file;
248
- const originalText = initializer.getText();
249
- const isTemplateLiteral = Node.isNoSubstitutionTemplateLiteral(initializer);
250
- const quote = isTemplateLiteral
251
- ? "`"
252
- : originalText.charAt(0);
253
- // Preserve the original quote style
254
- if (isTemplateLiteral) {
255
- initializer.replaceWithText(`\`/${transformedHref}\``);
256
- }
257
- else if (quote === '"') {
258
- initializer.replaceWithText(`"/${transformedHref}"`);
259
- }
260
- else {
261
- initializer.replaceWithText(`'/${transformedHref}'`);
262
- }
263
- hasModifications = true;
264
- }
265
- }
266
- }
267
214
  }
215
+ // Note: Link preload href transformations happen in Phase 5 (Asset Linking)
216
+ // During discovery phase, we only transform script tags
268
217
  }
269
218
  }
270
219
  if (entryPoints.length > 0) {
@@ -274,51 +223,87 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
274
223
  .join(",\n");
275
224
  const leadingCommentRanges = callExpr.getLeadingCommentRanges();
276
225
  const pureComment = leadingCommentRanges.find((r) => r.getText().includes("@__PURE__"));
277
- const callExprText = callExpr.getText();
278
- if (pureComment) {
279
- const pureCommentText = pureComment.getText();
280
- const newText = `(
281
- ${sideEffects},
282
- ${pureCommentText} ${callExprText}
283
- )`;
284
- const fullText = callExpr.getFullText();
285
- const leadingTriviaText = fullText.substring(0, fullText.length - callExprText.length);
286
- const newLeadingTriviaText = leadingTriviaText.replace(pureCommentText, "");
287
- // By replacing from `getFullStart`, we remove the original node and all its leading trivia
288
- // and replace it with our manually reconstructed string.
289
- // This should correctly move the pure comment and preserve other comments and whitespace.
290
- callExpr
291
- .getSourceFile()
292
- .replaceText([callExpr.getFullStart(), callExpr.getEnd()], newLeadingTriviaText + newText);
293
- }
294
- else {
295
- callExpr.replaceWithText(`(
296
- ${sideEffects},
297
- ${callExprText}
298
- )`);
226
+ const wrapInfo = {
227
+ callExpr: callExpr,
228
+ sideEffects: sideEffects,
229
+ pureCommentText: pureComment?.getText(),
230
+ };
231
+ if (!entryPointsPerCallExpr.has(callExpr)) {
232
+ entryPointsPerCallExpr.set(callExpr, wrapInfo);
299
233
  }
300
234
  needsRequestInfoImportRef.value = true;
301
- hasModifications = true;
302
235
  }
303
236
  });
304
- // Add requestInfo import if needed and not already imported
305
- if (needsRequestInfoImportRef.value && hasModifications) {
306
- if (sdkWorkerImportDecl) {
307
- // Module is imported but need to add requestInfo
308
- if (!hasRequestInfoImport) {
309
- sdkWorkerImportDecl.addNamedImport("requestInfo");
237
+ if (modifications.length > 0 || entryPointsPerCallExpr.size > 0) {
238
+ for (const mod of modifications) {
239
+ if (mod.type === "literalValue") {
240
+ mod.node.setLiteralValue(mod.value);
241
+ }
242
+ else if (mod.type === "replaceText") {
243
+ mod.node.replaceWithText(mod.text);
244
+ }
245
+ else if (mod.type === "addProperty") {
246
+ mod.node.addPropertyAssignment({
247
+ name: mod.name,
248
+ initializer: mod.initializer,
249
+ });
310
250
  }
311
251
  }
312
- else {
313
- // Add new import declaration
314
- sourceFile.addImportDeclaration({
315
- moduleSpecifier: "rwsdk/worker",
316
- namedImports: ["requestInfo"],
252
+ const wrapModifications = [];
253
+ for (const [callExpr, wrapInfo] of entryPointsPerCallExpr) {
254
+ const fullStart = callExpr.getFullStart();
255
+ const end = callExpr.getEnd();
256
+ const callExprText = callExpr.getText();
257
+ const fullText = callExpr.getFullText();
258
+ const leadingWhitespace = fullText.substring(0, fullText.length - callExprText.length);
259
+ let pureCommentText;
260
+ let leadingTriviaText;
261
+ if (wrapInfo.pureCommentText) {
262
+ pureCommentText = wrapInfo.pureCommentText;
263
+ leadingTriviaText = leadingWhitespace;
264
+ }
265
+ wrapModifications.push({
266
+ type: "wrapCallExpr",
267
+ sideEffects: wrapInfo.sideEffects,
268
+ pureCommentText: pureCommentText,
269
+ leadingTriviaText: leadingTriviaText,
270
+ fullStart: fullStart,
271
+ end: end,
272
+ callExprText: callExprText,
273
+ leadingWhitespace: leadingWhitespace,
317
274
  });
318
275
  }
319
- }
320
- // Return the transformed code only if modifications were made
321
- if (hasModifications) {
276
+ wrapModifications.sort((a, b) => b.fullStart - a.fullStart);
277
+ for (const mod of wrapModifications) {
278
+ if (mod.pureCommentText && mod.leadingTriviaText) {
279
+ const newText = `(
280
+ ${mod.sideEffects},
281
+ ${mod.pureCommentText} ${mod.callExprText}
282
+ )`;
283
+ const newLeadingTriviaText = mod.leadingTriviaText.replace(mod.pureCommentText, "");
284
+ sourceFile.replaceText([mod.fullStart, mod.end], newLeadingTriviaText + newText);
285
+ }
286
+ else {
287
+ const leadingNewlines = mod.leadingWhitespace.match(/\n\s*/)?.[0] || "";
288
+ sourceFile.replaceText([mod.fullStart, mod.end], `${leadingNewlines}(
289
+ ${mod.sideEffects},
290
+ ${mod.callExprText}
291
+ )`);
292
+ }
293
+ }
294
+ if (needsRequestInfoImportRef.value) {
295
+ if (sdkWorkerImportDecl) {
296
+ if (!hasRequestInfoImport) {
297
+ sdkWorkerImportDecl.addNamedImport("requestInfo");
298
+ }
299
+ }
300
+ else {
301
+ sourceFile.addImportDeclaration({
302
+ moduleSpecifier: "rwsdk/worker",
303
+ namedImports: ["requestInfo"],
304
+ });
305
+ }
306
+ }
322
307
  return {
323
308
  code: sourceFile.getFullText(),
324
309
  map: null,
@@ -326,7 +311,7 @@ export async function transformJsxScriptTagsCode(code, manifest = {}) {
326
311
  }
327
312
  return;
328
313
  }
329
- export const transformJsxScriptTagsPlugin = ({ manifestPath, }) => {
314
+ export const transformJsxScriptTagsPlugin = ({ clientEntryPoints, projectRootDir, }) => {
330
315
  let isBuild = false;
331
316
  return {
332
317
  name: "rwsdk:vite:transform-jsx-script-tags",
@@ -334,12 +319,20 @@ export const transformJsxScriptTagsPlugin = ({ manifestPath, }) => {
334
319
  isBuild = config.command === "build";
335
320
  },
336
321
  async transform(code, id) {
322
+ if (isBuild &&
323
+ this.environment?.name === "worker" &&
324
+ process.env.RWSDK_BUILD_PASS !== "worker") {
325
+ return null;
326
+ }
337
327
  if (this.environment?.name === "worker" &&
338
328
  id.endsWith(".tsx") &&
339
329
  !id.includes("node_modules") &&
340
330
  hasJsxFunctions(code)) {
341
- const manifest = isBuild ? await readManifest(manifestPath) : {};
342
- const result = await transformJsxScriptTagsCode(code, manifest);
331
+ log("Transforming JSX script tags in %s", id);
332
+ process.env.VERBOSE && log("Code:\n%s", code);
333
+ // During discovery phase, never use manifest - it doesn't exist yet
334
+ const result = await transformJsxScriptTagsCode(code, clientEntryPoints, {}, // Empty manifest during discovery
335
+ projectRootDir);
343
336
  if (result) {
344
337
  log("Transformed JSX script tags in %s", id);
345
338
  process.env.VERBOSE &&