rwsdk 1.0.0-alpha.2 → 1.0.0-alpha.20
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/browser.d.mts +10 -0
- package/dist/lib/e2e/browser.mjs +124 -0
- package/dist/lib/e2e/dev.d.mts +8 -0
- package/dist/lib/e2e/dev.mjs +242 -0
- package/dist/lib/e2e/environment.d.mts +14 -0
- package/dist/lib/e2e/environment.mjs +266 -0
- package/dist/lib/e2e/index.d.mts +8 -0
- package/dist/lib/e2e/index.mjs +8 -0
- package/dist/lib/e2e/poll.d.mts +8 -0
- package/dist/lib/e2e/poll.mjs +31 -0
- package/dist/lib/e2e/release.d.mts +56 -0
- package/dist/lib/e2e/release.mjs +559 -0
- package/dist/lib/e2e/retry.d.mts +4 -0
- package/dist/lib/e2e/retry.mjs +16 -0
- package/dist/lib/e2e/setup.d.mts +2 -0
- package/dist/lib/e2e/setup.mjs +1 -0
- package/dist/lib/e2e/tarball.d.mts +14 -0
- package/dist/lib/e2e/tarball.mjs +99 -0
- package/dist/lib/e2e/testHarness.d.mts +132 -0
- package/dist/lib/e2e/testHarness.mjs +437 -0
- package/dist/lib/e2e/types.d.mts +32 -0
- package/dist/lib/getShortName.mjs +6 -1
- package/dist/lib/getShortName.test.d.mts +1 -0
- package/dist/lib/getShortName.test.mjs +25 -0
- package/dist/lib/hasPkgScript.d.mts +4 -1
- package/dist/lib/hasPkgScript.mjs +9 -6
- package/dist/lib/hasPkgScript.test.d.mts +1 -0
- package/dist/lib/hasPkgScript.test.mjs +33 -0
- package/dist/lib/jsonUtils.mjs +3 -0
- package/dist/lib/jsonUtils.test.d.mts +1 -0
- package/dist/lib/jsonUtils.test.mjs +90 -0
- package/dist/lib/normalizeModulePath.d.mts +5 -0
- package/dist/lib/normalizeModulePath.mjs +1 -1
- package/dist/lib/normalizeModulePath.test.d.mts +1 -0
- package/dist/lib/{normalizeModulePath.test.js → normalizeModulePath.test.mjs} +20 -1
- package/dist/lib/smokeTests/browser.mjs +3 -94
- package/dist/lib/smokeTests/development.mjs +2 -223
- package/dist/lib/smokeTests/environment.d.mts +4 -11
- package/dist/lib/smokeTests/environment.mjs +10 -158
- package/dist/lib/smokeTests/release.d.mts +2 -49
- package/dist/lib/smokeTests/release.mjs +3 -503
- package/dist/llms/rules/middleware.d.ts +1 -1
- package/dist/llms/rules/middleware.js +4 -4
- package/dist/runtime/entries/worker.d.ts +0 -1
- package/dist/runtime/entries/worker.js +0 -1
- package/dist/runtime/lib/auth/session.d.ts +2 -2
- package/dist/runtime/lib/auth/session.js +4 -4
- package/dist/runtime/lib/memoizeOnId.test.d.ts +1 -0
- package/dist/runtime/lib/memoizeOnId.test.js +49 -0
- package/dist/runtime/lib/realtime/protocol.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/protocol.test.js +107 -0
- package/dist/runtime/lib/realtime/shared.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/shared.test.js +18 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.js +66 -0
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.js +40 -22
- package/dist/runtime/lib/router.test.js +590 -2
- package/dist/runtime/lib/rwContext.d.ts +22 -0
- package/dist/runtime/lib/rwContext.js +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +18 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +143 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +2 -1
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +6 -6
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.d.ts +1 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.js +49 -0
- package/dist/runtime/register/worker.d.ts +1 -1
- package/dist/runtime/register/worker.js +33 -21
- package/dist/runtime/render/assembleDocument.d.ts +6 -0
- package/dist/runtime/render/assembleDocument.js +22 -0
- package/dist/runtime/render/createThenableFromReadableStream.d.ts +1 -0
- package/dist/runtime/render/createThenableFromReadableStream.js +9 -0
- package/dist/runtime/render/normalizeActionResult.d.ts +1 -0
- package/dist/runtime/render/normalizeActionResult.js +43 -0
- package/dist/runtime/render/preloads.d.ts +2 -2
- package/dist/runtime/render/preloads.js +2 -3
- package/dist/runtime/render/{renderRscThenableToHtmlStream.d.ts → renderDocumentHtmlStream.d.ts} +3 -3
- package/dist/runtime/render/renderDocumentHtmlStream.js +39 -0
- package/dist/runtime/render/renderHtmlStream.d.ts +7 -0
- package/dist/runtime/render/renderHtmlStream.js +31 -0
- package/dist/runtime/render/renderToRscStream.d.ts +5 -3
- package/dist/runtime/render/renderToRscStream.js +12 -41
- package/dist/runtime/render/renderToStream.d.ts +2 -1
- package/dist/runtime/render/renderToStream.js +15 -8
- package/dist/runtime/render/stylesheets.d.ts +2 -2
- package/dist/runtime/render/stylesheets.js +2 -3
- package/dist/runtime/requestInfo/types.d.ts +0 -2
- package/dist/runtime/requestInfo/worker.js +1 -9
- package/dist/runtime/ssrBridge.d.ts +2 -1
- package/dist/runtime/ssrBridge.js +2 -1
- package/dist/runtime/worker.d.ts +1 -0
- package/dist/runtime/worker.js +11 -14
- package/dist/scripts/debug-sync.mjs +102 -133
- package/dist/vite/buildApp.d.mts +2 -1
- package/dist/vite/buildApp.mjs +9 -5
- package/dist/vite/checkIsUsingPrisma.d.mts +4 -0
- package/dist/vite/checkIsUsingPrisma.mjs +2 -2
- package/dist/vite/checkIsUsingPrisma.test.d.mts +1 -0
- package/dist/vite/checkIsUsingPrisma.test.mjs +30 -0
- package/dist/vite/configPlugin.mjs +54 -14
- package/dist/vite/createDirectiveLookupPlugin.d.mts +9 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +33 -29
- package/dist/vite/createDirectiveLookupPlugin.test.d.mts +1 -0
- package/dist/vite/createDirectiveLookupPlugin.test.mjs +40 -0
- package/dist/vite/directiveModulesDevPlugin.d.mts +4 -1
- package/dist/vite/directiveModulesDevPlugin.mjs +6 -5
- package/dist/vite/directiveModulesDevPlugin.test.d.mts +1 -0
- package/dist/vite/directiveModulesDevPlugin.test.mjs +59 -0
- package/dist/vite/directivesPlugin.d.mts +1 -0
- package/dist/vite/directivesPlugin.mjs +1 -1
- package/dist/vite/directivesPlugin.test.d.mts +1 -0
- package/dist/vite/directivesPlugin.test.mjs +24 -0
- package/dist/vite/ensureAliasArray.test.d.mts +1 -0
- package/dist/vite/ensureAliasArray.test.mjs +71 -0
- package/dist/vite/findSpecifiers.mjs +2 -1
- package/dist/vite/findSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSpecifiers.test.mjs +202 -0
- package/dist/vite/findSsrSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSsrSpecifiers.test.mjs +99 -0
- package/dist/vite/hasDirective.d.mts +6 -3
- package/dist/vite/hasDirective.mjs +43 -27
- package/dist/vite/hasDirective.test.d.mts +1 -0
- package/dist/vite/hasDirective.test.mjs +107 -0
- package/dist/vite/isJsFile.test.d.mts +1 -0
- package/dist/vite/isJsFile.test.mjs +38 -0
- package/dist/vite/{reactConditionsResolverPlugin.d.mts → knownDepsResolverPlugin.d.mts} +2 -2
- package/dist/vite/{reactConditionsResolverPlugin.mjs → knownDepsResolverPlugin.mjs} +28 -23
- package/dist/vite/linkerPlugin.d.mts +8 -0
- package/dist/vite/linkerPlugin.mjs +30 -22
- package/dist/vite/linkerPlugin.test.d.mts +1 -0
- package/dist/vite/linkerPlugin.test.mjs +41 -0
- package/dist/vite/miniflareHMRPlugin.d.mts +5 -0
- package/dist/vite/miniflareHMRPlugin.mjs +2 -2
- package/dist/vite/miniflareHMRPlugin.test.d.mts +1 -0
- package/dist/vite/miniflareHMRPlugin.test.mjs +42 -0
- package/dist/vite/redwoodPlugin.d.mts +9 -0
- package/dist/vite/redwoodPlugin.mjs +29 -5
- package/dist/vite/redwoodPlugin.test.d.mts +1 -0
- package/dist/vite/redwoodPlugin.test.mjs +34 -0
- package/dist/vite/resolveForcedPaths.d.mts +4 -0
- package/dist/vite/resolveForcedPaths.mjs +9 -0
- package/dist/vite/runDirectivesScan.d.mts +22 -1
- package/dist/vite/runDirectivesScan.mjs +105 -58
- package/dist/vite/runDirectivesScan.test.d.mts +1 -0
- package/dist/vite/runDirectivesScan.test.mjs +73 -0
- package/dist/vite/ssrBridgePlugin.mjs +8 -1
- package/dist/vite/transformClientComponents.mjs +6 -4
- package/dist/vite/transformClientComponents.test.mjs +116 -58
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +1 -1
- package/dist/vite/transformServerFunctions.test.mjs +3 -3
- package/package.json +56 -47
- package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
- package/dist/runtime/imports/resolveSSRValue.js +0 -8
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +0 -54
- package/dist/runtime/render/transformRscToHtmlStream.d.ts +0 -8
- package/dist/runtime/render/transformRscToHtmlStream.js +0 -19
- /package/dist/lib/{normalizeModulePath.test.d.ts → e2e/types.mjs} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { use } from "react";
|
|
3
2
|
import { getManifest } from "../lib/manifest.js";
|
|
4
3
|
const findCssForModule = (scriptId, manifest) => {
|
|
5
4
|
const css = new Set();
|
|
@@ -22,8 +21,8 @@ const findCssForModule = (scriptId, manifest) => {
|
|
|
22
21
|
inner(scriptId);
|
|
23
22
|
return Array.from(css);
|
|
24
23
|
};
|
|
25
|
-
export const Stylesheets = ({ requestInfo }) => {
|
|
26
|
-
const manifest =
|
|
24
|
+
export const Stylesheets = async ({ requestInfo, }) => {
|
|
25
|
+
const manifest = await getManifest();
|
|
27
26
|
const allStylesheets = new Set();
|
|
28
27
|
for (const scriptId of requestInfo.rw.scriptsToBeLoaded) {
|
|
29
28
|
const css = findCssForModule(scriptId, manifest);
|
|
@@ -5,8 +5,6 @@ export interface RequestInfo<Params = any, AppContext = DefaultAppContext> {
|
|
|
5
5
|
request: Request;
|
|
6
6
|
params: Params;
|
|
7
7
|
ctx: AppContext;
|
|
8
|
-
/** @deprecated: Use `response.headers` instead */
|
|
9
|
-
headers: Headers;
|
|
10
8
|
rw: RwContext;
|
|
11
9
|
cf: ExecutionContext;
|
|
12
10
|
response: ResponseInit & {
|
|
@@ -2,15 +2,7 @@ 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 = [
|
|
6
|
-
"request",
|
|
7
|
-
"params",
|
|
8
|
-
"ctx",
|
|
9
|
-
"headers",
|
|
10
|
-
"rw",
|
|
11
|
-
"cf",
|
|
12
|
-
"response",
|
|
13
|
-
];
|
|
5
|
+
const REQUEST_INFO_KEYS = ["request", "params", "ctx", "rw", "cf", "response"];
|
|
14
6
|
REQUEST_INFO_KEYS.forEach((key) => {
|
|
15
7
|
Object.defineProperty(requestInfoBase, key, {
|
|
16
8
|
enumerable: true,
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { renderHtmlStream } from "./render/renderHtmlStream";
|
|
2
|
+
export { createThenableFromReadableStream } from "./render/createThenableFromReadableStream";
|
|
2
3
|
export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
|
|
@@ -7,5 +7,6 @@
|
|
|
7
7
|
// import it through this bridge module, using the bare import path
|
|
8
8
|
// `rwsdk/__ssr_bridge`. We have bundler logic (ssrBridgePlugin) that looks out
|
|
9
9
|
// for imports to it.
|
|
10
|
-
export {
|
|
10
|
+
export { renderHtmlStream } from "./render/renderHtmlStream";
|
|
11
|
+
export { createThenableFromReadableStream } from "./render/createThenableFromReadableStream";
|
|
11
12
|
export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
|
package/dist/runtime/worker.d.ts
CHANGED
package/dist/runtime/worker.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { renderDocumentHtmlStream } from "./render/renderDocumentHtmlStream";
|
|
3
|
+
import { normalizeActionResult } from "./render/normalizeActionResult";
|
|
3
4
|
import { renderToRscStream } from "./render/renderToRscStream";
|
|
4
5
|
import { rscActionHandler } from "./register/worker";
|
|
5
6
|
import { injectRSCPayload } from "rsc-html-stream/server";
|
|
@@ -8,6 +9,7 @@ import { getRequestInfo, runWithRequestInfo, runWithRequestInfoOverrides, } from
|
|
|
8
9
|
import { defineRoutes } from "./lib/router";
|
|
9
10
|
import { generateNonce } from "./lib/utils";
|
|
10
11
|
import { ssrWebpackRequire } from "./imports/worker";
|
|
12
|
+
export * from "./requestInfo/types";
|
|
11
13
|
export const defineApp = (routes) => {
|
|
12
14
|
return {
|
|
13
15
|
fetch: async (request, env, cf) => {
|
|
@@ -34,7 +36,6 @@ export const defineApp = (routes) => {
|
|
|
34
36
|
const isRSCRequest = url.searchParams.has("__rsc") ||
|
|
35
37
|
request.headers.get("accept")?.includes("text/x-component");
|
|
36
38
|
const isAction = url.searchParams.has("__rsc_action_id");
|
|
37
|
-
const userHeaders = new Headers();
|
|
38
39
|
const rw = {
|
|
39
40
|
Document: DefaultDocument,
|
|
40
41
|
nonce: generateNonce(),
|
|
@@ -50,7 +51,6 @@ export const defineApp = (routes) => {
|
|
|
50
51
|
};
|
|
51
52
|
const outerRequestInfo = {
|
|
52
53
|
request,
|
|
53
|
-
headers: userHeaders,
|
|
54
54
|
cf,
|
|
55
55
|
params: {},
|
|
56
56
|
ctx: {},
|
|
@@ -79,12 +79,14 @@ export const defineApp = (routes) => {
|
|
|
79
79
|
status: 500,
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
const actionResult = requestInfo.rw.actionResult;
|
|
82
|
+
const actionResult = normalizeActionResult(requestInfo.rw.actionResult);
|
|
83
83
|
const pageElement = createPageElement(requestInfo, Page);
|
|
84
84
|
const { rscPayload: shouldInjectRSCPayload } = rw;
|
|
85
85
|
let rscPayloadStream = renderToRscStream({
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
input: {
|
|
87
|
+
node: pageElement,
|
|
88
|
+
actionResult,
|
|
89
|
+
},
|
|
88
90
|
onError,
|
|
89
91
|
});
|
|
90
92
|
if (isRSCRequest) {
|
|
@@ -104,11 +106,12 @@ export const defineApp = (routes) => {
|
|
|
104
106
|
nonce: rw.nonce,
|
|
105
107
|
});
|
|
106
108
|
}
|
|
107
|
-
let html = await
|
|
108
|
-
|
|
109
|
+
let html = await renderDocumentHtmlStream({
|
|
110
|
+
rscPayloadStream: rscPayloadStream,
|
|
109
111
|
Document: rw.Document,
|
|
110
112
|
requestInfo: requestInfo,
|
|
111
113
|
onError,
|
|
114
|
+
shouldSSR: rw.ssr,
|
|
112
115
|
});
|
|
113
116
|
if (injectRSCPayloadStream) {
|
|
114
117
|
html = html.pipeThrough(injectRSCPayloadStream);
|
|
@@ -139,12 +142,6 @@ export const defineApp = (routes) => {
|
|
|
139
142
|
// context(justinvdm, 18 Mar 2025): In some cases, such as a .fetch() call to a durable object instance, or Response.redirect(),
|
|
140
143
|
// we need to return a mutable response object.
|
|
141
144
|
const mutableResponse = new Response(response.body, response);
|
|
142
|
-
// Merge user headers from the legacy headers object
|
|
143
|
-
for (const [key, value] of userHeaders.entries()) {
|
|
144
|
-
if (!response.headers.has(key)) {
|
|
145
|
-
mutableResponse.headers.set(key, value);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
145
|
// Merge headers from user response init (these take precedence)
|
|
149
146
|
if (userResponseInit.headers) {
|
|
150
147
|
const userResponseHeaders = new Headers(userResponseInit.headers);
|
|
@@ -6,27 +6,6 @@ import { existsSync } from "node:fs";
|
|
|
6
6
|
import chokidar from "chokidar";
|
|
7
7
|
import { lock } from "proper-lockfile";
|
|
8
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const getPackageManagerInfo = (targetDir) => {
|
|
10
|
-
if (existsSync(path.join(targetDir, "bun.lock"))) {
|
|
11
|
-
return { name: "bun", lockFile: "bun.lock", command: "add" };
|
|
12
|
-
}
|
|
13
|
-
const pnpmResult = {
|
|
14
|
-
name: "pnpm",
|
|
15
|
-
lockFile: "pnpm-lock.yaml",
|
|
16
|
-
command: "add",
|
|
17
|
-
};
|
|
18
|
-
if (existsSync(path.join(targetDir, "yarn.lock"))) {
|
|
19
|
-
return { name: "yarn", lockFile: "yarn.lock", command: "add" };
|
|
20
|
-
}
|
|
21
|
-
if (existsSync(path.join(targetDir, "pnpm-lock.yaml")) ||
|
|
22
|
-
existsSync(path.join(targetDir, "node_modules", ".pnpm"))) {
|
|
23
|
-
return pnpmResult;
|
|
24
|
-
}
|
|
25
|
-
if (existsSync(path.join(targetDir, "package-lock.json"))) {
|
|
26
|
-
return { name: "npm", lockFile: "package-lock.json", command: "install" };
|
|
27
|
-
}
|
|
28
|
-
return pnpmResult;
|
|
29
|
-
};
|
|
30
9
|
const cleanupViteEntries = async (targetDir) => {
|
|
31
10
|
const nodeModulesDir = path.join(targetDir, "node_modules");
|
|
32
11
|
if (!existsSync(nodeModulesDir)) {
|
|
@@ -58,91 +37,6 @@ const cleanupViteEntries = async (targetDir) => {
|
|
|
58
37
|
console.log(`Failed to cleanup vite cache entries: ${error}`);
|
|
59
38
|
}
|
|
60
39
|
};
|
|
61
|
-
const performFullSync = async (sdkDir, targetDir) => {
|
|
62
|
-
let tarballPath = "";
|
|
63
|
-
let tarballName = "";
|
|
64
|
-
// Clean up vite cache
|
|
65
|
-
await cleanupViteEntries(targetDir);
|
|
66
|
-
try {
|
|
67
|
-
console.log("📦 Packing SDK...");
|
|
68
|
-
const packResult = await $({ cwd: sdkDir }) `npm pack --json`;
|
|
69
|
-
const json = JSON.parse(packResult.stdout || "[]");
|
|
70
|
-
const packInfo = Array.isArray(json) ? json[0] : undefined;
|
|
71
|
-
tarballName = (packInfo && (packInfo.filename || packInfo.name)) || "";
|
|
72
|
-
if (!tarballName) {
|
|
73
|
-
console.error("❌ Failed to get tarball name from npm pack.");
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
tarballPath = path.resolve(sdkDir, tarballName);
|
|
77
|
-
console.log(`💿 Installing ${tarballName} in ${targetDir}...`);
|
|
78
|
-
const pm = getPackageManagerInfo(targetDir);
|
|
79
|
-
const packageJsonPath = path.join(targetDir, "package.json");
|
|
80
|
-
const lockfilePath = path.join(targetDir, pm.lockFile);
|
|
81
|
-
const originalPackageJson = await fs
|
|
82
|
-
.readFile(packageJsonPath, "utf-8")
|
|
83
|
-
.catch(() => null);
|
|
84
|
-
const originalLockfile = await fs
|
|
85
|
-
.readFile(lockfilePath, "utf-8")
|
|
86
|
-
.catch(() => null);
|
|
87
|
-
try {
|
|
88
|
-
// For bun, we need to remove the existing dependency from package.json
|
|
89
|
-
// before adding the tarball to avoid a dependency loop error.
|
|
90
|
-
if (pm.name === "bun" && originalPackageJson) {
|
|
91
|
-
try {
|
|
92
|
-
const targetPackageJson = JSON.parse(originalPackageJson);
|
|
93
|
-
let modified = false;
|
|
94
|
-
if (targetPackageJson.dependencies?.rwsdk) {
|
|
95
|
-
delete targetPackageJson.dependencies.rwsdk;
|
|
96
|
-
modified = true;
|
|
97
|
-
}
|
|
98
|
-
if (targetPackageJson.devDependencies?.rwsdk) {
|
|
99
|
-
delete targetPackageJson.devDependencies.rwsdk;
|
|
100
|
-
modified = true;
|
|
101
|
-
}
|
|
102
|
-
if (modified) {
|
|
103
|
-
console.log("Temporarily removing rwsdk from target package.json to prevent dependency loop with bun.");
|
|
104
|
-
await fs.writeFile(packageJsonPath, JSON.stringify(targetPackageJson, null, 2));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch (e) {
|
|
108
|
-
console.warn("Could not modify target package.json, proceeding anyway.");
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const cmd = pm.name;
|
|
112
|
-
const args = [pm.command];
|
|
113
|
-
if (pm.name === "yarn") {
|
|
114
|
-
// For modern yarn, disable PnP to avoid resolution issues with local tarballs
|
|
115
|
-
process.env.YARN_NODE_LINKER = "node-modules";
|
|
116
|
-
args.push(`rwsdk@file:${tarballPath}`);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
args.push(tarballPath);
|
|
120
|
-
}
|
|
121
|
-
await $(cmd, args, {
|
|
122
|
-
cwd: targetDir,
|
|
123
|
-
stdio: "inherit",
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
finally {
|
|
127
|
-
if (originalPackageJson) {
|
|
128
|
-
console.log("Restoring package.json...");
|
|
129
|
-
await fs.writeFile(packageJsonPath, originalPackageJson);
|
|
130
|
-
}
|
|
131
|
-
if (originalLockfile) {
|
|
132
|
-
console.log(`Restoring ${pm.lockFile}...`);
|
|
133
|
-
await fs.writeFile(lockfilePath, originalLockfile);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
finally {
|
|
138
|
-
if (tarballPath) {
|
|
139
|
-
console.log("Removing tarball...");
|
|
140
|
-
await fs.unlink(tarballPath).catch(() => {
|
|
141
|
-
// ignore if deletion fails
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
40
|
const syncFilesWithRsyncOrFs = async (sdkDir, destDir, filesEntries) => {
|
|
147
41
|
const sources = filesEntries.map((p) => path.join(sdkDir, p));
|
|
148
42
|
// Always include package.json in sync
|
|
@@ -191,45 +85,120 @@ const syncFilesWithRsyncOrFs = async (sdkDir, destDir, filesEntries) => {
|
|
|
191
85
|
}
|
|
192
86
|
}
|
|
193
87
|
};
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
88
|
+
const findUp = async (names, startDir) => {
|
|
89
|
+
let dir = startDir;
|
|
90
|
+
while (dir !== path.dirname(dir)) {
|
|
91
|
+
for (const name of names) {
|
|
92
|
+
const filePath = path.join(dir, name);
|
|
93
|
+
if (existsSync(filePath)) {
|
|
94
|
+
return dir;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
dir = path.dirname(dir);
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
};
|
|
101
|
+
const getMonorepoRoot = async (startDir) => {
|
|
102
|
+
try {
|
|
103
|
+
// `pnpm root` is the most reliable way to find the workspace root node_modules
|
|
104
|
+
const { stdout } = await $({
|
|
105
|
+
cwd: startDir,
|
|
106
|
+
}) `pnpm root`;
|
|
107
|
+
// pnpm root returns the node_modules path, so we go up one level
|
|
108
|
+
return path.resolve(stdout, "..");
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
console.warn(`Could not determine pnpm root from ${startDir}. Falling back to file search.`);
|
|
112
|
+
const root = await findUp(["pnpm-workspace.yaml"], startDir);
|
|
113
|
+
if (root) {
|
|
114
|
+
return root;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
console.warn("Could not find pnpm monorepo root. Using parent directory of target as fallback.");
|
|
118
|
+
return path.resolve(startDir, "..");
|
|
203
119
|
};
|
|
204
120
|
const areDependenciesEqual = (deps1, deps2) => {
|
|
205
121
|
// Simple string comparison for this use case is sufficient
|
|
206
122
|
return JSON.stringify(deps1 ?? {}) === JSON.stringify(deps2 ?? {});
|
|
207
123
|
};
|
|
124
|
+
const performFullSync = async (sdkDir, targetDir, monorepoRoot) => {
|
|
125
|
+
console.log("📦 Performing full sync with tarball...");
|
|
126
|
+
let tarballPath = "";
|
|
127
|
+
const projectName = path.basename(targetDir);
|
|
128
|
+
const rwsyncDir = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`);
|
|
129
|
+
try {
|
|
130
|
+
// 1. Pack the SDK
|
|
131
|
+
const packResult = await $({ cwd: sdkDir }) `npm pack --json`;
|
|
132
|
+
const json = JSON.parse(packResult.stdout || "[]");
|
|
133
|
+
const packInfo = Array.isArray(json) ? json[0] : undefined;
|
|
134
|
+
const tarballName = (packInfo && (packInfo.filename || packInfo.name)) || "";
|
|
135
|
+
if (!tarballName) {
|
|
136
|
+
throw new Error("Failed to get tarball name from npm pack.");
|
|
137
|
+
}
|
|
138
|
+
tarballPath = path.resolve(sdkDir, tarballName);
|
|
139
|
+
// 2. Prepare isolated install directory
|
|
140
|
+
console.log(`Preparing isolated install directory at ${rwsyncDir}`);
|
|
141
|
+
await fs.rm(rwsyncDir, { recursive: true, force: true });
|
|
142
|
+
await fs.mkdir(rwsyncDir, { recursive: true });
|
|
143
|
+
await fs.writeFile(path.join(rwsyncDir, "package.json"), JSON.stringify({ name: `rwsync-env-${projectName}` }, null, 2));
|
|
144
|
+
// 3. Perform isolated install
|
|
145
|
+
console.log(`Installing ${tarballName} in isolation...`);
|
|
146
|
+
await $("pnpm", ["add", tarballPath], {
|
|
147
|
+
cwd: rwsyncDir,
|
|
148
|
+
stdio: "inherit",
|
|
149
|
+
});
|
|
150
|
+
// 4. Create symlink
|
|
151
|
+
const symlinkSource = path.join(rwsyncDir, "node_modules", "rwsdk");
|
|
152
|
+
const symlinkTarget = path.join(targetDir, "node_modules", "rwsdk");
|
|
153
|
+
console.log(`Symlinking ${symlinkTarget} -> ${symlinkSource}`);
|
|
154
|
+
await fs.rm(symlinkTarget, { recursive: true, force: true });
|
|
155
|
+
await fs.mkdir(path.dirname(symlinkTarget), { recursive: true });
|
|
156
|
+
await fs.symlink(symlinkSource, symlinkTarget, "dir");
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
if (tarballPath) {
|
|
160
|
+
console.log("Removing tarball...");
|
|
161
|
+
await fs.unlink(tarballPath).catch(() => { });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const performFastSync = async (sdkDir, targetDir, monorepoRoot) => {
|
|
166
|
+
console.log("⚡️ Performing fast sync with rsync...");
|
|
167
|
+
const projectName = path.basename(targetDir);
|
|
168
|
+
const rwsyncDir = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`);
|
|
169
|
+
const syncDestDir = path.join(rwsyncDir, "node_modules", "rwsdk");
|
|
170
|
+
// Copy directories/files declared in package.json#files (plus package.json)
|
|
171
|
+
const filesToSync = JSON.parse(await fs.readFile(path.join(sdkDir, "package.json"), "utf-8"))
|
|
172
|
+
.files || [];
|
|
173
|
+
await syncFilesWithRsyncOrFs(sdkDir, syncDestDir, filesToSync);
|
|
174
|
+
};
|
|
208
175
|
const performSync = async (sdkDir, targetDir) => {
|
|
209
176
|
console.log("🏗️ Rebuilding SDK...");
|
|
210
177
|
await $ `pnpm build`;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
178
|
+
// Clean up vite cache in the target project
|
|
179
|
+
await cleanupViteEntries(targetDir);
|
|
180
|
+
const monorepoRoot = await getMonorepoRoot(targetDir);
|
|
181
|
+
const projectName = path.basename(targetDir);
|
|
182
|
+
const installedSdkPackageJsonPath = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`, "node_modules", "rwsdk", "package.json");
|
|
183
|
+
let needsFullSync = false;
|
|
184
|
+
if (!existsSync(installedSdkPackageJsonPath)) {
|
|
185
|
+
console.log("No previous sync found, performing full sync.");
|
|
186
|
+
needsFullSync = true;
|
|
217
187
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
188
|
+
else {
|
|
189
|
+
const sdkPackageJson = JSON.parse(await fs.readFile(path.join(sdkDir, "package.json"), "utf-8"));
|
|
190
|
+
const installedSdkPackageJson = JSON.parse(await fs.readFile(installedSdkPackageJsonPath, "utf-8"));
|
|
191
|
+
if (!areDependenciesEqual(sdkPackageJson.dependencies, installedSdkPackageJson.dependencies) ||
|
|
192
|
+
!areDependenciesEqual(sdkPackageJson.devDependencies, installedSdkPackageJson.devDependencies)) {
|
|
193
|
+
console.log("Dependency changes detected, performing full sync.");
|
|
194
|
+
needsFullSync = true;
|
|
195
|
+
}
|
|
226
196
|
}
|
|
227
|
-
if (
|
|
228
|
-
|
|
229
|
-
await performFullSync(sdkDir, targetDir);
|
|
197
|
+
if (needsFullSync) {
|
|
198
|
+
await performFullSync(sdkDir, targetDir, monorepoRoot);
|
|
230
199
|
}
|
|
231
200
|
else {
|
|
232
|
-
await performFastSync(sdkDir, targetDir);
|
|
201
|
+
await performFastSync(sdkDir, targetDir, monorepoRoot);
|
|
233
202
|
}
|
|
234
203
|
console.log("✅ Done syncing");
|
|
235
204
|
};
|
package/dist/vite/buildApp.d.mts
CHANGED
|
@@ -6,10 +6,11 @@ import type { ViteBuilder } from "vite";
|
|
|
6
6
|
*
|
|
7
7
|
* @see docs/architecture/productionBuildProcess.md
|
|
8
8
|
*/
|
|
9
|
-
export declare function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, }: {
|
|
9
|
+
export declare function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, workerEntryPathname, }: {
|
|
10
10
|
builder: ViteBuilder;
|
|
11
11
|
clientEntryPoints: Set<string>;
|
|
12
12
|
clientFiles: Set<string>;
|
|
13
13
|
serverFiles: Set<string>;
|
|
14
14
|
projectRootDir: string;
|
|
15
|
+
workerEntryPathname: string;
|
|
15
16
|
}): Promise<void>;
|
package/dist/vite/buildApp.mjs
CHANGED
|
@@ -9,13 +9,14 @@ const log = debug("rwsdk:vite:build-app");
|
|
|
9
9
|
*
|
|
10
10
|
* @see docs/architecture/productionBuildProcess.md
|
|
11
11
|
*/
|
|
12
|
-
export async function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, }) {
|
|
12
|
+
export async function buildApp({ builder, clientEntryPoints, clientFiles, serverFiles, projectRootDir, workerEntryPathname, }) {
|
|
13
13
|
const workerEnv = builder.environments.worker;
|
|
14
14
|
await runDirectivesScan({
|
|
15
15
|
rootConfig: builder.config,
|
|
16
16
|
environments: builder.environments,
|
|
17
17
|
clientFiles,
|
|
18
18
|
serverFiles,
|
|
19
|
+
entries: [workerEntryPathname],
|
|
19
20
|
});
|
|
20
21
|
console.log("Building worker to discover used client components...");
|
|
21
22
|
process.env.RWSDK_BUILD_PASS = "worker";
|
|
@@ -42,11 +43,14 @@ export async function buildApp({ builder, clientEntryPoints, clientFiles, server
|
|
|
42
43
|
// Re-configure the worker environment for the linking pass
|
|
43
44
|
const workerConfig = workerEnv.config;
|
|
44
45
|
workerConfig.build.emptyOutDir = false;
|
|
46
|
+
// context(justinvdm, 22 Sep 2025): This is a workaround to satisfy the
|
|
47
|
+
// Cloudflare plugin's expectation of an entry chunk named `index`. The plugin
|
|
48
|
+
// now manages the worker build, so we no longer set rollup options
|
|
49
|
+
// directly. Instead, we re-point the original entry to the intermediate
|
|
50
|
+
// worker bundle from the first pass. This allows the linker pass to re-use
|
|
51
|
+
// the same plugin-driven configuration while bundling the final worker.
|
|
45
52
|
workerConfig.build.rollupOptions.input = {
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
workerConfig.build.rollupOptions.output = {
|
|
49
|
-
entryFileNames: "worker.js",
|
|
53
|
+
index: resolve(projectRootDir, "dist", "worker", "index.js"),
|
|
50
54
|
};
|
|
51
55
|
await builder.build(workerEnv);
|
|
52
56
|
console.log("Build complete!");
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export type PrismaCheckResult = {
|
|
2
2
|
isUsingPrisma: boolean;
|
|
3
3
|
};
|
|
4
|
+
export declare const isUsingPrisma: ({ projectRootDir, resolver, }: {
|
|
5
|
+
projectRootDir: string;
|
|
6
|
+
resolver?: (path: string, request: string) => string | false;
|
|
7
|
+
}) => boolean;
|
|
4
8
|
export declare const checkPrismaStatus: ({ projectRootDir, }: {
|
|
5
9
|
projectRootDir: string;
|
|
6
10
|
}) => PrismaCheckResult;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import enhancedResolve from "enhanced-resolve";
|
|
2
|
-
const isUsingPrisma = ({ projectRootDir }) => {
|
|
2
|
+
export const isUsingPrisma = ({ projectRootDir, resolver = enhancedResolve.sync, }) => {
|
|
3
3
|
try {
|
|
4
|
-
const prismaClientPath =
|
|
4
|
+
const prismaClientPath = resolver(projectRootDir, "@prisma/client");
|
|
5
5
|
if (!prismaClientPath) {
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { isUsingPrisma } from "./checkIsUsingPrisma.mjs";
|
|
3
|
+
describe("isUsingPrisma", () => {
|
|
4
|
+
it("should return true if prisma client is resolved", () => {
|
|
5
|
+
const resolver = () => "/path/to/prisma/client";
|
|
6
|
+
const result = isUsingPrisma({
|
|
7
|
+
projectRootDir: "/test/project",
|
|
8
|
+
resolver: resolver,
|
|
9
|
+
});
|
|
10
|
+
expect(result).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
it("should return false if prisma client is not resolved", () => {
|
|
13
|
+
const resolver = () => false;
|
|
14
|
+
const result = isUsingPrisma({
|
|
15
|
+
projectRootDir: "/test/project",
|
|
16
|
+
resolver: resolver,
|
|
17
|
+
});
|
|
18
|
+
expect(result).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it("should return false if resolver throws", () => {
|
|
21
|
+
const resolver = () => {
|
|
22
|
+
throw new Error("Module not found");
|
|
23
|
+
};
|
|
24
|
+
const result = isUsingPrisma({
|
|
25
|
+
projectRootDir: "/test/project",
|
|
26
|
+
resolver: resolver,
|
|
27
|
+
});
|
|
28
|
+
expect(result).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import path, { resolve } from "node:path";
|
|
2
2
|
import enhancedResolve from "enhanced-resolve";
|
|
3
|
-
import debug from "debug";
|
|
4
3
|
import { INTERMEDIATE_SSR_BRIDGE_PATH } from "../lib/constants.mjs";
|
|
5
4
|
import { buildApp } from "./buildApp.mjs";
|
|
6
5
|
import { externalModules } from "./constants.mjs";
|
|
7
|
-
const log = debug("rwsdk:vite:config");
|
|
8
6
|
export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clientFiles, serverFiles, clientEntryPoints, }) => ({
|
|
9
7
|
name: "rwsdk:config",
|
|
10
|
-
config: async (_) => {
|
|
8
|
+
config: async (_, { command }) => {
|
|
11
9
|
const mode = process.env.NODE_ENV;
|
|
12
10
|
const workerConfig = {
|
|
13
11
|
resolve: {
|
|
@@ -33,7 +31,17 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
33
31
|
},
|
|
34
32
|
optimizeDeps: {
|
|
35
33
|
noDiscovery: false,
|
|
36
|
-
include: [
|
|
34
|
+
include: [
|
|
35
|
+
"rwsdk/__ssr_bridge",
|
|
36
|
+
"rwsdk/auth",
|
|
37
|
+
"rwsdk/constants",
|
|
38
|
+
"rwsdk/db",
|
|
39
|
+
"rwsdk/debug",
|
|
40
|
+
"rwsdk/realtime/durableObject",
|
|
41
|
+
"rwsdk/realtime/worker",
|
|
42
|
+
"rwsdk/router",
|
|
43
|
+
"rwsdk/worker",
|
|
44
|
+
],
|
|
37
45
|
exclude: [],
|
|
38
46
|
entries: [workerEntryPathname],
|
|
39
47
|
esbuildOptions: {
|
|
@@ -49,14 +57,6 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
49
57
|
emitAssets: true,
|
|
50
58
|
emptyOutDir: false,
|
|
51
59
|
ssr: true,
|
|
52
|
-
rollupOptions: {
|
|
53
|
-
output: {
|
|
54
|
-
inlineDynamicImports: true,
|
|
55
|
-
},
|
|
56
|
-
input: {
|
|
57
|
-
worker: workerEntryPathname,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
62
|
const baseConfig = {
|
|
@@ -88,7 +88,13 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
88
88
|
},
|
|
89
89
|
optimizeDeps: {
|
|
90
90
|
noDiscovery: false,
|
|
91
|
-
include: [
|
|
91
|
+
include: [
|
|
92
|
+
"rwsdk/client",
|
|
93
|
+
"rwsdk/constants",
|
|
94
|
+
"rwsdk/debug",
|
|
95
|
+
"rwsdk/realtime/client",
|
|
96
|
+
"rwsdk/turnstile",
|
|
97
|
+
],
|
|
92
98
|
entries: [],
|
|
93
99
|
esbuildOptions: {
|
|
94
100
|
jsx: "automatic",
|
|
@@ -115,7 +121,18 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
115
121
|
noDiscovery: false,
|
|
116
122
|
entries: [workerEntryPathname],
|
|
117
123
|
exclude: externalModules,
|
|
118
|
-
include: [
|
|
124
|
+
include: [
|
|
125
|
+
"rwsdk/__ssr",
|
|
126
|
+
"rwsdk/__ssr_bridge",
|
|
127
|
+
"rwsdk/client",
|
|
128
|
+
"rwsdk/constants",
|
|
129
|
+
"rwsdk/debug",
|
|
130
|
+
"rwsdk/realtime/client",
|
|
131
|
+
"rwsdk/router",
|
|
132
|
+
"rwsdk/worker",
|
|
133
|
+
"rwsdk/realtime/durableObject",
|
|
134
|
+
"rwsdk/realtime/worker",
|
|
135
|
+
],
|
|
119
136
|
esbuildOptions: {
|
|
120
137
|
jsx: "automatic",
|
|
121
138
|
jsxImportSource: "react",
|
|
@@ -136,8 +153,30 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
136
153
|
outDir: path.dirname(INTERMEDIATE_SSR_BRIDGE_PATH),
|
|
137
154
|
rollupOptions: {
|
|
138
155
|
output: {
|
|
156
|
+
// context(justinvdm, 15 Sep 2025): The SSR bundle is a
|
|
157
|
+
// pre-compiled artifact. When the linker pass bundles it into
|
|
158
|
+
// the intermediate worker bundle (another pre-compiled
|
|
159
|
+
// artifact), Rollup merges their top-level scopes. Since both
|
|
160
|
+
// may have identical minified identifiers (e.g., `l0`), this
|
|
161
|
+
// causes a redeclaration error. To solve this, we wrap the SSR
|
|
162
|
+
// bundle in an exporting IIFE. This creates a scope boundary,
|
|
163
|
+
// preventing symbol collisions while producing a valid,
|
|
164
|
+
// tree-shakeable ES module. The inline plugin below removes the
|
|
165
|
+
// original `export` statement from the bundle to prevent syntax
|
|
166
|
+
// errors.
|
|
139
167
|
inlineDynamicImports: true,
|
|
168
|
+
banner: `export const { renderHtmlStream, ssrLoadModule, ssrWebpackRequire, ssrGetModuleExport, createThenableFromReadableStream } = (function() {`,
|
|
169
|
+
footer: `return { renderHtmlStream, ssrLoadModule, ssrWebpackRequire, ssrGetModuleExport, createThenableFromReadableStream };\n})();`,
|
|
140
170
|
},
|
|
171
|
+
plugins: [
|
|
172
|
+
{
|
|
173
|
+
name: "rwsdk:ssr-bridge-exports",
|
|
174
|
+
renderChunk(code) {
|
|
175
|
+
// Remove the original export statement as it's now handled by the banner/footer
|
|
176
|
+
return code.replace(/export\s*{[^}]+};?/, "");
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
],
|
|
141
180
|
},
|
|
142
181
|
},
|
|
143
182
|
},
|
|
@@ -154,6 +193,7 @@ export const configPlugin = ({ silent, projectRootDir, workerEntryPathname, clie
|
|
|
154
193
|
clientEntryPoints,
|
|
155
194
|
clientFiles,
|
|
156
195
|
serverFiles,
|
|
196
|
+
workerEntryPathname,
|
|
157
197
|
});
|
|
158
198
|
},
|
|
159
199
|
},
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
|
+
export declare function generateLookupMap({ files, isDev, kind, exportName, }: {
|
|
3
|
+
files: Set<string>;
|
|
4
|
+
isDev: boolean;
|
|
5
|
+
kind: "client" | "server";
|
|
6
|
+
exportName: string;
|
|
7
|
+
}): {
|
|
8
|
+
code: string;
|
|
9
|
+
map: import("magic-string").SourceMap;
|
|
10
|
+
};
|
|
2
11
|
interface DirectiveLookupConfig {
|
|
3
12
|
kind: "client" | "server";
|
|
4
13
|
directive: "use client" | "use server";
|