rwsdk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/imports/client.js +4 -9
- package/dist/runtime/imports/worker.js +2 -1
- package/dist/runtime/register/ssr.js +2 -1
- package/dist/runtime/requestInfo/worker.js +9 -1
- package/dist/runtime/worker.d.ts +0 -3
- package/dist/runtime/worker.js +1 -10
- package/dist/scripts/debug-sync.mjs +0 -23
- package/dist/scripts/smoke-test.mjs +0 -10
- package/dist/vite/buildApp.d.mts +15 -0
- package/dist/vite/buildApp.mjs +53 -0
- package/dist/vite/configPlugin.d.mts +4 -4
- package/dist/vite/configPlugin.mjs +70 -76
- package/dist/vite/constants.d.mts +2 -0
- package/dist/vite/constants.mjs +12 -0
- package/dist/vite/createDirectiveLookupPlugin.d.mts +0 -6
- package/dist/vite/createDirectiveLookupPlugin.mjs +69 -145
- package/dist/vite/createViteAwareResolver.d.mts +4 -0
- package/dist/vite/createViteAwareResolver.mjs +208 -0
- package/dist/vite/directiveModulesDevPlugin.d.mts +8 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +87 -0
- package/dist/vite/directivesFilteringPlugin.d.mts +6 -0
- package/dist/vite/directivesFilteringPlugin.mjs +31 -0
- package/dist/vite/directivesPlugin.mjs +32 -42
- package/dist/vite/getViteEsbuild.d.mts +1 -0
- package/dist/vite/getViteEsbuild.mjs +12 -0
- package/dist/vite/injectVitePreamblePlugin.d.mts +3 -2
- package/dist/vite/injectVitePreamblePlugin.mjs +8 -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 +20 -37
- package/dist/vite/moveStaticAssetsPlugin.mjs +2 -1
- package/dist/vite/prismaPlugin.mjs +1 -1
- package/dist/vite/reactConditionsResolverPlugin.mjs +15 -16
- package/dist/vite/redwoodPlugin.d.mts +0 -1
- package/dist/vite/redwoodPlugin.mjs +27 -9
- package/dist/vite/runDirectivesScan.d.mts +7 -0
- package/dist/vite/runDirectivesScan.mjs +156 -0
- package/dist/vite/ssrBridgePlugin.mjs +21 -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 +66 -84
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +67 -41
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +11 -12
- package/dist/vite/virtualPlugin.mjs +8 -0
- package/package.json +7 -1
- package/dist/runtime/clientNavigation.d.ts +0 -9
- package/dist/runtime/clientNavigation.js +0 -88
package/dist/lib/constants.d.mts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export declare const ROOT_DIR: string;
|
|
2
2
|
export declare const SRC_DIR: string;
|
|
3
3
|
export declare const DIST_DIR: string;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const VITE_DIR: string;
|
|
5
|
+
export declare const INTERMEDIATES_OUTPUT_DIR: string;
|
|
6
|
+
export declare const CLIENT_BARREL_PATH: string;
|
|
7
|
+
export declare const SERVER_BARREL_PATH: string;
|
|
8
|
+
export declare const INTERMEDIATE_SSR_BRIDGE_PATH: string;
|
|
9
|
+
export declare const CLIENT_MANIFEST_RELATIVE_PATH: string;
|
package/dist/lib/constants.mjs
CHANGED
|
@@ -3,4 +3,9 @@ const __dirname = new URL(".", import.meta.url).pathname;
|
|
|
3
3
|
export const ROOT_DIR = resolve(__dirname, "..", "..");
|
|
4
4
|
export const SRC_DIR = resolve(ROOT_DIR, "src");
|
|
5
5
|
export const DIST_DIR = resolve(ROOT_DIR, "dist");
|
|
6
|
-
export const
|
|
6
|
+
export const VITE_DIR = resolve(ROOT_DIR, "src", "vite");
|
|
7
|
+
export const INTERMEDIATES_OUTPUT_DIR = resolve(DIST_DIR, "__intermediate_builds");
|
|
8
|
+
export const CLIENT_BARREL_PATH = resolve(INTERMEDIATES_OUTPUT_DIR, "rwsdk-client-barrel.js");
|
|
9
|
+
export const SERVER_BARREL_PATH = resolve(INTERMEDIATES_OUTPUT_DIR, "rwsdk-server-barrel.js");
|
|
10
|
+
export const INTERMEDIATE_SSR_BRIDGE_PATH = resolve(INTERMEDIATES_OUTPUT_DIR, "ssr", "ssr_bridge.js");
|
|
11
|
+
export const CLIENT_MANIFEST_RELATIVE_PATH = resolve("dist", "client", ".vite", "manifest.json");
|
|
@@ -316,25 +316,9 @@ export async function checkUrl(url, artifactDir, browserPath, headless = true, b
|
|
|
316
316
|
export async function checkUrlSmoke(page, url, isRealtime, bail = false, skipClient = false, environment = "Development", timestampState, targetDir, skipHmr = false, skipStyleTests = false) {
|
|
317
317
|
const phase = isRealtime ? "Post-upgrade" : "Initial";
|
|
318
318
|
console.log(`🔍 Testing ${phase} smoke tests at ${url}`);
|
|
319
|
-
// Parse the base URL and path to properly handle smoke test queries
|
|
320
|
-
const parsedUrl = new URL(url);
|
|
321
|
-
log("Parsed URL: %O", {
|
|
322
|
-
origin: parsedUrl.origin,
|
|
323
|
-
pathname: parsedUrl.pathname,
|
|
324
|
-
search: parsedUrl.search,
|
|
325
|
-
});
|
|
326
|
-
// Add __smoke_test query parameter, preserving any existing query parameters
|
|
327
|
-
if (parsedUrl.searchParams.has("__smoke_test")) {
|
|
328
|
-
console.log(`URL already has __smoke_test parameter: ${url}`);
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
parsedUrl.searchParams.append("__smoke_test", "1");
|
|
332
|
-
log("Added __smoke_test parameter to URL");
|
|
333
|
-
}
|
|
334
319
|
// Navigate to smoke test page
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
await page.goto(smokeUrl, { waitUntil: "networkidle0" });
|
|
320
|
+
console.log(`🔍 Accessing smoke test page: ${url}`);
|
|
321
|
+
await page.goto(url, { waitUntil: "networkidle0" });
|
|
338
322
|
log("Page loaded successfully");
|
|
339
323
|
// Track failures to report at the end
|
|
340
324
|
let hasFailures = false;
|
|
@@ -692,9 +676,9 @@ export async function checkClientSmoke(page, phase = "", environment = "Developm
|
|
|
692
676
|
// Check if we're on a smoke test page - in which case missing the refresh button is a failure
|
|
693
677
|
const currentUrl = page.url();
|
|
694
678
|
log("Current URL: %s", currentUrl);
|
|
695
|
-
if (currentUrl.includes("__smoke_test")) {
|
|
696
|
-
log("ERROR: Smoke test page is
|
|
697
|
-
throw new Error("Smoke test page is
|
|
679
|
+
if (!currentUrl.includes("/__smoke_test")) {
|
|
680
|
+
log("ERROR: Smoke test page is not the current URL");
|
|
681
|
+
throw new Error("Smoke test page is not the current URL - this is a test failure");
|
|
698
682
|
}
|
|
699
683
|
console.log("ℹ️ Basic page structure verified, continuing without client-side smoke test");
|
|
700
684
|
return null;
|
|
@@ -6,4 +6,4 @@ export declare function createSmokeTestStylesheets(targetDir: string): Promise<v
|
|
|
6
6
|
/**
|
|
7
7
|
* Modifies the worker.tsx and wrangler.jsonc files to add realtime support
|
|
8
8
|
*/
|
|
9
|
-
export declare function modifyAppForRealtime(targetDir: string): Promise<void>;
|
|
9
|
+
export declare function modifyAppForRealtime(targetDir: string, skipClient?: boolean): Promise<void>;
|
|
@@ -46,7 +46,7 @@ export async function createSmokeTestComponents(targetDir, skipClient = false) {
|
|
|
46
46
|
log("Skipping client-side smoke test component creation");
|
|
47
47
|
}
|
|
48
48
|
// Modify worker.tsx and wrangler.jsonc for realtime support
|
|
49
|
-
await modifyAppForRealtime(targetDir);
|
|
49
|
+
await modifyAppForRealtime(targetDir, skipClient);
|
|
50
50
|
log("Smoke test components created successfully");
|
|
51
51
|
console.log("Created smoke test components:");
|
|
52
52
|
console.log(`- ${smokeTestFunctionsPath}`);
|
|
@@ -104,7 +104,7 @@ export async function createSmokeTestStylesheets(targetDir) {
|
|
|
104
104
|
/**
|
|
105
105
|
* Modifies the worker.tsx and wrangler.jsonc files to add realtime support
|
|
106
106
|
*/
|
|
107
|
-
export async function modifyAppForRealtime(targetDir) {
|
|
107
|
+
export async function modifyAppForRealtime(targetDir, skipClient = false) {
|
|
108
108
|
log("Modifying worker.tsx and wrangler.jsonc for realtime support");
|
|
109
109
|
// Modify worker.tsx
|
|
110
110
|
const workerPath = join(targetDir, "src", "worker.tsx");
|
|
@@ -118,8 +118,14 @@ export async function modifyAppForRealtime(targetDir) {
|
|
|
118
118
|
const hasRealtimeExport = workerContent.includes('export { RealtimeDurableObject } from "rwsdk/realtime/durableObject"');
|
|
119
119
|
const hasRealtimeRoute = workerContent.includes("realtimeRoute(");
|
|
120
120
|
const hasEnvImport = workerContent.includes('import { env } from "cloudflare:workers"');
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
const hasSmokeTestImport = workerContent.includes('import { SmokeTest } from "@/app/components/__SmokeTest.tsx"');
|
|
122
|
+
const hasSmokeTestRoute = workerContent.includes('route("/__smoke_test", SmokeTest)');
|
|
123
|
+
if (!hasRealtimeExport ||
|
|
124
|
+
!hasRealtimeRoute ||
|
|
125
|
+
!hasEnvImport ||
|
|
126
|
+
!hasSmokeTestImport ||
|
|
127
|
+
!hasSmokeTestRoute) {
|
|
128
|
+
log("Need to modify worker.tsx for realtime and smoke test support");
|
|
123
129
|
const s = new MagicString(workerContent);
|
|
124
130
|
// Add the export line if it doesn't exist
|
|
125
131
|
if (!hasRealtimeExport) {
|
|
@@ -145,6 +151,26 @@ export async function modifyAppForRealtime(targetDir) {
|
|
|
145
151
|
log("Added env import from cloudflare:workers");
|
|
146
152
|
}
|
|
147
153
|
}
|
|
154
|
+
// Add SmokeTest import if it doesn't exist
|
|
155
|
+
if (!hasSmokeTestImport) {
|
|
156
|
+
const importRegex = /import.*?from.*?;\n/g;
|
|
157
|
+
let lastImportMatch;
|
|
158
|
+
let lastImportPosition = 0;
|
|
159
|
+
// Find the position after the last import statement
|
|
160
|
+
while ((lastImportMatch = importRegex.exec(workerContent)) !== null) {
|
|
161
|
+
lastImportPosition =
|
|
162
|
+
lastImportMatch.index + lastImportMatch[0].length;
|
|
163
|
+
}
|
|
164
|
+
if (lastImportPosition > 0) {
|
|
165
|
+
s.appendRight(lastImportPosition, 'import { SmokeTest } from "@/app/components/__SmokeTest";\n');
|
|
166
|
+
log("Added SmokeTest import");
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// if no imports found, just prepend to the file
|
|
170
|
+
s.prepend('import { SmokeTest } from "@/app/components/__SmokeTest";\n');
|
|
171
|
+
log("Added SmokeTest import to the beginning of the file");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
148
174
|
// Add the realtimeRoute line if it doesn't exist
|
|
149
175
|
if (!hasRealtimeRoute) {
|
|
150
176
|
const defineAppMatch = workerContent.match(/export default defineApp\(\[/);
|
|
@@ -154,6 +180,16 @@ export async function modifyAppForRealtime(targetDir) {
|
|
|
154
180
|
log("Added realtimeRoute to defineApp");
|
|
155
181
|
}
|
|
156
182
|
}
|
|
183
|
+
// Add the smoke test route if it doesn't exist
|
|
184
|
+
if (!hasSmokeTestRoute) {
|
|
185
|
+
const defineAppRegex = /(export default defineApp\(\[)([\s\S]*)(\]\);)/m;
|
|
186
|
+
const match = workerContent.match(defineAppRegex);
|
|
187
|
+
if (match) {
|
|
188
|
+
const insertionPoint = match.index + match[1].length + match[2].length;
|
|
189
|
+
s.appendLeft(insertionPoint, ' render(Document, [route("/__smoke_test", SmokeTest)]),\n');
|
|
190
|
+
log("Added smoke test route to defineApp");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
157
193
|
// Import realtimeRoute if it's not already imported
|
|
158
194
|
if (!workerContent.includes("realtimeRoute")) {
|
|
159
195
|
// First check if we already have the import from rwsdk/realtime/worker
|
|
@@ -196,7 +232,7 @@ export async function modifyAppForRealtime(targetDir) {
|
|
|
196
232
|
log("Successfully modified worker.tsx");
|
|
197
233
|
}
|
|
198
234
|
else {
|
|
199
|
-
log("worker.tsx already has realtime support, no changes needed");
|
|
235
|
+
log("worker.tsx already has realtime and smoke test support, no changes needed");
|
|
200
236
|
}
|
|
201
237
|
}
|
|
202
238
|
else {
|
|
@@ -8,4 +8,4 @@ export declare function runDevServer(cwd?: string): Promise<{
|
|
|
8
8
|
/**
|
|
9
9
|
* Runs tests against the development server
|
|
10
10
|
*/
|
|
11
|
-
export declare function runDevTest(url: string, artifactDir: string,
|
|
11
|
+
export declare function runDevTest(url: string, artifactDir: string, browserPath?: string, headless?: boolean, bail?: boolean, skipClient?: boolean, realtime?: boolean, skipHmr?: boolean, skipStyleTests?: boolean): Promise<void>;
|
|
@@ -172,21 +172,15 @@ export async function runDevServer(cwd) {
|
|
|
172
172
|
/**
|
|
173
173
|
* Runs tests against the development server
|
|
174
174
|
*/
|
|
175
|
-
export async function runDevTest(url, artifactDir,
|
|
176
|
-
log("Starting dev server test
|
|
175
|
+
export async function runDevTest(url, artifactDir, browserPath, headless = true, bail = false, skipClient = false, realtime = false, skipHmr = false, skipStyleTests = false) {
|
|
176
|
+
log("Starting dev server test");
|
|
177
177
|
console.log("🚀 Testing local development server");
|
|
178
178
|
const browser = await launchBrowser(browserPath, headless);
|
|
179
179
|
const page = await browser.newPage();
|
|
180
180
|
try {
|
|
181
|
+
const testUrl = new URL("/__smoke_test", url).toString();
|
|
181
182
|
// DRY: check both root and custom path
|
|
182
|
-
await checkServerUp(url,
|
|
183
|
-
// Now run the tests with the custom path
|
|
184
|
-
const testUrl = url +
|
|
185
|
-
(customPath === "/"
|
|
186
|
-
? ""
|
|
187
|
-
: customPath.startsWith("/")
|
|
188
|
-
? customPath
|
|
189
|
-
: "/" + customPath);
|
|
183
|
+
await checkServerUp(url, "/", RETRIES, bail);
|
|
190
184
|
// Pass the target directory to checkUrl for HMR testing
|
|
191
185
|
const targetDir = state.resources.targetDir;
|
|
192
186
|
await page.goto(testUrl, { waitUntil: "networkidle0" });
|
|
@@ -40,7 +40,7 @@ export declare function runRelease(cwd: string, projectDir: string, resourceUniq
|
|
|
40
40
|
/**
|
|
41
41
|
* Runs tests against the production deployment
|
|
42
42
|
*/
|
|
43
|
-
export declare function runReleaseTest(
|
|
43
|
+
export declare function runReleaseTest(artifactDir: string, resources: TestResources, browserPath?: string, headless?: boolean, bail?: boolean, skipClient?: boolean, projectDir?: string, realtime?: boolean, skipHmr?: boolean, skipStyleTests?: boolean): Promise<void>;
|
|
44
44
|
/**
|
|
45
45
|
* Check if a resource name includes a specific resource unique key
|
|
46
46
|
* This is used to identify resources created during our tests
|
|
@@ -379,8 +379,8 @@ export async function runRelease(cwd, projectDir, resourceUniqueKey) {
|
|
|
379
379
|
/**
|
|
380
380
|
* Runs tests against the production deployment
|
|
381
381
|
*/
|
|
382
|
-
export async function runReleaseTest(
|
|
383
|
-
log("Starting release test
|
|
382
|
+
export async function runReleaseTest(artifactDir, resources, browserPath, headless = true, bail = false, skipClient = false, projectDir, realtime = false, skipHmr = false, skipStyleTests = false) {
|
|
383
|
+
log("Starting release test");
|
|
384
384
|
console.log("\n🚀 Testing production deployment");
|
|
385
385
|
try {
|
|
386
386
|
log("Running release process");
|
|
@@ -389,14 +389,9 @@ export async function runReleaseTest(customPath = "/", artifactDir, resources, b
|
|
|
389
389
|
log("Waiting 1s before checking server...");
|
|
390
390
|
await setTimeout(1000);
|
|
391
391
|
// DRY: check both root and custom path
|
|
392
|
-
await checkServerUp(url,
|
|
392
|
+
await checkServerUp(url, "/");
|
|
393
393
|
// Now run the tests with the custom path
|
|
394
|
-
const testUrl = url
|
|
395
|
-
(customPath === "/"
|
|
396
|
-
? ""
|
|
397
|
-
: customPath.startsWith("/")
|
|
398
|
-
? customPath
|
|
399
|
-
: "/" + customPath);
|
|
394
|
+
const testUrl = new URL("/__smoke_test", url).toString();
|
|
400
395
|
await checkUrl(testUrl, artifactDir, browserPath, headless, bail, skipClient, "Production", realtime, resources.targetDir, // Add target directory parameter
|
|
401
396
|
true, // Always skip HMR in production
|
|
402
397
|
skipStyleTests);
|
|
@@ -57,7 +57,7 @@ export async function runSmokeTests(options = {}) {
|
|
|
57
57
|
resources.stopDev = stopDev;
|
|
58
58
|
state.resources.stopDev = stopDev;
|
|
59
59
|
log("Running development server tests");
|
|
60
|
-
await runDevTest(url, options.artifactDir,
|
|
60
|
+
await runDevTest(url, options.artifactDir, browserPath, options.headless !== false, options.bail, options.skipClient, options.realtime, options.skipHmr, options.skipStyleTests);
|
|
61
61
|
// Mark that dev tests have run successfully
|
|
62
62
|
state.devTestsRan = true;
|
|
63
63
|
// Update the overall dev test status to PASSED
|
|
@@ -95,7 +95,7 @@ export async function runSmokeTests(options = {}) {
|
|
|
95
95
|
// Update status when release command runs
|
|
96
96
|
try {
|
|
97
97
|
console.log("\n🚀 Running release command smoke test");
|
|
98
|
-
await runReleaseTest(options.
|
|
98
|
+
await runReleaseTest(options.artifactDir, resources, browserPath, options.headless !== false, options.bail, options.skipClient, options.projectDir, options.realtime, options.skipHmr, options.skipStyleTests);
|
|
99
99
|
// Update release command status to PASSED
|
|
100
100
|
updateTestStatus("production", "releaseCommand", "PASSED");
|
|
101
101
|
// Mark that release tests have run successfully
|
|
@@ -5,7 +5,7 @@ import { RequestInfo } from "rwsdk/worker";
|
|
|
5
5
|
${skipClient ? "" : 'import { SmokeTestClient } from "./__SmokeTestClient";'}
|
|
6
6
|
import { getSmokeTestTimestamp } from "./__smokeTestFunctions";
|
|
7
7
|
|
|
8
|
-
export const
|
|
8
|
+
export const SmokeTest = async () => {
|
|
9
9
|
const currentTime = Date.now();
|
|
10
10
|
let status = "error";
|
|
11
11
|
let timestamp = 0;
|
|
@@ -77,5 +77,6 @@ export const SmokeTestInfo: React.FC = async () => {
|
|
|
77
77
|
${!skipClient ? "<SmokeTestClient/>" : ""}
|
|
78
78
|
</div>
|
|
79
79
|
);
|
|
80
|
-
}
|
|
80
|
+
};
|
|
81
|
+
`;
|
|
81
82
|
}
|
|
@@ -4,16 +4,11 @@ import { memoizeOnId } from "../lib/memoizeOnId";
|
|
|
4
4
|
// @ts-ignore
|
|
5
5
|
import { useClientLookup } from "virtual:use-client-lookup.js";
|
|
6
6
|
export const loadModule = memoizeOnId(async (id) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
else {
|
|
11
|
-
const moduleFn = useClientLookup[id];
|
|
12
|
-
if (!moduleFn) {
|
|
13
|
-
throw new Error(`(client) No module found for '${id}' in module lookup for "use client" directive`);
|
|
14
|
-
}
|
|
15
|
-
return await moduleFn();
|
|
7
|
+
const moduleFn = useClientLookup[id];
|
|
8
|
+
if (!moduleFn) {
|
|
9
|
+
throw new Error(`(client) No module found for '${id}' in module lookup for "use client" directive`);
|
|
16
10
|
}
|
|
11
|
+
return await moduleFn();
|
|
17
12
|
});
|
|
18
13
|
// context(justinvdm, 2 Dec 2024): re memoize(): React relies on the same promise instance being returned for the same id
|
|
19
14
|
export const clientWebpackRequire = memoizeOnId(async (id) => {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { requestInfo } from "../requestInfo/worker";
|
|
2
2
|
import { ssrWebpackRequire as baseSsrWebpackRequire } from "rwsdk/__ssr_bridge";
|
|
3
3
|
import { memoizeOnId } from "../lib/memoizeOnId";
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import { useServerLookup } from "virtual:use-server-lookup.js";
|
|
4
6
|
export const loadServerModule = memoizeOnId(async (id) => {
|
|
5
|
-
const { useServerLookup } = await import("virtual:use-server-lookup.js");
|
|
6
7
|
const moduleFn = useServerLookup[id];
|
|
7
8
|
if (!moduleFn) {
|
|
8
9
|
throw new Error(`(worker) No module found for '${id}' in module lookup for "use server" directive`);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createServerReference as baseCreateServerReference } from "react-server-dom-webpack/client.edge";
|
|
2
2
|
import { memoizeOnId } from "../lib/memoizeOnId";
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { useServerLookup } from "virtual:use-server-lookup.js";
|
|
3
5
|
export const loadServerModule = memoizeOnId(async (id) => {
|
|
4
|
-
const { useServerLookup } = await import("virtual:use-server-lookup.js");
|
|
5
6
|
const moduleFn = useServerLookup[id];
|
|
6
7
|
if (!moduleFn) {
|
|
7
8
|
throw new Error(`(worker) No module found for '${id}' in module lookup for "use server" directive`);
|
|
@@ -2,7 +2,15 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
2
2
|
const requestInfoDeferred = Promise.withResolvers();
|
|
3
3
|
const requestInfoStore = new AsyncLocalStorage();
|
|
4
4
|
const requestInfoBase = {};
|
|
5
|
-
const REQUEST_INFO_KEYS = [
|
|
5
|
+
const REQUEST_INFO_KEYS = [
|
|
6
|
+
"request",
|
|
7
|
+
"params",
|
|
8
|
+
"ctx",
|
|
9
|
+
"headers",
|
|
10
|
+
"rw",
|
|
11
|
+
"cf",
|
|
12
|
+
"response",
|
|
13
|
+
];
|
|
6
14
|
REQUEST_INFO_KEYS.forEach((key) => {
|
|
7
15
|
Object.defineProperty(requestInfoBase, key, {
|
|
8
16
|
enumerable: true,
|
package/dist/runtime/worker.d.ts
CHANGED
|
@@ -10,9 +10,6 @@ declare global {
|
|
|
10
10
|
export declare const defineApp: <T extends RequestInfo = RequestInfo<any, DefaultAppContext>>(routes: Route<T>[]) => {
|
|
11
11
|
fetch: (request: Request, env: Env, cf: ExecutionContext) => Promise<Response>;
|
|
12
12
|
};
|
|
13
|
-
export declare const SmokeTestWrapper: React.FC<{
|
|
14
|
-
children: React.ReactNode;
|
|
15
|
-
}>;
|
|
16
13
|
export declare const DefaultDocument: React.FC<{
|
|
17
14
|
children: React.ReactNode;
|
|
18
15
|
}>;
|
package/dist/runtime/worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { transformRscToHtmlStream } from "./render/transformRscToHtmlStream";
|
|
3
3
|
import { renderToRscStream } from "./render/renderToRscStream";
|
|
4
4
|
import { rscActionHandler } from "./register/worker";
|
|
@@ -33,7 +33,6 @@ export const defineApp = (routes) => {
|
|
|
33
33
|
const url = new URL(request.url);
|
|
34
34
|
const isRSCRequest = url.searchParams.has("__rsc") ||
|
|
35
35
|
request.headers.get("accept")?.includes("text/x-component");
|
|
36
|
-
const isSmokeTest = url.searchParams.has("__smoke_test");
|
|
37
36
|
const userHeaders = new Headers();
|
|
38
37
|
const rw = {
|
|
39
38
|
Document: DefaultDocument,
|
|
@@ -67,9 +66,6 @@ export const defineApp = (routes) => {
|
|
|
67
66
|
else {
|
|
68
67
|
pageElement = _jsx(Page, { ...requestInfo });
|
|
69
68
|
}
|
|
70
|
-
if (isSmokeTest) {
|
|
71
|
-
pageElement = _jsx(SmokeTestWrapper, { children: pageElement });
|
|
72
|
-
}
|
|
73
69
|
return pageElement;
|
|
74
70
|
};
|
|
75
71
|
const renderPage = async (requestInfo, Page, onError) => {
|
|
@@ -175,11 +171,6 @@ export const defineApp = (routes) => {
|
|
|
175
171
|
},
|
|
176
172
|
};
|
|
177
173
|
};
|
|
178
|
-
export const SmokeTestWrapper = async ({ children }) => {
|
|
179
|
-
const smokeTestInfo = await Object.values(await import.meta.glob("/src/app/components/__SmokeTest.tsx"))[0]();
|
|
180
|
-
const SmokeTestInfo = smokeTestInfo.SmokeTestInfo;
|
|
181
|
-
return (_jsxs(_Fragment, { children: [_jsx(SmokeTestInfo, {}), children] }));
|
|
182
|
-
};
|
|
183
174
|
export const DefaultDocument = ({ children, }) => (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" })] }), _jsx("body", { children: _jsx("div", { id: "root", children: children }) })] }));
|
|
184
175
|
const isClientReference = (Component) => {
|
|
185
176
|
return Object.prototype.hasOwnProperty.call(Component, "$$isClientReference");
|
|
@@ -59,30 +59,11 @@ const cleanupViteEntries = async (targetDir) => {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
const performFullSync = async (sdkDir, targetDir) => {
|
|
62
|
-
const sdkPackageJsonPath = path.join(sdkDir, "package.json");
|
|
63
|
-
let originalSdkPackageJson = null;
|
|
64
62
|
let tarballPath = "";
|
|
65
63
|
let tarballName = "";
|
|
66
64
|
// Clean up vite cache
|
|
67
65
|
await cleanupViteEntries(targetDir);
|
|
68
66
|
try {
|
|
69
|
-
try {
|
|
70
|
-
originalSdkPackageJson = await fs.readFile(sdkPackageJsonPath, "utf-8");
|
|
71
|
-
const packageJson = JSON.parse(originalSdkPackageJson);
|
|
72
|
-
const originalVersion = packageJson.version;
|
|
73
|
-
const timestamp = new Date()
|
|
74
|
-
.toISOString()
|
|
75
|
-
.replace(/[-:T.]/g, "")
|
|
76
|
-
.slice(0, 14);
|
|
77
|
-
const newVersion = `${originalVersion}+build.${timestamp}`;
|
|
78
|
-
console.log(`Temporarily setting version to ${newVersion}`);
|
|
79
|
-
packageJson.version = newVersion;
|
|
80
|
-
await fs.writeFile(sdkPackageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
console.warn("Could not modify package.json version, proceeding without it.");
|
|
84
|
-
originalSdkPackageJson = null; // don't restore if we failed to modify
|
|
85
|
-
}
|
|
86
67
|
console.log("📦 Packing SDK...");
|
|
87
68
|
const packResult = await $({ cwd: sdkDir }) `npm pack --json`;
|
|
88
69
|
const json = JSON.parse(packResult.stdout || "[]");
|
|
@@ -152,10 +133,6 @@ const performFullSync = async (sdkDir, targetDir) => {
|
|
|
152
133
|
}
|
|
153
134
|
}
|
|
154
135
|
finally {
|
|
155
|
-
if (originalSdkPackageJson) {
|
|
156
|
-
console.log("Restoring package.json...");
|
|
157
|
-
await fs.writeFile(sdkPackageJsonPath, originalSdkPackageJson);
|
|
158
|
-
}
|
|
159
136
|
if (tarballPath) {
|
|
160
137
|
console.log("Removing tarball...");
|
|
161
138
|
await fs.unlink(tarballPath).catch(() => {
|
|
@@ -17,7 +17,6 @@ if (fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
|
17
17
|
const ciFlag = args.includes("--ci");
|
|
18
18
|
// Set initial default values (sync will be determined below)
|
|
19
19
|
const options = {
|
|
20
|
-
customPath: "/", // Default path
|
|
21
20
|
skipDev: false,
|
|
22
21
|
skipRelease: false,
|
|
23
22
|
skipClient: false,
|
|
@@ -88,7 +87,6 @@ Smoke Test Usage:
|
|
|
88
87
|
node smoke-test.mjs [options]
|
|
89
88
|
|
|
90
89
|
Options:
|
|
91
|
-
--url=PATH Custom URL path to test (e.g., "/login")
|
|
92
90
|
--skip-dev Skip testing the local development server
|
|
93
91
|
--skip-release Skip testing the release/production deployment
|
|
94
92
|
--skip-client Skip client-side tests, only run server-side checks
|
|
@@ -114,14 +112,6 @@ Options:
|
|
|
114
112
|
else if (arg.startsWith("--artifact-dir=")) {
|
|
115
113
|
options.artifactDir = arg.substring(15);
|
|
116
114
|
}
|
|
117
|
-
else if (arg.startsWith("--url=")) {
|
|
118
|
-
options.customPath = arg.substring(6);
|
|
119
|
-
}
|
|
120
|
-
else if (!arg.startsWith("--")) {
|
|
121
|
-
// For backwards compatibility, any non-flag argument is treated as the custom path
|
|
122
|
-
console.log(`Setting URL path to "${arg}" (use --url= format in the future)`);
|
|
123
|
-
options.customPath = arg;
|
|
124
|
-
}
|
|
125
115
|
else {
|
|
126
116
|
// Throw error for unknown options instead of just warning
|
|
127
117
|
log("Unknown option: %s", arg);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ViteBuilder } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* The build orchestrator is responsible for running the multi-phase build
|
|
4
|
+
* process for production. It is designed to solve the circular dependency
|
|
5
|
+
* between the worker, client, and SSR builds.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/architecture/productionBuildProcess.md
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, }: {
|
|
10
|
+
builder: ViteBuilder;
|
|
11
|
+
clientEntryPoints: Set<string>;
|
|
12
|
+
clientFiles: Set<string>;
|
|
13
|
+
serverFiles: Set<string>;
|
|
14
|
+
projectRootDir: string;
|
|
15
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import debug from "debug";
|
|
3
|
+
import { runDirectivesScan } from "./runDirectivesScan.mjs";
|
|
4
|
+
const log = debug("rwsdk:vite:build-app");
|
|
5
|
+
/**
|
|
6
|
+
* The build orchestrator is responsible for running the multi-phase build
|
|
7
|
+
* process for production. It is designed to solve the circular dependency
|
|
8
|
+
* between the worker, client, and SSR builds.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/architecture/productionBuildProcess.md
|
|
11
|
+
*/
|
|
12
|
+
export async function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, }) {
|
|
13
|
+
const workerEnv = builder.environments.worker;
|
|
14
|
+
await runDirectivesScan({
|
|
15
|
+
rootConfig: builder.config,
|
|
16
|
+
environment: workerEnv,
|
|
17
|
+
clientFiles,
|
|
18
|
+
serverFiles,
|
|
19
|
+
});
|
|
20
|
+
console.log("Building worker to discover used client components...");
|
|
21
|
+
process.env.RWSDK_BUILD_PASS = "worker";
|
|
22
|
+
await builder.build(workerEnv);
|
|
23
|
+
log("Used client files after worker build & filtering: %O", Array.from(clientFiles));
|
|
24
|
+
console.log("Building SSR...");
|
|
25
|
+
await builder.build(builder.environments.ssr);
|
|
26
|
+
log("Discovered clientEntryPoints: %O", Array.from(clientEntryPoints));
|
|
27
|
+
console.log("Building client...");
|
|
28
|
+
const clientEnv = builder.environments["client"];
|
|
29
|
+
clientEnv.config.build ??= {};
|
|
30
|
+
clientEnv.config.build.rollupOptions ??= {};
|
|
31
|
+
const clientEntryPointsArray = Array.from(clientEntryPoints);
|
|
32
|
+
if (clientEntryPointsArray.length === 0) {
|
|
33
|
+
log("No client entry points discovered, using default: src/client.tsx");
|
|
34
|
+
clientEnv.config.build.rollupOptions.input = ["src/client.tsx"];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
clientEnv.config.build.rollupOptions.input = clientEntryPointsArray;
|
|
38
|
+
}
|
|
39
|
+
await builder.build(clientEnv);
|
|
40
|
+
console.log("Linking worker build...");
|
|
41
|
+
process.env.RWSDK_BUILD_PASS = "linker";
|
|
42
|
+
// Re-configure the worker environment for the linking pass
|
|
43
|
+
const workerConfig = workerEnv.config;
|
|
44
|
+
workerConfig.build.emptyOutDir = false;
|
|
45
|
+
workerConfig.build.rollupOptions.input = {
|
|
46
|
+
worker: resolve(projectRootDir, "dist", "worker", "worker.js"),
|
|
47
|
+
};
|
|
48
|
+
workerConfig.build.rollupOptions.output = {
|
|
49
|
+
entryFileNames: "worker.js",
|
|
50
|
+
};
|
|
51
|
+
await builder.build(workerEnv);
|
|
52
|
+
console.log("Build complete!");
|
|
53
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const externalModules: string[];
|
|
4
|
-
export declare const configPlugin: ({ silent, projectRootDir, clientEntryPathnames, workerEntryPathname, }: {
|
|
2
|
+
export declare const configPlugin: ({ silent, projectRootDir, workerEntryPathname, clientFiles, serverFiles, clientEntryPoints, }: {
|
|
5
3
|
silent: boolean;
|
|
6
4
|
projectRootDir: string;
|
|
7
|
-
clientEntryPathnames: string[];
|
|
8
5
|
workerEntryPathname: string;
|
|
6
|
+
clientFiles: Set<string>;
|
|
7
|
+
serverFiles: Set<string>;
|
|
8
|
+
clientEntryPoints: Set<string>;
|
|
9
9
|
}) => Plugin;
|