rwsdk 1.0.0-beta.0 → 1.0.0-beta.10
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 +29 -6
- package/dist/lib/e2e/index.d.mts +1 -0
- package/dist/lib/e2e/index.mjs +1 -0
- package/dist/lib/e2e/tarball.mjs +25 -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 +3 -0
- package/dist/scripts/smoke-test.mjs +4 -9
- 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
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,6 +35,9 @@ 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 (/^\d/.test(rwsdkVersion)) {
|
|
39
|
+
rwsdkVersion = `v${rwsdkVersion}`;
|
|
40
|
+
}
|
|
38
41
|
const tmpDirPrefix = path.join(os.tmpdir(), `rwsdk-addon-${addonName}-`);
|
|
39
42
|
const tmpDir = await fs.mkdtemp(tmpDirPrefix);
|
|
40
43
|
const downloadUrl = `https://github.com/redwoodjs/sdk/releases/download/${rwsdkVersion}/${addonName}-${rwsdkVersion}.tar.gz`;
|
|
@@ -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,
|
|
@@ -66,12 +68,6 @@ if (fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
|
66
68
|
else if (arg === "--copy-project") {
|
|
67
69
|
options.copyProject = true;
|
|
68
70
|
}
|
|
69
|
-
else if (arg === "--no-sync") {
|
|
70
|
-
syncExplicit = false;
|
|
71
|
-
}
|
|
72
|
-
else if (arg === "--sync") {
|
|
73
|
-
syncExplicit = true;
|
|
74
|
-
}
|
|
75
71
|
else if (arg === "--ci") {
|
|
76
72
|
// Already handled above, just skip
|
|
77
73
|
}
|
|
@@ -99,7 +95,6 @@ Options:
|
|
|
99
95
|
--keep Keep temporary test directory after tests complete
|
|
100
96
|
--no-headless Run browser tests with GUI (not headless)
|
|
101
97
|
--sync Force syncing SDK code to test project
|
|
102
|
-
--no-sync Disable syncing SDK code to test project
|
|
103
98
|
--ci Run in CI mode (keeps temp dirs, sets headless)
|
|
104
99
|
--bail Stop on first test failure
|
|
105
100
|
--copy-project Copy the project to the artifacts directory
|
|
@@ -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 }),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import { compile } from "@mdx-js/mdx";
|
|
3
3
|
import debug from "debug";
|
|
4
|
+
import { glob } from "glob";
|
|
4
5
|
import fsp from "node:fs/promises";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import { INTERMEDIATES_OUTPUT_DIR } from "../lib/constants.mjs";
|
|
@@ -17,6 +18,39 @@ const isObject = (value) => Object.prototype.toString.call(value) === "[object O
|
|
|
17
18
|
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/utils.ts
|
|
18
19
|
const externalRE = /^(https?:)?\/\//;
|
|
19
20
|
const isExternalUrl = (url) => externalRE.test(url);
|
|
21
|
+
async function findDirectiveRoots({ root, readFileWithCache, directiveCheckCache, }) {
|
|
22
|
+
const srcDir = path.resolve(root, "src");
|
|
23
|
+
const files = await glob("**/*.{ts,tsx,js,jsx,mjs,mts,cjs,cts,mdx}", {
|
|
24
|
+
cwd: srcDir,
|
|
25
|
+
absolute: true,
|
|
26
|
+
});
|
|
27
|
+
const directiveFiles = new Set();
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
if (directiveCheckCache.has(file)) {
|
|
30
|
+
if (directiveCheckCache.get(file)) {
|
|
31
|
+
directiveFiles.add(file);
|
|
32
|
+
}
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const content = await readFileWithCache(file);
|
|
37
|
+
const hasClient = hasDirective(content, "use client");
|
|
38
|
+
const hasServer = hasDirective(content, "use server");
|
|
39
|
+
const hasAnyDirective = hasClient || hasServer;
|
|
40
|
+
directiveCheckCache.set(file, hasAnyDirective);
|
|
41
|
+
if (hasAnyDirective) {
|
|
42
|
+
directiveFiles.add(file);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
log("Could not read file during pre-scan, skipping:", file);
|
|
47
|
+
// Cache the failure to avoid re-reading a problematic file
|
|
48
|
+
directiveCheckCache.set(file, false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
log("Pre-scan found directive files:", Array.from(directiveFiles));
|
|
52
|
+
return directiveFiles;
|
|
53
|
+
}
|
|
20
54
|
export async function resolveModuleWithEnvironment({ path, importer, importerEnv, clientResolver, workerResolver, }) {
|
|
21
55
|
const resolver = importerEnv === "client" ? clientResolver : workerResolver;
|
|
22
56
|
return new Promise((resolvePromise) => {
|
|
@@ -56,6 +90,16 @@ export const runDirectivesScan = async ({ rootConfig, environments, clientFiles,
|
|
|
56
90
|
// Set environment variable to indicate scanning is in progress
|
|
57
91
|
process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE = "true";
|
|
58
92
|
try {
|
|
93
|
+
const fileContentCache = new Map();
|
|
94
|
+
const directiveCheckCache = new Map();
|
|
95
|
+
const readFileWithCache = async (path) => {
|
|
96
|
+
if (fileContentCache.has(path)) {
|
|
97
|
+
return fileContentCache.get(path);
|
|
98
|
+
}
|
|
99
|
+
const contents = await fsp.readFile(path, "utf-8");
|
|
100
|
+
fileContentCache.set(path, contents);
|
|
101
|
+
return contents;
|
|
102
|
+
};
|
|
59
103
|
const esbuild = await getViteEsbuild(rootConfig.root);
|
|
60
104
|
const input = initialEntries ?? environments.worker.config.build.rollupOptions?.input;
|
|
61
105
|
let entries;
|
|
@@ -78,19 +122,19 @@ export const runDirectivesScan = async ({ rootConfig, environments, clientFiles,
|
|
|
78
122
|
// Filter out virtual modules since they can't be scanned by esbuild
|
|
79
123
|
const realEntries = entries.filter((entry) => !entry.includes("virtual:"));
|
|
80
124
|
const absoluteEntries = realEntries.map((entry) => path.resolve(rootConfig.root, entry));
|
|
81
|
-
|
|
125
|
+
const applicationDirectiveFiles = await findDirectiveRoots({
|
|
126
|
+
root: rootConfig.root,
|
|
127
|
+
readFileWithCache,
|
|
128
|
+
directiveCheckCache,
|
|
129
|
+
});
|
|
130
|
+
const combinedEntries = new Set([
|
|
131
|
+
...absoluteEntries,
|
|
132
|
+
...applicationDirectiveFiles,
|
|
133
|
+
]);
|
|
134
|
+
log("Starting directives scan with combined entries:", Array.from(combinedEntries));
|
|
82
135
|
const workerResolver = createViteAwareResolver(rootConfig, environments.worker);
|
|
83
136
|
const clientResolver = createViteAwareResolver(rootConfig, environments.client);
|
|
84
137
|
const moduleEnvironments = new Map();
|
|
85
|
-
const fileContentCache = new Map();
|
|
86
|
-
const readFileWithCache = async (path) => {
|
|
87
|
-
if (fileContentCache.has(path)) {
|
|
88
|
-
return fileContentCache.get(path);
|
|
89
|
-
}
|
|
90
|
-
const contents = await fsp.readFile(path, "utf-8");
|
|
91
|
-
fileContentCache.set(path, contents);
|
|
92
|
-
return contents;
|
|
93
|
-
};
|
|
94
138
|
const esbuildScanPlugin = {
|
|
95
139
|
name: "rwsdk:esbuild-scan-plugin",
|
|
96
140
|
setup(build) {
|
|
@@ -232,7 +276,7 @@ export const runDirectivesScan = async ({ rootConfig, environments, clientFiles,
|
|
|
232
276
|
},
|
|
233
277
|
};
|
|
234
278
|
await esbuild.build({
|
|
235
|
-
entryPoints:
|
|
279
|
+
entryPoints: Array.from(combinedEntries),
|
|
236
280
|
bundle: true,
|
|
237
281
|
write: false,
|
|
238
282
|
outdir: path.join(INTERMEDIATES_OUTPUT_DIR, "directive-scan"),
|
|
@@ -254,7 +298,8 @@ export const runDirectivesScan = async ({ rootConfig, environments, clientFiles,
|
|
|
254
298
|
}
|
|
255
299
|
};
|
|
256
300
|
const deferredLog = (message) => {
|
|
301
|
+
const doLog = process.env.RWSDK_WORKER_RUN ? log : console.log;
|
|
257
302
|
setTimeout(() => {
|
|
258
|
-
|
|
303
|
+
doLog(message);
|
|
259
304
|
}, 500);
|
|
260
305
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rwsdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "v1.0.0-beta.10",
|
|
4
4
|
"description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -145,11 +145,13 @@
|
|
|
145
145
|
"@vitejs/plugin-react": "~5.0.0",
|
|
146
146
|
"chokidar": "~4.0.0",
|
|
147
147
|
"debug": "~4.4.0",
|
|
148
|
+
"decompress": "~4.2.1",
|
|
148
149
|
"enhanced-resolve": "~5.18.1",
|
|
149
150
|
"eventsource-parser": "~3.0.0",
|
|
150
151
|
"execa": "~9.6.0",
|
|
151
152
|
"find-up": "~8.0.0",
|
|
152
153
|
"fs-extra": "~11.3.0",
|
|
154
|
+
"get-port": "^7.1.0",
|
|
153
155
|
"glob": "~11.0.1",
|
|
154
156
|
"ignore": "~7.0.4",
|
|
155
157
|
"jsonc-parser": "~3.3.1",
|
|
@@ -167,13 +169,13 @@
|
|
|
167
169
|
"unique-names-generator": "~4.7.1",
|
|
168
170
|
"vibe-rules": "~0.3.0",
|
|
169
171
|
"vite-tsconfig-paths": "~5.1.4",
|
|
170
|
-
"
|
|
172
|
+
"@types/glob": "^8.1.0"
|
|
171
173
|
},
|
|
172
174
|
"peerDependencies": {
|
|
173
|
-
"@cloudflare/vite-plugin": "^1.
|
|
174
|
-
"react": ">=19.
|
|
175
|
-
"react-dom": ">=19.
|
|
176
|
-
"react-server-dom-webpack": ">=19.
|
|
175
|
+
"@cloudflare/vite-plugin": "^1.13.10",
|
|
176
|
+
"react": ">=19.3.0-canary-4fdf7cf2-20251003 <20.0.0",
|
|
177
|
+
"react-dom": ">=19.3.0-canary-4fdf7cf2-20251003 <20.0.0",
|
|
178
|
+
"react-server-dom-webpack": ">=19.3.0-canary-4fdf7cf2-20251003 <20.0.0",
|
|
177
179
|
"vite": "^6.2.6 || 7.x",
|
|
178
180
|
"wrangler": "^4.35.0"
|
|
179
181
|
},
|
|
@@ -189,7 +191,7 @@
|
|
|
189
191
|
"semver": "~7.7.1",
|
|
190
192
|
"tsx": "~4.20.0",
|
|
191
193
|
"typescript": "~5.9.0",
|
|
192
|
-
"vite": "7.1.
|
|
194
|
+
"vite": "~7.1.9",
|
|
193
195
|
"vitest": "~3.2.0"
|
|
194
196
|
}
|
|
195
197
|
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import debug from "debug";
|
|
2
|
-
const log = debug("rwsdk:vite:manifest-plugin");
|
|
3
|
-
const virtualModuleId = "virtual:rwsdk:manifest.js";
|
|
4
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
5
|
-
export const manifestPlugin = ({ projectRootDir, }) => {
|
|
6
|
-
let isBuild = false;
|
|
7
|
-
return {
|
|
8
|
-
name: "rwsdk:vite:manifest-plugin",
|
|
9
|
-
enforce: "pre",
|
|
10
|
-
configResolved(config) {
|
|
11
|
-
isBuild = config.command === "build";
|
|
12
|
-
},
|
|
13
|
-
resolveId(id) {
|
|
14
|
-
// Skip during directive scanning to avoid performance issues
|
|
15
|
-
if (process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (id === virtualModuleId) {
|
|
19
|
-
return resolvedVirtualModuleId;
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
async load(id) {
|
|
23
|
-
// Skip during directive scanning to avoid performance issues
|
|
24
|
-
if (process.env.RWSDK_DIRECTIVE_SCAN_ACTIVE) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (id === resolvedVirtualModuleId) {
|
|
28
|
-
if (isBuild) {
|
|
29
|
-
// context(justinvdm, 28 Aug 2025): During the build, we don't have
|
|
30
|
-
// the manifest yet. We insert a placeholder that the linker plugin
|
|
31
|
-
// will replace in the final phase.
|
|
32
|
-
log("Returning manifest placeholder for build");
|
|
33
|
-
return `export default "__RWSDK_MANIFEST_PLACEHOLDER__"`;
|
|
34
|
-
}
|
|
35
|
-
// In dev, we can return an empty object.
|
|
36
|
-
log("Not a build, returning empty manifest");
|
|
37
|
-
return `export default {}`;
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
configEnvironment(name, config) {
|
|
41
|
-
if (name !== "worker" && name !== "ssr") {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
log("Configuring environment: name=%s", name);
|
|
45
|
-
config.optimizeDeps ??= {};
|
|
46
|
-
config.optimizeDeps.esbuildOptions ??= {};
|
|
47
|
-
config.optimizeDeps.esbuildOptions.plugins ??= [];
|
|
48
|
-
config.optimizeDeps.esbuildOptions.plugins.push({
|
|
49
|
-
name: "rwsdk:manifest:esbuild",
|
|
50
|
-
setup(build) {
|
|
51
|
-
log("Setting up esbuild plugin for environment: %s", name);
|
|
52
|
-
build.onResolve({ filter: /^virtual:rwsdk:manifest\.js$/ }, () => {
|
|
53
|
-
log("Resolving virtual manifest module in esbuild");
|
|
54
|
-
return {
|
|
55
|
-
path: "virtual:rwsdk:manifest.js",
|
|
56
|
-
external: true,
|
|
57
|
-
};
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
};
|
|
File without changes
|