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.
- package/dist/lib/constants.d.mts +6 -1
- package/dist/lib/constants.mjs +6 -1
- package/dist/lib/smokeTests/browser.mjs +5 -21
- package/dist/lib/smokeTests/codeUpdates.d.mts +1 -1
- package/dist/lib/smokeTests/codeUpdates.mjs +41 -5
- package/dist/lib/smokeTests/development.d.mts +1 -1
- package/dist/lib/smokeTests/development.mjs +4 -10
- package/dist/lib/smokeTests/release.d.mts +1 -1
- package/dist/lib/smokeTests/release.mjs +4 -9
- package/dist/lib/smokeTests/runSmokeTests.mjs +2 -2
- package/dist/lib/smokeTests/templates/SmokeTest.template.js +3 -2
- package/dist/lib/testUtils/stubEnvVars.d.mts +2 -0
- package/dist/lib/testUtils/stubEnvVars.mjs +11 -0
- package/dist/runtime/client/client.d.ts +10 -0
- package/dist/runtime/{client.js → client/client.js} +13 -10
- package/dist/runtime/{clientNavigation.test.js → client/navigation.test.js} +1 -1
- package/dist/runtime/client/setWebpackRequire.d.ts +1 -0
- package/dist/runtime/client/setWebpackRequire.js +2 -0
- package/dist/runtime/{client.d.ts → client/types.d.ts} +4 -10
- package/dist/runtime/client/types.js +1 -0
- package/dist/runtime/entries/client.d.ts +2 -2
- package/dist/runtime/entries/client.js +2 -2
- package/dist/runtime/imports/client.d.ts +3 -3
- package/dist/runtime/imports/client.js +11 -15
- package/dist/runtime/imports/ssr.d.ts +3 -3
- package/dist/runtime/imports/ssr.js +3 -3
- package/dist/runtime/imports/worker.d.ts +3 -3
- package/dist/runtime/imports/worker.js +5 -4
- package/dist/runtime/lib/manifest.d.ts +11 -2
- package/dist/runtime/lib/manifest.js +1 -1
- package/dist/runtime/lib/memoizeOnId.d.ts +1 -0
- package/dist/runtime/lib/memoizeOnId.js +11 -0
- package/dist/runtime/lib/realtime/client.d.ts +1 -1
- package/dist/runtime/lib/realtime/client.js +1 -1
- package/dist/runtime/lib/router.d.ts +3 -3
- package/dist/runtime/lib/router.js +77 -33
- package/dist/runtime/register/ssr.d.ts +1 -1
- package/dist/runtime/register/ssr.js +4 -3
- package/dist/runtime/render/preloads.d.ts +6 -0
- package/dist/runtime/render/preloads.js +40 -0
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +2 -1
- package/dist/runtime/render/stylesheets.js +1 -1
- package/dist/runtime/requestInfo/types.d.ts +3 -1
- package/dist/runtime/requestInfo/worker.js +9 -1
- package/dist/runtime/worker.d.ts +0 -3
- package/dist/runtime/worker.js +2 -11
- package/dist/scripts/debug-sync.mjs +142 -39
- package/dist/scripts/smoke-test.mjs +0 -10
- package/dist/scripts/worker-run.mjs +8 -3
- package/dist/vite/buildApp.d.mts +15 -0
- package/dist/vite/buildApp.mjs +53 -0
- package/dist/vite/configPlugin.d.mts +4 -2
- package/dist/vite/configPlugin.mjs +69 -62
- package/dist/vite/createDirectiveLookupPlugin.d.mts +0 -6
- package/dist/vite/createDirectiveLookupPlugin.mjs +61 -145
- package/dist/vite/directiveModulesDevPlugin.d.mts +8 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +62 -0
- package/dist/vite/directivesFilteringPlugin.d.mts +6 -0
- package/dist/vite/directivesFilteringPlugin.mjs +31 -0
- package/dist/vite/directivesPlugin.mjs +28 -42
- package/dist/vite/getViteEsbuild.d.mts +1 -0
- package/dist/vite/getViteEsbuild.mjs +12 -0
- package/dist/vite/hasOwnReactVitePlugin.d.mts +3 -0
- package/dist/vite/hasOwnReactVitePlugin.mjs +14 -0
- package/dist/vite/injectVitePreamblePlugin.d.mts +3 -2
- package/dist/vite/injectVitePreamblePlugin.mjs +4 -2
- package/dist/vite/linkerPlugin.d.mts +4 -0
- package/dist/vite/linkerPlugin.mjs +41 -0
- package/dist/vite/manifestPlugin.d.mts +2 -2
- package/dist/vite/manifestPlugin.mjs +12 -37
- package/dist/vite/miniflareHMRPlugin.mjs +17 -2
- package/dist/vite/moveStaticAssetsPlugin.mjs +2 -1
- package/dist/vite/prismaPlugin.mjs +1 -1
- package/dist/vite/reactConditionsResolverPlugin.d.mts +3 -4
- package/dist/vite/reactConditionsResolverPlugin.mjs +74 -56
- package/dist/vite/redwoodPlugin.d.mts +1 -1
- package/dist/vite/redwoodPlugin.mjs +36 -12
- package/dist/vite/runDirectivesScan.d.mts +7 -0
- package/dist/vite/runDirectivesScan.mjs +152 -0
- package/dist/vite/ssrBridgePlugin.mjs +13 -14
- package/dist/vite/transformClientComponents.d.mts +0 -1
- package/dist/vite/transformClientComponents.mjs +1 -9
- package/dist/vite/transformJsxScriptTagsPlugin.d.mts +4 -3
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +151 -158
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +393 -136
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +11 -12
- package/package.json +28 -4
- /package/dist/runtime/{imports → client}/ClientOnly.d.ts +0 -0
- /package/dist/runtime/{imports → client}/ClientOnly.js +0 -0
- /package/dist/runtime/{clientNavigation.d.ts → client/navigation.d.ts} +0 -0
- /package/dist/runtime/{clientNavigation.js → client/navigation.js} +0 -0
- /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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
79
|
+
const modifications = [];
|
|
94
80
|
const needsRequestInfoImportRef = { value: false };
|
|
95
|
-
|
|
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
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
initializer
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
321
|
-
|
|
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 = ({
|
|
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
|
-
|
|
342
|
-
|
|
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 &&
|