rwsdk 1.0.0-beta.9 → 1.0.0-beta.9-test.20251007055438
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/runtime/entries/worker.d.ts +1 -0
- package/dist/runtime/entries/worker.js +1 -0
- package/dist/runtime/lib/requestState.d.ts +7 -0
- package/dist/runtime/lib/requestState.js +39 -0
- package/dist/runtime/requestInfo/types.d.ts +1 -0
- package/dist/runtime/requestInfo/worker.js +9 -1
- package/dist/runtime/worker.js +1 -0
- package/dist/vite/runDirectivesScan.mjs +55 -11
- package/package.json +4 -3
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a request-scoped state variable that automatically resolves to the correct
|
|
3
|
+
* instance based on the current request context using AsyncLocalStorage.
|
|
4
|
+
*
|
|
5
|
+
* @returns A tuple containing [proxy object, setter function]
|
|
6
|
+
*/
|
|
7
|
+
export declare function defineRequestState<T>(): [T, (value: T) => void];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { requestInfo } from "../requestInfo/worker.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a request-scoped state variable that automatically resolves to the correct
|
|
4
|
+
* instance based on the current request context using AsyncLocalStorage.
|
|
5
|
+
*
|
|
6
|
+
* @returns A tuple containing [proxy object, setter function]
|
|
7
|
+
*/
|
|
8
|
+
export function defineRequestState() {
|
|
9
|
+
// Generate a unique key for this state variable to prevent collisions
|
|
10
|
+
const key = `__requestState_${crypto.randomUUID()}`;
|
|
11
|
+
const setter = (value) => {
|
|
12
|
+
requestInfo.__userContext[key] = value;
|
|
13
|
+
};
|
|
14
|
+
// Create a proxy that delegates all property access to the stored instance
|
|
15
|
+
const proxy = new Proxy({}, {
|
|
16
|
+
get(target, prop, receiver) {
|
|
17
|
+
const userContext = requestInfo.__userContext;
|
|
18
|
+
const instance = userContext?.[key];
|
|
19
|
+
if (!instance) {
|
|
20
|
+
throw new Error(`Request-scoped state not initialized. Make sure to call setter before accessing properties.`);
|
|
21
|
+
}
|
|
22
|
+
const value = instance[prop];
|
|
23
|
+
if (typeof value === "function") {
|
|
24
|
+
return value.bind(instance);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
},
|
|
28
|
+
set(target, prop, value) {
|
|
29
|
+
const userContext = requestInfo.__userContext;
|
|
30
|
+
const instance = userContext?.[key];
|
|
31
|
+
if (!instance) {
|
|
32
|
+
throw new Error(`Request-scoped state not initialized. Make sure to call setter before setting properties.`);
|
|
33
|
+
}
|
|
34
|
+
instance[prop] = value;
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
return [proxy, setter];
|
|
39
|
+
}
|
|
@@ -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
|
+
"rw",
|
|
10
|
+
"cf",
|
|
11
|
+
"response",
|
|
12
|
+
"__userContext",
|
|
13
|
+
];
|
|
6
14
|
REQUEST_INFO_KEYS.forEach((key) => {
|
|
7
15
|
Object.defineProperty(requestInfoBase, key, {
|
|
8
16
|
enumerable: true,
|
package/dist/runtime/worker.js
CHANGED
|
@@ -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"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rwsdk",
|
|
3
|
-
"version": "1.0.0-beta.9",
|
|
3
|
+
"version": "1.0.0-beta.9-test.20251007055438",
|
|
4
4
|
"description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -168,7 +168,8 @@
|
|
|
168
168
|
"ts-morph": "~27.0.0",
|
|
169
169
|
"unique-names-generator": "~4.7.1",
|
|
170
170
|
"vibe-rules": "~0.3.0",
|
|
171
|
-
"vite-tsconfig-paths": "~5.1.4"
|
|
171
|
+
"vite-tsconfig-paths": "~5.1.4",
|
|
172
|
+
"@types/glob": "^8.1.0"
|
|
172
173
|
},
|
|
173
174
|
"peerDependencies": {
|
|
174
175
|
"@cloudflare/vite-plugin": "^1.12.4",
|
|
@@ -190,7 +191,7 @@
|
|
|
190
191
|
"semver": "~7.7.1",
|
|
191
192
|
"tsx": "~4.20.0",
|
|
192
193
|
"typescript": "~5.9.0",
|
|
193
|
-
"vite": "7.1.
|
|
194
|
+
"vite": "~7.1.9",
|
|
194
195
|
"vitest": "~3.2.0"
|
|
195
196
|
}
|
|
196
197
|
}
|