rwsdk 1.0.0-beta.1 → 1.0.0-beta.11
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/e2e/constants.d.mts +13 -0
- package/dist/lib/e2e/constants.mjs +67 -0
- package/dist/lib/e2e/environment.d.mts +1 -1
- package/dist/lib/e2e/environment.mjs +16 -6
- package/dist/lib/e2e/index.d.mts +1 -0
- package/dist/lib/e2e/index.mjs +1 -0
- package/dist/lib/e2e/testHarness.d.mts +33 -3
- package/dist/lib/e2e/testHarness.mjs +181 -109
- package/dist/runtime/client/client.d.ts +1 -0
- package/dist/runtime/client/client.js +2 -0
- package/dist/runtime/client/navigation.d.ts +8 -0
- package/dist/runtime/client/navigation.js +39 -31
- package/dist/runtime/entries/clientSSR.d.ts +1 -0
- package/dist/runtime/entries/clientSSR.js +3 -0
- package/dist/runtime/lib/db/createDb.d.ts +1 -2
- package/dist/runtime/lib/db/createDb.js +4 -0
- package/dist/runtime/lib/manifest.d.ts +1 -1
- package/dist/runtime/lib/manifest.js +7 -4
- package/dist/runtime/lib/realtime/client.js +8 -2
- package/dist/runtime/lib/router.d.ts +1 -19
- package/dist/runtime/lib/router.test.js +2 -0
- package/dist/runtime/lib/{rwContext.d.ts → types.d.ts} +1 -0
- package/dist/runtime/render/renderDocumentHtmlStream.d.ts +1 -1
- package/dist/runtime/render/renderToStream.d.ts +1 -1
- package/dist/runtime/render/renderToString.d.ts +1 -1
- package/dist/runtime/requestInfo/types.d.ts +1 -1
- package/dist/runtime/script.d.ts +1 -3
- package/dist/runtime/script.js +1 -10
- package/dist/runtime/worker.js +25 -0
- package/dist/scripts/addon.mjs +1 -1
- package/dist/scripts/smoke-test.mjs +4 -2
- package/dist/scripts/worker-run.d.mts +1 -1
- package/dist/scripts/worker-run.mjs +50 -113
- package/dist/vite/buildApp.mjs +2 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +1 -1
- package/dist/vite/linkerPlugin.mjs +1 -1
- package/dist/vite/redwoodPlugin.mjs +0 -4
- package/dist/vite/runDirectivesScan.mjs +57 -12
- package/package.json +9 -7
- package/dist/vite/manifestPlugin.d.mts +0 -4
- package/dist/vite/manifestPlugin.mjs +0 -63
- /package/dist/runtime/lib/{rwContext.js → types.js} +0 -0
|
@@ -4,6 +4,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
// context(justinvdm, 14 Aug 2025): `react-server-dom-webpack` uses this global
|
|
5
5
|
// to load modules, so we need to define it here before importing
|
|
6
6
|
// "react-server-dom-webpack."
|
|
7
|
+
// prettier-ignore
|
|
7
8
|
import "./setWebpackRequire";
|
|
8
9
|
import React from "react";
|
|
9
10
|
import { hydrateRoot } from "react-dom/client";
|
|
@@ -11,6 +12,7 @@ import { createFromFetch, createFromReadableStream, encodeReply, } from "react-s
|
|
|
11
12
|
import { rscStream } from "rsc-html-stream/client";
|
|
12
13
|
export { default as React } from "react";
|
|
13
14
|
export { ClientOnly } from "./ClientOnly.js";
|
|
15
|
+
export { initClientNavigation, navigate } from "./navigation.js";
|
|
14
16
|
export const fetchTransport = (transportContext) => {
|
|
15
17
|
const fetchCallServer = async (id, args) => {
|
|
16
18
|
const url = new URL(window.location.href);
|
|
@@ -4,6 +4,14 @@ export interface ClientNavigationOptions {
|
|
|
4
4
|
scrollBehavior?: "auto" | "smooth" | "instant";
|
|
5
5
|
}
|
|
6
6
|
export declare function validateClickEvent(event: MouseEvent, target: HTMLElement): boolean;
|
|
7
|
+
export interface NavigateOptions {
|
|
8
|
+
history?: "push" | "replace";
|
|
9
|
+
info?: {
|
|
10
|
+
scrollToTop?: boolean;
|
|
11
|
+
scrollBehavior?: "auto" | "smooth" | "instant";
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function navigate(href: string, options?: NavigateOptions): Promise<void>;
|
|
7
15
|
export declare function initClientNavigation(opts?: ClientNavigationOptions): {
|
|
8
16
|
handleResponse: (response: Response) => boolean;
|
|
9
17
|
};
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
function saveScrollPosition(x, y) {
|
|
2
|
-
window.history.replaceState({
|
|
3
|
-
...window.history.state,
|
|
4
|
-
scrollX: x,
|
|
5
|
-
scrollY: y,
|
|
6
|
-
}, "", window.location.href);
|
|
7
|
-
}
|
|
8
1
|
export function validateClickEvent(event, target) {
|
|
9
2
|
// should this only work for left click?
|
|
10
3
|
if (event.button !== 0) {
|
|
@@ -37,19 +30,44 @@ export function validateClickEvent(event, target) {
|
|
|
37
30
|
}
|
|
38
31
|
return true;
|
|
39
32
|
}
|
|
33
|
+
let IS_CLIENT_NAVIGATION = false;
|
|
34
|
+
export async function navigate(href, options = { history: "push" }) {
|
|
35
|
+
if (!IS_CLIENT_NAVIGATION) {
|
|
36
|
+
window.location.href = href;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
saveScrollPosition(window.scrollX, window.scrollY);
|
|
40
|
+
const url = window.location.origin + href;
|
|
41
|
+
if (options.history === "push") {
|
|
42
|
+
window.history.pushState({ path: href }, "", url);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
window.history.replaceState({ path: href }, "", url);
|
|
46
|
+
}
|
|
47
|
+
// @ts-expect-error
|
|
48
|
+
await globalThis.__rsc_callServer();
|
|
49
|
+
const scrollToTop = options.info?.scrollToTop ?? true;
|
|
50
|
+
const scrollBehavior = options.info?.scrollBehavior ?? "instant";
|
|
51
|
+
if (scrollToTop && history.scrollRestoration === "auto") {
|
|
52
|
+
window.scrollTo({
|
|
53
|
+
top: 0,
|
|
54
|
+
left: 0,
|
|
55
|
+
behavior: scrollBehavior,
|
|
56
|
+
});
|
|
57
|
+
saveScrollPosition(0, 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function saveScrollPosition(x, y) {
|
|
61
|
+
window.history.replaceState({
|
|
62
|
+
...window.history.state,
|
|
63
|
+
scrollX: x,
|
|
64
|
+
scrollY: y,
|
|
65
|
+
}, "", window.location.href);
|
|
66
|
+
}
|
|
40
67
|
export function initClientNavigation(opts = {}) {
|
|
41
|
-
|
|
42
|
-
onNavigate: async function onNavigate() {
|
|
43
|
-
// @ts-expect-error
|
|
44
|
-
await globalThis.__rsc_callServer();
|
|
45
|
-
},
|
|
46
|
-
scrollToTop: true,
|
|
47
|
-
scrollBehavior: "instant",
|
|
48
|
-
...opts,
|
|
49
|
-
};
|
|
68
|
+
IS_CLIENT_NAVIGATION = true;
|
|
50
69
|
history.scrollRestoration = "auto";
|
|
51
70
|
document.addEventListener("click", async function handleClickEvent(event) {
|
|
52
|
-
// Prevent default navigation
|
|
53
71
|
if (!validateClickEvent(event, event.target)) {
|
|
54
72
|
return;
|
|
55
73
|
}
|
|
@@ -57,28 +75,18 @@ export function initClientNavigation(opts = {}) {
|
|
|
57
75
|
const el = event.target;
|
|
58
76
|
const a = el.closest("a");
|
|
59
77
|
const href = a?.getAttribute("href");
|
|
60
|
-
|
|
61
|
-
window.history.pushState({ path: href }, "", window.location.origin + href);
|
|
62
|
-
await options.onNavigate();
|
|
63
|
-
if (options.scrollToTop && history.scrollRestoration === "auto") {
|
|
64
|
-
window.scrollTo({
|
|
65
|
-
top: 0,
|
|
66
|
-
left: 0,
|
|
67
|
-
behavior: options.scrollBehavior,
|
|
68
|
-
});
|
|
69
|
-
saveScrollPosition(0, 0);
|
|
70
|
-
}
|
|
71
|
-
history.scrollRestoration = "auto";
|
|
78
|
+
navigate(href);
|
|
72
79
|
}, true);
|
|
73
80
|
window.addEventListener("popstate", async function handlePopState() {
|
|
74
|
-
|
|
75
|
-
await
|
|
81
|
+
// @ts-expect-error
|
|
82
|
+
await globalThis.__rsc_callServer();
|
|
76
83
|
});
|
|
77
84
|
// Return a handleResponse function for use with initClient
|
|
78
85
|
return {
|
|
79
86
|
handleResponse: function handleResponse(response) {
|
|
80
87
|
if (!response.ok) {
|
|
81
88
|
// Redirect to the current page (window.location) to show the error
|
|
89
|
+
// This means the page that produced the error is called twice.
|
|
82
90
|
window.location.href = window.location.href;
|
|
83
91
|
return false;
|
|
84
92
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { Kysely } from "kysely";
|
|
2
|
-
|
|
3
|
-
export declare function createDb<T>(durableObjectBinding: DurableObjectNamespace<SqliteDurableObject>, name?: string): Kysely<T>;
|
|
2
|
+
export declare function createDb<DatabaseType>(durableObjectBinding: DurableObjectNamespace<any>, name?: string): Kysely<DatabaseType>;
|
|
@@ -5,6 +5,10 @@ export function createDb(durableObjectBinding, name = "main") {
|
|
|
5
5
|
dialect: new DOWorkerDialect({
|
|
6
6
|
kyselyExecuteQuery: (...args) => {
|
|
7
7
|
const durableObjectId = durableObjectBinding.idFromName(name);
|
|
8
|
+
// context(justinvdm, 2 Oct 2025): First prize would be a type parameter
|
|
9
|
+
// for the durable object and then use it for `durableObjectBinding`'s
|
|
10
|
+
// type, rather than casting like this. However, that would prevent
|
|
11
|
+
// users from being able to do createDb<InferredDbType> then though.
|
|
8
12
|
const stub = durableObjectBinding.get(durableObjectId);
|
|
9
13
|
stub.initialize();
|
|
10
14
|
return stub.kyselyExecuteQuery(...args);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
let manifest;
|
|
2
|
-
export
|
|
2
|
+
export async function getManifest() {
|
|
3
3
|
if (manifest) {
|
|
4
4
|
return manifest;
|
|
5
5
|
}
|
|
6
6
|
if (import.meta.env.VITE_IS_DEV_SERVER) {
|
|
7
|
+
// In dev, there's no manifest, so we can use an empty object.
|
|
7
8
|
manifest = {};
|
|
8
9
|
}
|
|
9
10
|
else {
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
// context(justinvdm, 2 Oct 2025): In production, the manifest is a
|
|
12
|
+
// placeholder string that will be replaced by the linker plugin with the
|
|
13
|
+
// actual manifest JSON object.
|
|
14
|
+
manifest = "__RWSDK_MANIFEST_PLACEHOLDER__";
|
|
12
15
|
}
|
|
13
16
|
return manifest;
|
|
14
|
-
}
|
|
17
|
+
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// context(justinvdm, 14 Aug 2025): `react-server-dom-webpack` uses this globa ___webpack_require__ global,
|
|
2
|
+
// so we need to import our client entry point (which sets it), before importing
|
|
3
|
+
// prettier-ignore
|
|
2
4
|
import { initClient } from "../../client/client";
|
|
3
|
-
|
|
5
|
+
// prettier-ignore
|
|
6
|
+
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
|
|
7
|
+
// prettier-ignore
|
|
4
8
|
import { MESSAGE_TYPE } from "./shared";
|
|
9
|
+
// prettier-ignore
|
|
10
|
+
import { packMessage, unpackMessage, } from "./protocol";
|
|
5
11
|
const DEFAULT_KEY = "default";
|
|
6
12
|
export const initRealtimeClient = ({ key = DEFAULT_KEY, handleResponse, } = {}) => {
|
|
7
13
|
const transport = realtimeTransport({ key, handleResponse });
|
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
import type { Kysely } from "kysely";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { RequestInfo } from "../requestInfo/types";
|
|
4
|
-
|
|
5
|
-
children: React.ReactNode;
|
|
6
|
-
};
|
|
7
|
-
export type LayoutProps<T extends RequestInfo = RequestInfo> = {
|
|
8
|
-
children?: React.ReactNode;
|
|
9
|
-
requestInfo?: T;
|
|
10
|
-
};
|
|
11
|
-
export type RwContext = {
|
|
12
|
-
nonce: string;
|
|
13
|
-
Document: React.FC<DocumentProps<any>>;
|
|
14
|
-
rscPayload: boolean;
|
|
15
|
-
ssr: boolean;
|
|
16
|
-
layouts?: React.FC<LayoutProps<any>>[];
|
|
17
|
-
databases: Map<string, Kysely<any>>;
|
|
18
|
-
scriptsToBeLoaded: Set<string>;
|
|
19
|
-
pageRouteResolved: PromiseWithResolvers<void> | undefined;
|
|
20
|
-
actionResult?: unknown;
|
|
21
|
-
};
|
|
3
|
+
import type { DocumentProps, LayoutProps } from "./types.js";
|
|
22
4
|
export type RouteMiddleware<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<React.JSX.Element | Response | void>;
|
|
23
5
|
type RouteFunction<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<Response>;
|
|
24
6
|
type MaybePromise<T> = T | Promise<T>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DocumentProps } from "../lib/
|
|
1
|
+
import { type DocumentProps } from "../lib/types.js";
|
|
2
2
|
import { type RequestInfo } from "../requestInfo/types.js";
|
|
3
3
|
export declare const renderDocumentHtmlStream: ({ rscPayloadStream, Document, requestInfo, shouldSSR, onError, }: {
|
|
4
4
|
rscPayloadStream: ReadableStream;
|
package/dist/runtime/script.d.ts
CHANGED
package/dist/runtime/script.js
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
1
|
import { env } from "cloudflare:workers";
|
|
2
|
-
|
|
3
|
-
export const defineScript = (fn) => {
|
|
4
|
-
const app = defineApp([
|
|
5
|
-
async () => {
|
|
6
|
-
await fn({ env: env });
|
|
7
|
-
return new Response("Done!");
|
|
8
|
-
},
|
|
9
|
-
]);
|
|
10
|
-
return app;
|
|
11
|
-
};
|
|
2
|
+
export const defineScript = (fn) => () => fn({ env: env });
|
package/dist/runtime/worker.js
CHANGED
|
@@ -23,6 +23,29 @@ export const defineApp = (routes) => {
|
|
|
23
23
|
url.pathname = url.pathname.slice("/assets/".length);
|
|
24
24
|
return env.ASSETS.fetch(new Request(url.toString(), request));
|
|
25
25
|
}
|
|
26
|
+
else if (import.meta.env.VITE_IS_DEV_SERVER &&
|
|
27
|
+
new URL(request.url).pathname === "/__worker-run") {
|
|
28
|
+
const url = new URL(request.url);
|
|
29
|
+
const scriptPath = url.searchParams.get("script");
|
|
30
|
+
if (!scriptPath) {
|
|
31
|
+
return new Response("Missing 'script' query parameter", {
|
|
32
|
+
status: 400,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const scriptModule = await import(/* @vite-ignore */ scriptPath);
|
|
37
|
+
if (scriptModule.default) {
|
|
38
|
+
await scriptModule.default(request, env, cf);
|
|
39
|
+
}
|
|
40
|
+
return new Response("Script executed successfully");
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
console.error(`Error executing script: ${scriptPath}\n\n${e.stack}`);
|
|
44
|
+
return new Response(`Error executing script: ${e.message}`, {
|
|
45
|
+
status: 500,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
26
49
|
else if (import.meta.env.VITE_IS_DEV_SERVER &&
|
|
27
50
|
request.url.includes("/__vite_preamble__")) {
|
|
28
51
|
return new Response('import RefreshRuntime from "/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window); window.$RefreshReg$ = () => {}; window.$RefreshSig$ = () => (type) => type; window.__vite_plugin_react_preamble_installed__ = true;', {
|
|
@@ -43,6 +66,8 @@ export const defineApp = (routes) => {
|
|
|
43
66
|
ssr: true,
|
|
44
67
|
databases: new Map(),
|
|
45
68
|
scriptsToBeLoaded: new Set(),
|
|
69
|
+
entryScripts: new Set(),
|
|
70
|
+
inlineScripts: new Set(),
|
|
46
71
|
pageRouteResolved: undefined,
|
|
47
72
|
};
|
|
48
73
|
const userResponseInit = {
|
package/dist/scripts/addon.mjs
CHANGED
|
@@ -35,7 +35,7 @@ export const addon = async () => {
|
|
|
35
35
|
console.error('Could not find "rwsdk" in your dependencies or devDependencies.');
|
|
36
36
|
process.exit(1);
|
|
37
37
|
}
|
|
38
|
-
if (
|
|
38
|
+
if (/^\d/.test(rwsdkVersion)) {
|
|
39
39
|
rwsdkVersion = `v${rwsdkVersion}`;
|
|
40
40
|
}
|
|
41
41
|
const tmpDirPrefix = path.join(os.tmpdir(), `rwsdk-addon-${addonName}-`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
-
import { join } from "path";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { runSmokeTests } from "../lib/smokeTests/runSmokeTests.mjs";
|
|
5
5
|
import { isRunningInCI } from "../lib/smokeTests/utils.mjs";
|
|
@@ -16,11 +16,13 @@ if (fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
|
16
16
|
// Check for CI flag first
|
|
17
17
|
const ciFlag = args.includes("--ci");
|
|
18
18
|
// Set initial default values (sync will be determined below)
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const starterPath = join(__dirname, "..", "..", "..", "starter");
|
|
19
21
|
const options = {
|
|
20
22
|
skipDev: false,
|
|
21
23
|
skipRelease: false,
|
|
22
24
|
skipClient: false,
|
|
23
|
-
projectDir:
|
|
25
|
+
projectDir: starterPath,
|
|
24
26
|
artifactDir: join(process.cwd(), ".artifacts"), // Default to .artifacts in current directory
|
|
25
27
|
keep: isRunningInCI(ciFlag), // Default to true in CI environments
|
|
26
28
|
headless: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
|
@@ -1,131 +1,68 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { redwood } from "../vite/index.mjs";
|
|
11
|
-
const debug = baseDebug("rwsdk:worker-run");
|
|
12
|
-
export const runWorkerScript = async (relativeScriptPath) => {
|
|
1
|
+
import dbg from "debug";
|
|
2
|
+
import getPort from "get-port";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import * as vite from "vite";
|
|
5
|
+
import { createLogger } from "vite";
|
|
6
|
+
const debug = dbg("rwsdk:worker-run");
|
|
7
|
+
const main = async () => {
|
|
8
|
+
process.env.RWSDK_WORKER_RUN = "1";
|
|
9
|
+
const relativeScriptPath = process.argv[2];
|
|
13
10
|
if (!relativeScriptPath) {
|
|
14
11
|
console.error("Error: Script path is required");
|
|
15
12
|
console.log("\nUsage:");
|
|
16
|
-
console.log("
|
|
17
|
-
console.log("\nOptions:");
|
|
18
|
-
console.log(" RWSDK_WRANGLER_CONFIG Environment variable for config path");
|
|
13
|
+
console.log(" rwsdk worker-run <script-path>");
|
|
19
14
|
console.log("\nExamples:");
|
|
20
|
-
console.log("
|
|
21
|
-
console.log(" RWSDK_WRANGLER_CONFIG=custom.toml npm run worker:run src/scripts/seed.ts\n");
|
|
15
|
+
console.log(" rwsdk worker-run src/scripts/seed.ts\n");
|
|
22
16
|
process.exit(1);
|
|
23
17
|
}
|
|
24
|
-
const scriptPath = resolve(process.cwd(), relativeScriptPath);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const workerConfig = unstable_readConfig({
|
|
31
|
-
config: workerConfigPath,
|
|
32
|
-
env: "dev",
|
|
33
|
-
});
|
|
34
|
-
const durableObjectsToExport = workerConfig.durable_objects?.bindings
|
|
35
|
-
.filter((binding) => !binding.script_name)
|
|
36
|
-
.map((binding) => binding.class_name) ?? [];
|
|
37
|
-
const workerEntryRelativePath = workerConfig.main;
|
|
38
|
-
const workerEntryPath = workerEntryRelativePath ?? path.join(process.cwd(), "src/worker.tsx");
|
|
39
|
-
const durableObjectExports = [];
|
|
40
|
-
if (durableObjectsToExport.length > 0) {
|
|
41
|
-
const resolver = enhancedResolve.create.sync({
|
|
42
|
-
extensions: [".mts", ".ts", ".tsx", ".mjs", ".js", ".jsx", ".json"],
|
|
43
|
-
});
|
|
44
|
-
const workerEntryContents = await readFile(workerEntryPath, "utf-8");
|
|
45
|
-
const workerEntryAst = parse(Lang.Tsx, workerEntryContents);
|
|
46
|
-
const exportDeclarations = [
|
|
47
|
-
...workerEntryAst.root().findAll('export { $$$EXPORTS } from "$MODULE"'),
|
|
48
|
-
...workerEntryAst.root().findAll("export { $$$EXPORTS } from '$MODULE'"),
|
|
49
|
-
...workerEntryAst.root().findAll("export { $$$EXPORTS } from '$MODULE'"),
|
|
50
|
-
];
|
|
51
|
-
for (const exportDeclaration of exportDeclarations) {
|
|
52
|
-
const moduleMatch = exportDeclaration.getMatch("MODULE");
|
|
53
|
-
const exportsMatch = exportDeclaration.getMultipleMatches("EXPORTS");
|
|
54
|
-
if (!moduleMatch || exportsMatch.length === 0) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
const modulePath = moduleMatch.text();
|
|
58
|
-
const specifiers = exportsMatch.map((m) => m.text().trim());
|
|
59
|
-
for (const specifier of specifiers) {
|
|
60
|
-
if (durableObjectsToExport.includes(specifier)) {
|
|
61
|
-
const resolvedPath = resolver(path.dirname(workerEntryPath), modulePath);
|
|
62
|
-
durableObjectExports.push(`export { ${specifier} } from "${resolvedPath}";`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
18
|
+
const scriptPath = path.resolve(process.cwd(), relativeScriptPath);
|
|
19
|
+
const port = await getPort();
|
|
20
|
+
let server;
|
|
21
|
+
const cleanup = async () => {
|
|
22
|
+
if (server) {
|
|
23
|
+
await server.close();
|
|
65
24
|
}
|
|
66
|
-
|
|
67
|
-
const tmpDir = await tmp.dir({
|
|
68
|
-
prefix: "rw-worker-run-",
|
|
69
|
-
unsafeCleanup: true,
|
|
70
|
-
});
|
|
71
|
-
const relativeTmpWorkerEntryPath = "worker.tsx";
|
|
72
|
-
const tmpWorkerPath = path.join(tmpDir.path, "wrangler.json");
|
|
73
|
-
const tmpWorkerEntryPath = path.join(tmpDir.path, relativeTmpWorkerEntryPath);
|
|
74
|
-
const scriptWorkerConfig = {
|
|
75
|
-
...workerConfig,
|
|
76
|
-
configPath: tmpWorkerPath,
|
|
77
|
-
userConfigPath: tmpWorkerPath,
|
|
78
|
-
main: relativeTmpWorkerEntryPath,
|
|
25
|
+
process.exit();
|
|
79
26
|
};
|
|
27
|
+
process.on("SIGINT", cleanup);
|
|
28
|
+
process.on("SIGTERM", cleanup);
|
|
80
29
|
try {
|
|
81
|
-
await
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
configFile: false,
|
|
91
|
-
plugins: [
|
|
92
|
-
redwood({
|
|
93
|
-
configPath: tmpWorkerPath,
|
|
94
|
-
includeCloudflarePlugin: true,
|
|
95
|
-
entry: {
|
|
96
|
-
worker: tmpWorkerEntryPath,
|
|
97
|
-
},
|
|
98
|
-
}),
|
|
99
|
-
],
|
|
30
|
+
server = await vite.createServer({
|
|
31
|
+
logLevel: "silent",
|
|
32
|
+
build: {
|
|
33
|
+
outDir: ".rwsdk",
|
|
34
|
+
},
|
|
35
|
+
customLogger: createLogger("info", {
|
|
36
|
+
prefix: "[rwsdk]",
|
|
37
|
+
allowClearScreen: true,
|
|
38
|
+
}),
|
|
100
39
|
server: {
|
|
101
|
-
port
|
|
40
|
+
port,
|
|
41
|
+
host: "localhost",
|
|
102
42
|
},
|
|
103
43
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
44
|
+
await server.listen();
|
|
45
|
+
const url = `http://localhost:${port}/__worker-run?script=${scriptPath}`;
|
|
46
|
+
debug("Fetching %s", url);
|
|
47
|
+
const response = await fetch(url);
|
|
48
|
+
debug("Response from worker: %s", response);
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const errorText = await response.text();
|
|
51
|
+
console.error(`Error: worker-run script failed with status ${response.status}.`);
|
|
52
|
+
if (errorText) {
|
|
53
|
+
console.error("Response:", errorText);
|
|
111
54
|
}
|
|
112
|
-
|
|
113
|
-
await fetch(`http://localhost:${address.port}/`);
|
|
114
|
-
debug("Worker fetched successfully");
|
|
115
|
-
}
|
|
116
|
-
finally {
|
|
117
|
-
debug("Closing server...");
|
|
118
|
-
server.close();
|
|
119
|
-
debug("Server closed");
|
|
55
|
+
process.exit(1);
|
|
120
56
|
}
|
|
57
|
+
const responseText = await response.text();
|
|
58
|
+
debug("Response from worker: %s", responseText);
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
console.error("rwsdk: Error running script:\n\n%s", e.message);
|
|
62
|
+
process.exit(1);
|
|
121
63
|
}
|
|
122
64
|
finally {
|
|
123
|
-
|
|
124
|
-
debug("Temporary files cleaned up");
|
|
65
|
+
await cleanup();
|
|
125
66
|
}
|
|
126
|
-
// todo(justinvdm, 01 Apr 2025): Investigate what handles are remaining open
|
|
127
|
-
process.exit(0);
|
|
128
67
|
};
|
|
129
|
-
|
|
130
|
-
runWorkerScript(process.argv[2]);
|
|
131
|
-
}
|
|
68
|
+
main();
|
package/dist/vite/buildApp.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
4
|
import { runDirectivesScan } from "./runDirectivesScan.mjs";
|
|
4
5
|
const log = debug("rwsdk:vite:build-app");
|
|
@@ -10,6 +11,7 @@ const log = debug("rwsdk:vite:build-app");
|
|
|
10
11
|
* @see docs/architecture/productionBuildProcess.md
|
|
11
12
|
*/
|
|
12
13
|
export async function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, workerEntryPathname, }) {
|
|
14
|
+
await rm(resolve(projectRootDir, "dist"), { recursive: true, force: true });
|
|
13
15
|
const workerEnv = builder.environments.worker;
|
|
14
16
|
await runDirectivesScan({
|
|
15
17
|
rootConfig: builder.config,
|
|
@@ -38,7 +38,7 @@ export const directiveModulesDevPlugin = ({ clientFiles, serverFiles, projectRoo
|
|
|
38
38
|
return {
|
|
39
39
|
name: "rwsdk:directive-modules-dev",
|
|
40
40
|
configureServer(server) {
|
|
41
|
-
if (!process.env.VITE_IS_DEV_SERVER
|
|
41
|
+
if (!process.env.VITE_IS_DEV_SERVER) {
|
|
42
42
|
resolveScanPromise();
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
@@ -9,7 +9,7 @@ export function linkWorkerBundle({ code, manifestContent, projectRootDir, }) {
|
|
|
9
9
|
const manifest = JSON.parse(manifestContent);
|
|
10
10
|
// 1. Replace the manifest placeholder with the actual manifest content.
|
|
11
11
|
log("Injecting manifest into worker bundle");
|
|
12
|
-
newCode = newCode.replace('"__RWSDK_MANIFEST_PLACEHOLDER__"
|
|
12
|
+
newCode = newCode.replace(/['"]__RWSDK_MANIFEST_PLACEHOLDER__['"]/, manifestContent);
|
|
13
13
|
// 2. Replace asset placeholders with their final hashed paths.
|
|
14
14
|
log("Replacing asset placeholders in final worker bundle");
|
|
15
15
|
for (const [key, value] of Object.entries(manifest)) {
|
|
@@ -18,7 +18,6 @@ import { directivesPlugin } from "./directivesPlugin.mjs";
|
|
|
18
18
|
import { injectVitePreamble } from "./injectVitePreamblePlugin.mjs";
|
|
19
19
|
import { knownDepsResolverPlugin } from "./knownDepsResolverPlugin.mjs";
|
|
20
20
|
import { linkerPlugin } from "./linkerPlugin.mjs";
|
|
21
|
-
import { manifestPlugin } from "./manifestPlugin.mjs";
|
|
22
21
|
import { miniflareHMRPlugin } from "./miniflareHMRPlugin.mjs";
|
|
23
22
|
import { moveStaticAssetsPlugin } from "./moveStaticAssetsPlugin.mjs";
|
|
24
23
|
import { prismaPlugin } from "./prismaPlugin.mjs";
|
|
@@ -144,9 +143,6 @@ export const redwoodPlugin = async (options = {}) => {
|
|
|
144
143
|
clientEntryPoints,
|
|
145
144
|
projectRootDir,
|
|
146
145
|
}),
|
|
147
|
-
manifestPlugin({
|
|
148
|
-
projectRootDir,
|
|
149
|
-
}),
|
|
150
146
|
moveStaticAssetsPlugin({ rootDir: projectRootDir }),
|
|
151
147
|
prismaPlugin({ projectRootDir }),
|
|
152
148
|
linkerPlugin({ projectRootDir }),
|