rwsdk 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/stripBase.d.mts +1 -0
- package/dist/lib/stripBase.mjs +5 -0
- package/dist/lib/stripBase.test.d.mts +1 -0
- package/dist/lib/stripBase.test.mjs +22 -0
- package/dist/runtime/lib/router.js +15 -1
- package/dist/runtime/lib/types.d.ts +1 -0
- package/dist/runtime/worker.js +52 -22
- package/dist/vite/buildApp.mjs +45 -2
- package/dist/vite/linkerPlugin.mjs +4 -1
- package/dist/vite/linkerPlugin.test.mjs +10 -0
- package/dist/vite/transformJsxScriptTagsPlugin.d.mts +1 -1
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +24 -13
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +68 -18
- package/dist/vite/vitePreamblePlugin.d.mts +153 -1
- package/dist/vite/vitePreamblePlugin.mjs +16 -6
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function stripBase(path: string, base: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { stripBase } from "./stripBase.mjs";
|
|
3
|
+
describe("stripBase", () => {
|
|
4
|
+
it("should strip base prefix from path", () => {
|
|
5
|
+
expect(stripBase("/auth/src/client.tsx", "/auth/")).toBe("/src/client.tsx");
|
|
6
|
+
});
|
|
7
|
+
it("should be a no-op when base is /", () => {
|
|
8
|
+
expect(stripBase("/src/client.tsx", "/")).toBe("/src/client.tsx");
|
|
9
|
+
});
|
|
10
|
+
it("should be a no-op when path does not start with base", () => {
|
|
11
|
+
expect(stripBase("/src/client.tsx", "/auth/")).toBe("/src/client.tsx");
|
|
12
|
+
});
|
|
13
|
+
it("should handle path equal to base", () => {
|
|
14
|
+
expect(stripBase("/auth/", "/auth/")).toBe("/");
|
|
15
|
+
});
|
|
16
|
+
it("should handle multi-level base paths", () => {
|
|
17
|
+
expect(stripBase("/org/app/src/client.tsx", "/org/app/")).toBe("/src/client.tsx");
|
|
18
|
+
});
|
|
19
|
+
it("should be a no-op when base is empty string", () => {
|
|
20
|
+
expect(stripBase("/src/client.tsx", "")).toBe("/src/client.tsx");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -317,7 +317,17 @@ export function defineRoutes(routes) {
|
|
|
317
317
|
if (!isClientReference(componentHandler) && !requestInfo.rw.pageRouteResolved) {
|
|
318
318
|
requestInfo.rw.pageRouteResolved = Promise.withResolvers();
|
|
319
319
|
}
|
|
320
|
-
|
|
320
|
+
const response = await renderPage(requestInfo, WrappedComponent, onError);
|
|
321
|
+
// context(justinvdm, 2026-03-17): renderPage stores rendering
|
|
322
|
+
// errors on rw.renderError instead of throwing, to avoid
|
|
323
|
+
// corrupting React's internal RSC stream state. We check for
|
|
324
|
+
// it here and throw so except handlers can process it.
|
|
325
|
+
if (requestInfo.rw.renderError) {
|
|
326
|
+
const error = requestInfo.rw.renderError;
|
|
327
|
+
requestInfo.rw.renderError = undefined;
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
return response;
|
|
321
331
|
}
|
|
322
332
|
// Handle non-component final handler (e.g., returns new Response)
|
|
323
333
|
const tailResult = await componentHandler(getRequestInfo());
|
|
@@ -347,6 +357,10 @@ Route handlers must return one of:
|
|
|
347
357
|
});
|
|
348
358
|
}
|
|
349
359
|
catch (error) {
|
|
360
|
+
// context(justinvdm, 2026-03-17): If pageRouteResolved was set up for
|
|
361
|
+
// the component that threw, resolve it so the worker doesn't hang
|
|
362
|
+
// waiting on it after the except handler returns its response.
|
|
363
|
+
getRequestInfo().rw.pageRouteResolved?.resolve();
|
|
350
364
|
return await executeExceptHandlers(error, currentRouteIndex);
|
|
351
365
|
}
|
|
352
366
|
}
|
|
@@ -13,6 +13,7 @@ export type RwContext = {
|
|
|
13
13
|
inlineScripts: Set<string>;
|
|
14
14
|
pageRouteResolved: PromiseWithResolvers<void> | undefined;
|
|
15
15
|
actionResult?: unknown;
|
|
16
|
+
renderError?: unknown;
|
|
16
17
|
};
|
|
17
18
|
export type DocumentProps<T extends RequestInfo = RequestInfo> = T & {
|
|
18
19
|
children: React.ReactNode;
|
package/dist/runtime/worker.js
CHANGED
|
@@ -16,6 +16,17 @@ export const defineApp = (routes) => {
|
|
|
16
16
|
__rwRoutes: routes,
|
|
17
17
|
fetch: async (request, env, cf) => {
|
|
18
18
|
globalThis.__webpack_require__ = ssrWebpackRequire;
|
|
19
|
+
// context(justinvdm, 17 Mar 2026): Strip the Vite base path from the
|
|
20
|
+
// request URL so that routes defined as "/" match requests to "/app/"
|
|
21
|
+
// when base: '/app/' is configured. Vite injects BASE_URL automatically.
|
|
22
|
+
const base = import.meta.env.BASE_URL;
|
|
23
|
+
if (base && base !== "/") {
|
|
24
|
+
const url = new URL(request.url);
|
|
25
|
+
if (url.pathname.startsWith(base)) {
|
|
26
|
+
url.pathname = "/" + url.pathname.slice(base.length);
|
|
27
|
+
request = new Request(url.toString(), request);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
// context(justinvdm, 5 Feb 2025): Serve assets requests using the assets service binding
|
|
20
31
|
// todo(justinvdm, 5 Feb 2025): Find a way to avoid this so asset requests are served directly
|
|
21
32
|
// rather than first needing to go through the worker
|
|
@@ -107,7 +118,7 @@ export const defineApp = (routes) => {
|
|
|
107
118
|
}
|
|
108
119
|
return pageElement;
|
|
109
120
|
};
|
|
110
|
-
const renderPage = async (requestInfo, Page,
|
|
121
|
+
const renderPage = async (requestInfo, Page, _onError) => {
|
|
111
122
|
if (isClientReference(requestInfo.rw.Document)) {
|
|
112
123
|
if (import.meta.env.DEV) {
|
|
113
124
|
console.error("Document cannot be a client component");
|
|
@@ -116,6 +127,17 @@ export const defineApp = (routes) => {
|
|
|
116
127
|
status: 500,
|
|
117
128
|
});
|
|
118
129
|
}
|
|
130
|
+
// context(justinvdm, 2026-03-17): Capture rendering errors so the
|
|
131
|
+
// router can throw them and route to except handlers. We store the
|
|
132
|
+
// error on rw.renderError instead of throwing from renderPage, because
|
|
133
|
+
// throwing mid-render corrupts React's internal RSC stream state
|
|
134
|
+
// (causing "chunk.reason.enqueueModel is not a function" in subsequent
|
|
135
|
+
// renders). By returning normally, streams are cleaned up properly.
|
|
136
|
+
const onError = (error) => {
|
|
137
|
+
if (!rw.renderError) {
|
|
138
|
+
rw.renderError = error;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
119
141
|
const actionResult = normalizeActionResult(requestInfo.rw.actionResult);
|
|
120
142
|
const isDataOnly = request.headers.get("x-rsc-data-only") === "true";
|
|
121
143
|
const pageElement = isDataOnly && actionResult !== undefined
|
|
@@ -149,13 +171,28 @@ export const defineApp = (routes) => {
|
|
|
149
171
|
nonce: rw.nonce,
|
|
150
172
|
});
|
|
151
173
|
}
|
|
152
|
-
let html
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
let html;
|
|
175
|
+
try {
|
|
176
|
+
html = await renderDocumentHtmlStream({
|
|
177
|
+
rscPayloadStream: rscPayloadStream,
|
|
178
|
+
Document: rw.Document,
|
|
179
|
+
requestInfo: requestInfo,
|
|
180
|
+
onError,
|
|
181
|
+
shouldSSR: rw.ssr,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
catch (renderError) {
|
|
185
|
+
// context(justinvdm, 2026-03-17): If renderDocumentHtmlStream throws
|
|
186
|
+
// AND we already captured the error via onError, return a minimal
|
|
187
|
+
// response. The router will detect rw.renderError and route to
|
|
188
|
+
// except handlers. We must not re-throw here because throwing from
|
|
189
|
+
// renderPage corrupts React's internal RSC stream state, preventing
|
|
190
|
+
// the except handler from rendering its error page.
|
|
191
|
+
if (rw.renderError) {
|
|
192
|
+
return new Response(null, { status: 500 });
|
|
193
|
+
}
|
|
194
|
+
throw renderError;
|
|
195
|
+
}
|
|
159
196
|
if (injectRSCPayloadStream) {
|
|
160
197
|
html = html.pipeThrough(injectRSCPayloadStream);
|
|
161
198
|
}
|
|
@@ -167,20 +204,13 @@ export const defineApp = (routes) => {
|
|
|
167
204
|
headers: responseHeaders,
|
|
168
205
|
});
|
|
169
206
|
};
|
|
170
|
-
const response = await runWithRequestInfo(outerRequestInfo,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
onError: reject,
|
|
178
|
-
rscActionHandler,
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
catch (e) {
|
|
182
|
-
reject(e);
|
|
183
|
-
}
|
|
207
|
+
const response = await runWithRequestInfo(outerRequestInfo, () => router.handle({
|
|
208
|
+
request,
|
|
209
|
+
renderPage,
|
|
210
|
+
getRequestInfo: getRequestInfo,
|
|
211
|
+
runWithRequestInfoOverrides,
|
|
212
|
+
onError: () => { },
|
|
213
|
+
rscActionHandler,
|
|
184
214
|
}));
|
|
185
215
|
// context(justinvdm, 18 Mar 2025): In some cases, such as a .fetch() call to a durable object instance, or Response.redirect(),
|
|
186
216
|
// we need to return a mutable response object.
|
package/dist/vite/buildApp.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { cp, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { INTERMEDIATES_OUTPUT_DIR } from "../lib/constants.mjs";
|
|
6
6
|
import { runDirectivesScan } from "./runDirectivesScan.mjs";
|
|
7
7
|
const log = debug("rwsdk:vite:build-app");
|
|
@@ -87,4 +87,47 @@ export async function buildApp({ builder, clientEntryPoints, clientFiles, server
|
|
|
87
87
|
};
|
|
88
88
|
await builder.build(workerEnv);
|
|
89
89
|
console.log("Build complete!");
|
|
90
|
+
// context(zshannon, 16 Mar 2026): Nest client output under base subdirectory
|
|
91
|
+
// for Cloudflare's assets module, which maps URL paths directly to file paths.
|
|
92
|
+
const base = builder.config.base || "/";
|
|
93
|
+
if (base !== "/") {
|
|
94
|
+
const subdir = base.replace(/^\/|\/$/g, "");
|
|
95
|
+
const clientDir = resolve(projectRootDir, "dist", "client");
|
|
96
|
+
const tmpDir = resolve(projectRootDir, "dist", "_client_tmp");
|
|
97
|
+
const nestDir = join(clientDir, subdir);
|
|
98
|
+
await rm(tmpDir, { force: true, recursive: true });
|
|
99
|
+
await cp(clientDir, tmpDir, { recursive: true });
|
|
100
|
+
await rm(clientDir, { force: true, recursive: true });
|
|
101
|
+
await mkdir(nestDir, { recursive: true });
|
|
102
|
+
for (const entry of await readdir(tmpDir)) {
|
|
103
|
+
await cp(join(tmpDir, entry), join(nestDir, entry), { recursive: true });
|
|
104
|
+
}
|
|
105
|
+
await rm(tmpDir, { force: true, recursive: true });
|
|
106
|
+
// context(justinvdm, 17 Mar 2026): The Cloudflare Vite plugin generates a
|
|
107
|
+
// wrangler.json in the dist output. We need to patch its assets.directory
|
|
108
|
+
// to account for the nesting we just did.
|
|
109
|
+
const workerDistDir = resolve(projectRootDir, "dist", "worker");
|
|
110
|
+
const wranglerCandidates = ["wrangler.json", "wrangler.jsonc", "wrangler.toml"];
|
|
111
|
+
for (const candidate of wranglerCandidates) {
|
|
112
|
+
const wranglerPath = join(workerDistDir, candidate);
|
|
113
|
+
if (existsSync(wranglerPath) && candidate !== "wrangler.toml") {
|
|
114
|
+
const content = await readFile(wranglerPath, "utf-8");
|
|
115
|
+
const wrangler = JSON.parse(content);
|
|
116
|
+
if (wrangler.assets?.directory) {
|
|
117
|
+
const currentDir = wrangler.assets.directory;
|
|
118
|
+
const fixedDir = currentDir.replace(`/${subdir}`, "");
|
|
119
|
+
if (fixedDir !== currentDir) {
|
|
120
|
+
wrangler.assets.directory = fixedDir;
|
|
121
|
+
await writeFile(wranglerPath, JSON.stringify(wrangler, null, 2));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.warn(`Warning: ${candidate} assets.directory "${currentDir}" ` +
|
|
125
|
+
`did not contain expected "/${subdir}" segment`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
console.log(`Nested client assets under ${subdir}/`);
|
|
132
|
+
}
|
|
90
133
|
}
|
|
@@ -23,8 +23,11 @@ export function linkWorkerBundle({ code, manifestContent, projectRootDir, base,
|
|
|
23
23
|
}
|
|
24
24
|
// 3. Deprefix any remaining placeholders that were not in the manifest.
|
|
25
25
|
// This handles public assets that don't go through the bundler.
|
|
26
|
+
// context(justinvdm, 17 Mar 2026): Prepend base (without trailing slash)
|
|
27
|
+
// so public asset paths are correct under a non-default base.
|
|
26
28
|
log("Deprefixing remaining asset placeholders");
|
|
27
|
-
|
|
29
|
+
const basePrefix = (base ? base : "/").replace(/\/$/, "");
|
|
30
|
+
newCode = newCode.replaceAll("rwsdk_asset:", basePrefix);
|
|
28
31
|
return {
|
|
29
32
|
code: newCode,
|
|
30
33
|
map: null,
|
|
@@ -53,4 +53,14 @@ describe("linkWorkerBundle", () => {
|
|
|
53
53
|
});
|
|
54
54
|
expect(result.code).toContain(`const publicImg = "/images/photo.jpg";`);
|
|
55
55
|
});
|
|
56
|
+
it("should deprefix remaining asset placeholders with base prefix", () => {
|
|
57
|
+
const code = `const publicImg = "rwsdk_asset:/images/photo.jpg";`;
|
|
58
|
+
const result = linkWorkerBundle({
|
|
59
|
+
code,
|
|
60
|
+
manifestContent,
|
|
61
|
+
projectRootDir,
|
|
62
|
+
base: "/app/",
|
|
63
|
+
});
|
|
64
|
+
expect(result.code).toContain(`const publicImg = "/app/images/photo.jpg";`);
|
|
65
|
+
});
|
|
56
66
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Plugin } from "vite";
|
|
2
|
-
export declare function transformJsxScriptTagsCode(code: string, clientEntryPoints: Set<string>, manifest: Record<string, any> | undefined, projectRootDir: string): Promise<{
|
|
2
|
+
export declare function transformJsxScriptTagsCode(code: string, clientEntryPoints: Set<string>, manifest: Record<string, any> | undefined, projectRootDir: string, base: string): Promise<{
|
|
3
3
|
code: string;
|
|
4
4
|
map: null;
|
|
5
5
|
} | undefined>;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
2
|
import { Node, Project, SyntaxKind, } from "ts-morph";
|
|
3
3
|
import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
|
|
4
|
+
import { stripBase } from "../lib/stripBase.mjs";
|
|
4
5
|
const log = debug("rwsdk:vite:transform-jsx-script-tags");
|
|
5
|
-
function transformAssetPath(importPath, projectRootDir) {
|
|
6
|
+
function transformAssetPath(importPath, projectRootDir, base) {
|
|
6
7
|
if (process.env.VITE_IS_DEV_SERVER === "1") {
|
|
8
|
+
// context(justinvdm, 17 Mar 2026): In dev mode with a non-default base,
|
|
9
|
+
// prefix the path so Vite can resolve it under the base URL.
|
|
10
|
+
if (base && base !== "/" && importPath.startsWith("/") && !importPath.startsWith(base)) {
|
|
11
|
+
return base.replace(/\/$/, "") + importPath;
|
|
12
|
+
}
|
|
7
13
|
return importPath;
|
|
8
14
|
}
|
|
9
|
-
const
|
|
15
|
+
const strippedPath = stripBase(importPath, base);
|
|
16
|
+
const normalizedImportPath = normalizeModulePath(strippedPath, projectRootDir);
|
|
10
17
|
return `rwsdk_asset:${normalizedImportPath}`;
|
|
11
18
|
}
|
|
12
19
|
// Note: This plugin only runs during discovery phase (Phase 1)
|
|
@@ -25,7 +32,7 @@ function hasJsxFunctions(text) {
|
|
|
25
32
|
text.includes('jsxDEV("link"') ||
|
|
26
33
|
text.includes("jsxDEV('link'"));
|
|
27
34
|
}
|
|
28
|
-
function transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir) {
|
|
35
|
+
function transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir, base) {
|
|
29
36
|
const scriptProject = new Project({ useInMemoryFileSystem: true });
|
|
30
37
|
try {
|
|
31
38
|
const wrappedContent = `function __wrapper() {${scriptContent}}`;
|
|
@@ -45,9 +52,10 @@ function transformScriptImports(scriptContent, clientEntryPoints, manifest, proj
|
|
|
45
52
|
const importPath = args[0].getLiteralValue();
|
|
46
53
|
if (importPath.startsWith("/")) {
|
|
47
54
|
log("Found dynamic import with root-relative path: %s", importPath);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
const normalizedEntry = stripBase(importPath, base);
|
|
56
|
+
entryPoints.push(normalizedEntry);
|
|
57
|
+
clientEntryPoints.add(normalizedEntry);
|
|
58
|
+
const transformedImportPath = transformAssetPath(importPath, projectRootDir, base);
|
|
51
59
|
args[0].setLiteralValue(transformedImportPath);
|
|
52
60
|
hasChanges = true;
|
|
53
61
|
}
|
|
@@ -68,7 +76,7 @@ function transformScriptImports(scriptContent, clientEntryPoints, manifest, proj
|
|
|
68
76
|
return { content: undefined, hasChanges: false, entryPoints: [] };
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
|
-
export async function transformJsxScriptTagsCode(code, clientEntryPoints, manifest = {}, projectRootDir) {
|
|
79
|
+
export async function transformJsxScriptTagsCode(code, clientEntryPoints, manifest = {}, projectRootDir, base) {
|
|
72
80
|
// context(justinvdm, 15 Jun 2025): Optimization to exit early
|
|
73
81
|
// to avoidunnecessary ts-morph parsing
|
|
74
82
|
if (!hasJsxFunctions(code)) {
|
|
@@ -136,9 +144,10 @@ export async function transformJsxScriptTagsCode(code, clientEntryPoints, manife
|
|
|
136
144
|
Node.isNoSubstitutionTemplateLiteral(initializer)) {
|
|
137
145
|
const srcValue = initializer.getLiteralValue();
|
|
138
146
|
if (srcValue.startsWith("/")) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
147
|
+
const normalizedSrcEntry = stripBase(srcValue, base);
|
|
148
|
+
entryPoints.push(normalizedSrcEntry);
|
|
149
|
+
clientEntryPoints.add(normalizedSrcEntry);
|
|
150
|
+
const transformedSrc = transformAssetPath(srcValue, projectRootDir, base);
|
|
142
151
|
modifications.push({
|
|
143
152
|
type: "literalValue",
|
|
144
153
|
node: initializer,
|
|
@@ -153,7 +162,7 @@ export async function transformJsxScriptTagsCode(code, clientEntryPoints, manife
|
|
|
153
162
|
Node.isNoSubstitutionTemplateLiteral(initializer))) {
|
|
154
163
|
hasStringLiteralChildren = true;
|
|
155
164
|
const scriptContent = initializer.getLiteralValue();
|
|
156
|
-
const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir);
|
|
165
|
+
const { content: transformedContent, hasChanges: contentHasChanges, entryPoints: dynamicEntryPoints, } = transformScriptImports(scriptContent, clientEntryPoints, manifest, projectRootDir, base);
|
|
157
166
|
entryPoints.push(...dynamicEntryPoints);
|
|
158
167
|
if (contentHasChanges && transformedContent) {
|
|
159
168
|
const isTemplateLiteral = Node.isNoSubstitutionTemplateLiteral(initializer);
|
|
@@ -189,7 +198,7 @@ export async function transformJsxScriptTagsCode(code, clientEntryPoints, manife
|
|
|
189
198
|
Node.isNoSubstitutionTemplateLiteral(initializer))) {
|
|
190
199
|
const hrefValue = initializer.getLiteralValue();
|
|
191
200
|
if (hrefValue.startsWith("/")) {
|
|
192
|
-
const transformedHref = transformAssetPath(hrefValue, projectRootDir);
|
|
201
|
+
const transformedHref = transformAssetPath(hrefValue, projectRootDir, base);
|
|
193
202
|
modifications.push({
|
|
194
203
|
type: "literalValue",
|
|
195
204
|
node: initializer,
|
|
@@ -313,10 +322,12 @@ ${mod.callExprText}
|
|
|
313
322
|
}
|
|
314
323
|
export const transformJsxScriptTagsPlugin = ({ clientEntryPoints, projectRootDir, }) => {
|
|
315
324
|
let isBuild = false;
|
|
325
|
+
let base = "/";
|
|
316
326
|
return {
|
|
317
327
|
name: "rwsdk:vite:transform-jsx-script-tags",
|
|
318
328
|
configResolved(config) {
|
|
319
329
|
isBuild = config.command === "build";
|
|
330
|
+
base = config.base || "/";
|
|
320
331
|
},
|
|
321
332
|
async transform(code, id) {
|
|
322
333
|
if (isBuild &&
|
|
@@ -331,7 +342,7 @@ export const transformJsxScriptTagsPlugin = ({ clientEntryPoints, projectRootDir
|
|
|
331
342
|
process.env.VERBOSE && log("Code:\n%s", code);
|
|
332
343
|
// During discovery phase, never use manifest - it doesn't exist yet
|
|
333
344
|
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, {}, // Empty manifest during discovery
|
|
334
|
-
projectRootDir);
|
|
345
|
+
projectRootDir, base);
|
|
335
346
|
if (result) {
|
|
336
347
|
log("Transformed JSX script tags in %s", id);
|
|
337
348
|
process.env.VERBOSE &&
|
|
@@ -24,7 +24,7 @@ describe("transformJsxScriptTagsCode", () => {
|
|
|
24
24
|
})
|
|
25
25
|
`;
|
|
26
26
|
const clientEntryPoints = new Set();
|
|
27
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/Users/justin/rw/forks/workers-sdk/sdk/sdk");
|
|
27
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/Users/justin/rw/forks/workers-sdk/sdk/sdk", "/");
|
|
28
28
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
29
29
|
|
|
30
30
|
(
|
|
@@ -45,7 +45,7 @@ nonce: requestInfo.rw.nonce
|
|
|
45
45
|
})
|
|
46
46
|
`;
|
|
47
47
|
const clientEntryPoints = new Set();
|
|
48
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
48
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
49
49
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
50
50
|
|
|
51
51
|
(
|
|
@@ -63,7 +63,7 @@ nonce: requestInfo.rw.nonce
|
|
|
63
63
|
jsx("script", { type: "module", children: "import('/src/client.tsx')" })
|
|
64
64
|
`;
|
|
65
65
|
const clientEntryPoints = new Set();
|
|
66
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
66
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
67
67
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
68
68
|
|
|
69
69
|
(
|
|
@@ -89,7 +89,7 @@ nonce: requestInfo.rw.nonce
|
|
|
89
89
|
})
|
|
90
90
|
`;
|
|
91
91
|
const clientEntryPoints = new Set();
|
|
92
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
92
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
93
93
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
94
94
|
|
|
95
95
|
(
|
|
@@ -120,7 +120,7 @@ import('/src/entry.js');
|
|
|
120
120
|
})
|
|
121
121
|
`;
|
|
122
122
|
const clientEntryPoints = new Set();
|
|
123
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
123
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
124
124
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
125
125
|
|
|
126
126
|
(
|
|
@@ -146,7 +146,7 @@ nonce: requestInfo.rw.nonce
|
|
|
146
146
|
})
|
|
147
147
|
`;
|
|
148
148
|
const clientEntryPoints = new Set();
|
|
149
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
149
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
150
150
|
const expected = `
|
|
151
151
|
jsx("link", {
|
|
152
152
|
rel: "preload",
|
|
@@ -165,7 +165,7 @@ nonce: requestInfo.rw.nonce
|
|
|
165
165
|
})
|
|
166
166
|
`;
|
|
167
167
|
const clientEntryPoints = new Set();
|
|
168
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
168
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
169
169
|
const expected = `
|
|
170
170
|
jsx("link", {
|
|
171
171
|
href: "rwsdk_asset:/src/client.tsx",
|
|
@@ -197,7 +197,7 @@ nonce: requestInfo.rw.nonce
|
|
|
197
197
|
})
|
|
198
198
|
`;
|
|
199
199
|
const clientEntryPoints = new Set();
|
|
200
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
200
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
201
201
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
202
202
|
|
|
203
203
|
jsx("html", {
|
|
@@ -231,7 +231,7 @@ nonce: requestInfo.rw.nonce
|
|
|
231
231
|
jsx("div", { children: "No scripts or links here" })
|
|
232
232
|
`;
|
|
233
233
|
const clientEntryPoints = new Set();
|
|
234
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
234
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
235
235
|
expect(result).toBeUndefined();
|
|
236
236
|
});
|
|
237
237
|
it("handles paths not found in manifest", async () => {
|
|
@@ -242,7 +242,7 @@ nonce: requestInfo.rw.nonce
|
|
|
242
242
|
})
|
|
243
243
|
`;
|
|
244
244
|
const clientEntryPoints = new Set();
|
|
245
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
245
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
246
246
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
247
247
|
|
|
248
248
|
(
|
|
@@ -263,7 +263,7 @@ nonce: requestInfo.rw.nonce
|
|
|
263
263
|
})
|
|
264
264
|
`;
|
|
265
265
|
const clientEntryPoints = new Set();
|
|
266
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
266
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
267
267
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
268
268
|
|
|
269
269
|
(
|
|
@@ -284,7 +284,7 @@ nonce: requestInfo.rw.nonce
|
|
|
284
284
|
})
|
|
285
285
|
`;
|
|
286
286
|
const clientEntryPoints = new Set();
|
|
287
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
287
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
288
288
|
expect(result?.code).toEqual(`import { requestInfo } from "rwsdk/worker";
|
|
289
289
|
|
|
290
290
|
jsx("script", {
|
|
@@ -302,7 +302,7 @@ nonce: requestInfo.rw.nonce
|
|
|
302
302
|
})
|
|
303
303
|
`;
|
|
304
304
|
const clientEntryPoints = new Set();
|
|
305
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
305
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
306
306
|
expect(result?.code).toEqual(undefined);
|
|
307
307
|
});
|
|
308
308
|
it("does not add nonce to script tags that already have nonce", async () => {
|
|
@@ -314,7 +314,7 @@ nonce: requestInfo.rw.nonce
|
|
|
314
314
|
})
|
|
315
315
|
`;
|
|
316
316
|
const clientEntryPoints = new Set();
|
|
317
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
317
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
318
318
|
expect(result?.code).toEqual(undefined);
|
|
319
319
|
});
|
|
320
320
|
it("uses existing requestInfo import if already present", async () => {
|
|
@@ -328,7 +328,7 @@ nonce: requestInfo.rw.nonce
|
|
|
328
328
|
})
|
|
329
329
|
`;
|
|
330
330
|
const clientEntryPoints = new Set();
|
|
331
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
331
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
332
332
|
expect(result?.code).toEqual(`
|
|
333
333
|
import { foo } from 'bar';
|
|
334
334
|
import { requestInfo, someOtherThing } from "rwsdk/worker";
|
|
@@ -355,7 +355,7 @@ nonce: requestInfo.rw.nonce
|
|
|
355
355
|
})
|
|
356
356
|
`;
|
|
357
357
|
const clientEntryPoints = new Set();
|
|
358
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
358
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
359
359
|
expect(result?.code).toEqual(`
|
|
360
360
|
import { foo } from 'bar';
|
|
361
361
|
import { someOtherThing, requestInfo } from "rwsdk/worker";
|
|
@@ -376,7 +376,7 @@ nonce: requestInfo.rw.nonce
|
|
|
376
376
|
`;
|
|
377
377
|
// Call without providing manifest (simulating dev mode)
|
|
378
378
|
const clientEntryPoints = new Set();
|
|
379
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
379
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
380
380
|
const expected = `import { requestInfo } from "rwsdk/worker";
|
|
381
381
|
|
|
382
382
|
(
|
|
@@ -496,7 +496,7 @@ export const Document = ({
|
|
|
496
496
|
}, this);
|
|
497
497
|
`;
|
|
498
498
|
const clientEntryPoints = new Set();
|
|
499
|
-
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir");
|
|
499
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
500
500
|
// For this complex test, we'll just verify the key transformations
|
|
501
501
|
const expected = `
|
|
502
502
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
@@ -616,4 +616,54 @@ columnNumber: 2
|
|
|
616
616
|
}, this);`;
|
|
617
617
|
expect(normalizeCode(result?.code || "")).toEqual(normalizeCode(expected));
|
|
618
618
|
});
|
|
619
|
+
it("strips base prefix from script src entry points", async () => {
|
|
620
|
+
const code = `
|
|
621
|
+
jsx("script", {
|
|
622
|
+
src: "/auth/src/client.tsx",
|
|
623
|
+
type: "module"
|
|
624
|
+
})
|
|
625
|
+
`;
|
|
626
|
+
const clientEntryPoints = new Set();
|
|
627
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/auth/");
|
|
628
|
+
expect(clientEntryPoints.has("/src/client.tsx")).toBe(true);
|
|
629
|
+
expect(clientEntryPoints.has("/auth/src/client.tsx")).toBe(false);
|
|
630
|
+
expect(result?.code).toContain('scriptsToBeLoaded.add("/src/client.tsx")');
|
|
631
|
+
expect(result?.code).not.toContain('scriptsToBeLoaded.add("/auth/src/client.tsx")');
|
|
632
|
+
});
|
|
633
|
+
it("strips base prefix from dynamic imports in inline scripts", async () => {
|
|
634
|
+
const code = `
|
|
635
|
+
jsx("script", {
|
|
636
|
+
type: "module",
|
|
637
|
+
children: "import('/auth/src/client.tsx')"
|
|
638
|
+
})
|
|
639
|
+
`;
|
|
640
|
+
const clientEntryPoints = new Set();
|
|
641
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/auth/");
|
|
642
|
+
expect(clientEntryPoints.has("/src/client.tsx")).toBe(true);
|
|
643
|
+
expect(clientEntryPoints.has("/auth/src/client.tsx")).toBe(false);
|
|
644
|
+
expect(result?.code).toContain('scriptsToBeLoaded.add("/src/client.tsx")');
|
|
645
|
+
});
|
|
646
|
+
it("strips base prefix from link preload href in asset paths", async () => {
|
|
647
|
+
const code = `
|
|
648
|
+
jsx("link", {
|
|
649
|
+
rel: "modulepreload",
|
|
650
|
+
href: "/auth/src/client.tsx"
|
|
651
|
+
})
|
|
652
|
+
`;
|
|
653
|
+
const clientEntryPoints = new Set();
|
|
654
|
+
const result = await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/auth/");
|
|
655
|
+
expect(result?.code).toContain("rwsdk_asset:/src/client.tsx");
|
|
656
|
+
expect(result?.code).not.toContain("rwsdk_asset:/auth/src/client.tsx");
|
|
657
|
+
});
|
|
658
|
+
it("does not strip when base is /", async () => {
|
|
659
|
+
const code = `
|
|
660
|
+
jsx("script", {
|
|
661
|
+
src: "/src/client.tsx",
|
|
662
|
+
type: "module"
|
|
663
|
+
})
|
|
664
|
+
`;
|
|
665
|
+
const clientEntryPoints = new Set();
|
|
666
|
+
await transformJsxScriptTagsCode(code, clientEntryPoints, mockManifest, "/project/root/dir", "/");
|
|
667
|
+
expect(clientEntryPoints.has("/src/client.tsx")).toBe(true);
|
|
668
|
+
});
|
|
619
669
|
});
|
|
@@ -1 +1,153 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ResolvedConfig } from "vite";
|
|
2
|
+
export declare const vitePreamblePlugin: () => {
|
|
3
|
+
configResolved(config: ResolvedConfig): void;
|
|
4
|
+
hotUpdate?: import("rollup").ObjectHook<(this: import("rollup").MinimalPluginContext & {
|
|
5
|
+
environment: import("vite").DevEnvironment;
|
|
6
|
+
}, options: import("vite").HotUpdateOptions) => Array<import("vite").EnvironmentModuleNode> | void | Promise<Array<import("vite").EnvironmentModuleNode> | void>>;
|
|
7
|
+
resolveId?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, source: string, importer: string | undefined, options: {
|
|
8
|
+
attributes: Record<string, string>;
|
|
9
|
+
custom?: import("rollup").CustomPluginOptions;
|
|
10
|
+
ssr?: boolean | undefined;
|
|
11
|
+
isEntry: boolean;
|
|
12
|
+
}) => Promise<import("rollup").ResolveIdResult> | import("rollup").ResolveIdResult, {
|
|
13
|
+
filter?: {
|
|
14
|
+
id?: RegExp | RegExp[] | {
|
|
15
|
+
include?: RegExp | RegExp[] | undefined;
|
|
16
|
+
exclude?: RegExp | RegExp[] | undefined;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
load?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, id: string, options?: {
|
|
21
|
+
ssr?: boolean | undefined;
|
|
22
|
+
}) => Promise<import("rollup").LoadResult> | import("rollup").LoadResult, {
|
|
23
|
+
filter?: {
|
|
24
|
+
id?: string | RegExp | (string | RegExp)[] | {
|
|
25
|
+
include?: string | RegExp | (string | RegExp)[] | undefined;
|
|
26
|
+
exclude?: string | RegExp | (string | RegExp)[] | undefined;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
}>;
|
|
30
|
+
transform?: import("rollup").ObjectHook<(this: import("rollup").TransformPluginContext, code: string, id: string, options?: {
|
|
31
|
+
ssr?: boolean | undefined;
|
|
32
|
+
}) => Promise<import("rollup").TransformResult> | import("rollup").TransformResult, {
|
|
33
|
+
filter?: {
|
|
34
|
+
id?: string | RegExp | (string | RegExp)[] | {
|
|
35
|
+
include?: string | RegExp | (string | RegExp)[] | undefined;
|
|
36
|
+
exclude?: string | RegExp | (string | RegExp)[] | undefined;
|
|
37
|
+
};
|
|
38
|
+
code?: string | RegExp | (string | RegExp)[] | {
|
|
39
|
+
include?: string | RegExp | (string | RegExp)[] | undefined;
|
|
40
|
+
exclude?: string | RegExp | (string | RegExp)[] | undefined;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}>;
|
|
44
|
+
sharedDuringBuild?: boolean;
|
|
45
|
+
perEnvironmentStartEndDuringDev?: boolean;
|
|
46
|
+
perEnvironmentWatchChangeDuringDev?: boolean;
|
|
47
|
+
enforce?: "pre" | "post";
|
|
48
|
+
apply?: "serve" | "build" | ((this: void, config: import("vite").UserConfig, env: import("vite").ConfigEnv) => boolean);
|
|
49
|
+
applyToEnvironment?: (environment: {
|
|
50
|
+
name: string;
|
|
51
|
+
getTopLevelConfig(): ResolvedConfig;
|
|
52
|
+
config: ResolvedConfig & {
|
|
53
|
+
define?: Record<string, any>;
|
|
54
|
+
resolve: Required<import("vite").ResolveOptions>;
|
|
55
|
+
consumer: "client" | "server";
|
|
56
|
+
keepProcessEnv?: boolean;
|
|
57
|
+
optimizeDeps: import("vite").DepOptimizationOptions;
|
|
58
|
+
dev: import("vite").ResolvedDevEnvironmentOptions;
|
|
59
|
+
build: import("vite").ResolvedBuildEnvironmentOptions;
|
|
60
|
+
plugins: readonly import("vite").Plugin[];
|
|
61
|
+
};
|
|
62
|
+
logger: import("vite").Logger;
|
|
63
|
+
}) => boolean | Promise<boolean> | import("vite").PluginOption;
|
|
64
|
+
config?: import("rollup").ObjectHook<(this: import("vite").ConfigPluginContext, config: import("vite").UserConfig, env: import("vite").ConfigEnv) => Omit<import("vite").UserConfig, "plugins"> | null | void | Promise<Omit<import("vite").UserConfig, "plugins"> | null | void>>;
|
|
65
|
+
configEnvironment?: import("rollup").ObjectHook<(this: import("vite").ConfigPluginContext, name: string, config: import("vite").EnvironmentOptions, env: import("vite").ConfigEnv & {
|
|
66
|
+
isSsrTargetWebworker?: boolean;
|
|
67
|
+
}) => import("vite").EnvironmentOptions | null | void | Promise<import("vite").EnvironmentOptions | null | void>>;
|
|
68
|
+
configureServer?: import("rollup").ObjectHook<import("vite").ServerHook>;
|
|
69
|
+
configurePreviewServer?: import("rollup").ObjectHook<import("vite").PreviewServerHook>;
|
|
70
|
+
transformIndexHtml?: import("vite").IndexHtmlTransform;
|
|
71
|
+
buildApp?: import("rollup").ObjectHook<import("vite").BuildAppHook>;
|
|
72
|
+
handleHotUpdate?: import("rollup").ObjectHook<(this: import("vite").MinimalPluginContextWithoutEnvironment, ctx: import("vite").HmrContext) => Array<import("vite").ModuleNode> | void | Promise<Array<import("vite").ModuleNode> | void>>;
|
|
73
|
+
api?: any;
|
|
74
|
+
cacheKey?: string | undefined;
|
|
75
|
+
name: string;
|
|
76
|
+
version?: string | undefined;
|
|
77
|
+
renderError?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, error?: Error | undefined) => void | Promise<void>, {
|
|
78
|
+
sequential?: boolean;
|
|
79
|
+
}> | undefined;
|
|
80
|
+
augmentChunkHash?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, chunk: import("rollup").RenderedChunk) => string | void, {}> | undefined;
|
|
81
|
+
generateBundle?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: import("rollup").NormalizedOutputOptions, bundle: import("rollup").OutputBundle, isWrite: boolean) => void | Promise<void>, {}> | undefined;
|
|
82
|
+
outputOptions?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: import("rollup").OutputOptions) => import("rollup").OutputOptions | import("rollup").NullValue, {}> | undefined;
|
|
83
|
+
renderChunk?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, code: string, chunk: import("rollup").RenderedChunk, options: import("rollup").NormalizedOutputOptions, meta: {
|
|
84
|
+
chunks: Record<string, import("rollup").RenderedChunk>;
|
|
85
|
+
}) => string | {
|
|
86
|
+
code: string;
|
|
87
|
+
map?: import("rollup").SourceMapInput;
|
|
88
|
+
} | import("rollup").NullValue | Promise<string | {
|
|
89
|
+
code: string;
|
|
90
|
+
map?: import("rollup").SourceMapInput;
|
|
91
|
+
} | import("rollup").NullValue>, {}> | undefined;
|
|
92
|
+
renderDynamicImport?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: {
|
|
93
|
+
customResolution: string | null;
|
|
94
|
+
format: import("rollup").InternalModuleFormat;
|
|
95
|
+
moduleId: string;
|
|
96
|
+
targetModuleId: string | null;
|
|
97
|
+
chunk: import("rollup").PreRenderedChunkWithFileName;
|
|
98
|
+
targetChunk: import("rollup").PreRenderedChunkWithFileName | null;
|
|
99
|
+
getTargetChunkImports: () => import("rollup").DynamicImportTargetChunk[] | null;
|
|
100
|
+
targetModuleAttributes: Record<string, string>;
|
|
101
|
+
}) => {
|
|
102
|
+
left: string;
|
|
103
|
+
right: string;
|
|
104
|
+
} | import("rollup").NullValue, {}> | undefined;
|
|
105
|
+
renderStart?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, outputOptions: import("rollup").NormalizedOutputOptions, inputOptions: import("rollup").NormalizedInputOptions) => void | Promise<void>, {
|
|
106
|
+
sequential?: boolean;
|
|
107
|
+
}> | undefined;
|
|
108
|
+
resolveFileUrl?: import("rollup").ObjectHook<import("rollup").ResolveFileUrlHook, {}> | undefined;
|
|
109
|
+
resolveImportMeta?: import("rollup").ObjectHook<import("rollup").ResolveImportMetaHook, {}> | undefined;
|
|
110
|
+
writeBundle?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: import("rollup").NormalizedOutputOptions, bundle: import("rollup").OutputBundle) => void | Promise<void>, {
|
|
111
|
+
sequential?: boolean;
|
|
112
|
+
}> | undefined;
|
|
113
|
+
footer?: import("rollup").ObjectHook<import("rollup").AddonHook, {}> | undefined;
|
|
114
|
+
banner?: import("rollup").ObjectHook<import("rollup").AddonHook, {}> | undefined;
|
|
115
|
+
intro?: import("rollup").ObjectHook<import("rollup").AddonHook, {}> | undefined;
|
|
116
|
+
outro?: import("rollup").ObjectHook<import("rollup").AddonHook, {}> | undefined;
|
|
117
|
+
buildEnd?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, error?: Error | undefined) => void | Promise<void>, {
|
|
118
|
+
sequential?: boolean;
|
|
119
|
+
}> | undefined;
|
|
120
|
+
buildStart?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: import("rollup").NormalizedInputOptions) => void | Promise<void>, {
|
|
121
|
+
sequential?: boolean;
|
|
122
|
+
}> | undefined;
|
|
123
|
+
closeBundle?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, error?: Error | undefined) => void | Promise<void>, {
|
|
124
|
+
sequential?: boolean;
|
|
125
|
+
}> | undefined;
|
|
126
|
+
closeWatcher?: import("rollup").ObjectHook<(this: import("rollup").PluginContext) => void | Promise<void>, {
|
|
127
|
+
sequential?: boolean;
|
|
128
|
+
}> | undefined;
|
|
129
|
+
moduleParsed?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, info: import("rollup").ModuleInfo) => void | Promise<void>, {
|
|
130
|
+
sequential?: boolean;
|
|
131
|
+
}> | undefined;
|
|
132
|
+
onLog?: import("rollup").ObjectHook<(this: import("rollup").MinimalPluginContext, level: import("rollup").LogLevel, log: import("rollup").RollupLog) => boolean | import("rollup").NullValue, {}> | undefined;
|
|
133
|
+
options?: import("rollup").ObjectHook<(this: import("rollup").MinimalPluginContext, options: import("rollup").InputOptions) => import("rollup").InputOptions | import("rollup").NullValue | Promise<import("rollup").InputOptions | import("rollup").NullValue>, {}> | undefined;
|
|
134
|
+
resolveDynamicImport?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, specifier: string | import("rollup").AstNode, importer: string, options: {
|
|
135
|
+
attributes: Record<string, string>;
|
|
136
|
+
importerAttributes: Record<string, string>;
|
|
137
|
+
}) => import("rollup").ResolveIdResult | Promise<import("rollup").ResolveIdResult>, {}> | undefined;
|
|
138
|
+
shouldTransformCachedModule?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, options: {
|
|
139
|
+
ast: import("rollup").ProgramNode;
|
|
140
|
+
attributes: Record<string, string>;
|
|
141
|
+
code: string;
|
|
142
|
+
id: string;
|
|
143
|
+
meta: import("rollup").CustomPluginOptions;
|
|
144
|
+
moduleSideEffects: boolean | "no-treeshake";
|
|
145
|
+
resolvedSources: import("rollup").ResolvedIdMap;
|
|
146
|
+
syntheticNamedExports: boolean | string;
|
|
147
|
+
}) => boolean | import("rollup").NullValue | Promise<boolean | import("rollup").NullValue>, {}> | undefined;
|
|
148
|
+
watchChange?: import("rollup").ObjectHook<(this: import("rollup").PluginContext, id: string, change: {
|
|
149
|
+
event: import("rollup").ChangeEvent;
|
|
150
|
+
}) => void | Promise<void>, {
|
|
151
|
+
sequential?: boolean;
|
|
152
|
+
}> | undefined;
|
|
153
|
+
};
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import MagicString from "magic-string";
|
|
2
2
|
import { virtualPlugin } from "./virtualPlugin.mjs";
|
|
3
|
-
export const vitePreamblePlugin = () =>
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export const vitePreamblePlugin = () => {
|
|
4
|
+
let base = "/";
|
|
5
|
+
const inner = virtualPlugin("vite-preamble", async () => {
|
|
6
|
+
const refreshPath = base.replace(/\/$/, "") + "/@react-refresh";
|
|
7
|
+
const s = new MagicString(`
|
|
8
|
+
import RefreshRuntime from "${refreshPath}"; RefreshRuntime.injectIntoGlobalHook(window); window.$RefreshReg$ = () => {}; window.$RefreshSig$ = () => (type) => type; window.__vite_plugin_react_preamble_installed__ = true;
|
|
6
9
|
`);
|
|
10
|
+
return {
|
|
11
|
+
code: s.toString(),
|
|
12
|
+
map: s.generateMap(),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
7
15
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
...inner,
|
|
17
|
+
configResolved(config) {
|
|
18
|
+
base = config.base || "/";
|
|
19
|
+
},
|
|
10
20
|
};
|
|
11
|
-
}
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rwsdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
"glob": "~13.0.6",
|
|
177
177
|
"ignore": "~7.0.5",
|
|
178
178
|
"jsonc-parser": "~3.3.1",
|
|
179
|
-
"kysely": "~0.28.
|
|
179
|
+
"kysely": "~0.28.12",
|
|
180
180
|
"kysely-do": "~0.0.1-rc.1",
|
|
181
181
|
"lodash": "~4.17.23",
|
|
182
182
|
"magic-string": "~0.30.21",
|