rwsdk 0.1.11 → 0.1.13
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/scripts/debug-sync.mjs +20 -4
- package/dist/vite/directivesPlugin.mjs +0 -2
- package/dist/vite/findSsrSpecifiers.d.mts +11 -0
- package/dist/vite/findSsrSpecifiers.mjs +51 -0
- package/dist/vite/invalidateClientModule.d.mts +2 -0
- package/dist/vite/invalidateClientModule.mjs +8 -0
- package/dist/vite/invalidateModule copy.d.mts +2 -0
- package/dist/vite/invalidateModule copy.mjs +14 -0
- package/dist/vite/invalidateSSRModule.d.mts +2 -0
- package/dist/vite/invalidateSSRModule.mjs +7 -0
- package/dist/vite/miniflareHMRPlugin.mjs +43 -1
- package/dist/vite/ssrBridgePlugin.mjs +16 -8
- package/package.json +1 -1
|
@@ -136,7 +136,15 @@ export const debugSync = async (opts) => {
|
|
|
136
136
|
throw e;
|
|
137
137
|
}
|
|
138
138
|
// Initial sync for watch mode. We do it *after* acquiring the lock.
|
|
139
|
-
|
|
139
|
+
let initialSyncOk = false;
|
|
140
|
+
try {
|
|
141
|
+
await performSync(sdkDir, targetDir);
|
|
142
|
+
initialSyncOk = true;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error("❌ Initial sync failed:", error);
|
|
146
|
+
console.log(" Still watching for changes...");
|
|
147
|
+
}
|
|
140
148
|
const filesToWatch = [
|
|
141
149
|
path.join(sdkDir, "src"),
|
|
142
150
|
path.join(sdkDir, "types"),
|
|
@@ -169,8 +177,14 @@ export const debugSync = async (opts) => {
|
|
|
169
177
|
/* ignore kill errors */
|
|
170
178
|
});
|
|
171
179
|
}
|
|
172
|
-
|
|
173
|
-
|
|
180
|
+
try {
|
|
181
|
+
await performSync(sdkDir, targetDir);
|
|
182
|
+
runWatchedCommand();
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error("❌ Sync failed:", error);
|
|
186
|
+
console.log(" Still watching for changes...");
|
|
187
|
+
}
|
|
174
188
|
});
|
|
175
189
|
const cleanup = async () => {
|
|
176
190
|
console.log("\nCleaning up...");
|
|
@@ -182,7 +196,9 @@ export const debugSync = async (opts) => {
|
|
|
182
196
|
};
|
|
183
197
|
process.on("SIGINT", cleanup);
|
|
184
198
|
process.on("SIGTERM", cleanup);
|
|
185
|
-
|
|
199
|
+
if (initialSyncOk) {
|
|
200
|
+
runWatchedCommand();
|
|
201
|
+
}
|
|
186
202
|
};
|
|
187
203
|
if (import.meta.url === new URL(process.argv[1], import.meta.url).href) {
|
|
188
204
|
const args = process.argv.slice(2);
|
|
@@ -4,7 +4,6 @@ import debug from "debug";
|
|
|
4
4
|
import { transformClientComponents } from "./transformClientComponents.mjs";
|
|
5
5
|
import { transformServerFunctions } from "./transformServerFunctions.mjs";
|
|
6
6
|
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
7
|
-
import { invalidateModule } from "./invalidateModule.mjs";
|
|
8
7
|
const log = debug("rwsdk:vite:rsc-directives-plugin");
|
|
9
8
|
const verboseLog = debug("verbose:rwsdk:vite:rsc-directives-plugin");
|
|
10
9
|
const getLoader = (filePath) => {
|
|
@@ -48,7 +47,6 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
|
|
|
48
47
|
devServer.environments[environment].depsOptimizer?.registerMissingImport(resolvedId, fullPath);
|
|
49
48
|
if (isAfterFirstResponse && !hadFile) {
|
|
50
49
|
log("Invalidating cache for lookup module %s after adding module id=%s", lookupModule, id);
|
|
51
|
-
invalidateModule(devServer, environment, `virtual:use-${kind}-lookup`);
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds __vite_ssr_import__ and __vite_ssr_dynamic_import__ specifiers in the code.
|
|
3
|
+
* @param id The file identifier for language detection.
|
|
4
|
+
* @param code The code to search for SSR imports.
|
|
5
|
+
* @param log Optional logger function for debug output.
|
|
6
|
+
* @returns Object with arrays of static and dynamic import specifiers.
|
|
7
|
+
*/
|
|
8
|
+
export declare function findSsrImportSpecifiers(id: string, code: string, log?: (...args: any[]) => void): {
|
|
9
|
+
imports: string[];
|
|
10
|
+
dynamicImports: string[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { parse as sgParse, Lang as SgLang, Lang } from "@ast-grep/napi";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Finds __vite_ssr_import__ and __vite_ssr_dynamic_import__ specifiers in the code.
|
|
5
|
+
* @param id The file identifier for language detection.
|
|
6
|
+
* @param code The code to search for SSR imports.
|
|
7
|
+
* @param log Optional logger function for debug output.
|
|
8
|
+
* @returns Object with arrays of static and dynamic import specifiers.
|
|
9
|
+
*/
|
|
10
|
+
export function findSsrImportSpecifiers(id, code, log) {
|
|
11
|
+
const ext = path.extname(id).toLowerCase();
|
|
12
|
+
const lang = ext === ".tsx" || ext === ".jsx" ? Lang.Tsx : SgLang.TypeScript;
|
|
13
|
+
const logger = log ?? (() => { });
|
|
14
|
+
const imports = [];
|
|
15
|
+
const dynamicImports = [];
|
|
16
|
+
try {
|
|
17
|
+
const root = sgParse(lang, code);
|
|
18
|
+
const patterns = [
|
|
19
|
+
{
|
|
20
|
+
pattern: `__vite_ssr_import__("$SPECIFIER")`,
|
|
21
|
+
list: imports,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
pattern: `__vite_ssr_import__('$SPECIFIER')`,
|
|
25
|
+
list: imports,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: `__vite_ssr_dynamic_import__("$SPECIFIER")`,
|
|
29
|
+
list: dynamicImports,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
pattern: `__vite_ssr_dynamic_import__('$SPECIFIER')`,
|
|
33
|
+
list: dynamicImports,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
for (const { pattern, list } of patterns) {
|
|
37
|
+
const matches = root.root().findAll(pattern);
|
|
38
|
+
for (const match of matches) {
|
|
39
|
+
const specifier = match.getMatch("SPECIFIER")?.text();
|
|
40
|
+
if (specifier) {
|
|
41
|
+
list.push(specifier);
|
|
42
|
+
logger(`Found SSR import specifier: %s in pattern: %s`, specifier, pattern);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
logger("Error parsing code for SSR imports: %O", err);
|
|
49
|
+
}
|
|
50
|
+
return { imports, dynamicImports };
|
|
51
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { invalidateModule } from "./invalidateModule.mjs";
|
|
2
|
+
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
3
|
+
import { VIRTUAL_SSR_PREFIX } from "./ssrBridgePlugin.mjs";
|
|
4
|
+
export const invalidateClientModule = (devServer, filePath) => {
|
|
5
|
+
invalidateModule(devServer, "ssr", filePath);
|
|
6
|
+
invalidateModule(devServer, "client", filePath);
|
|
7
|
+
invalidateModule(devServer, "worker", VIRTUAL_SSR_PREFIX + normalizeModulePath(devServer.config.root, filePath));
|
|
8
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
const log = debug("rwsdk:vite:invalidate-module");
|
|
3
|
+
const verboseLog = debug("verbose:rwsdk:vite:invalidate-module");
|
|
4
|
+
export const invalidateModule = (devServer, environment, id) => {
|
|
5
|
+
const [rawId, _query] = id.split("?");
|
|
6
|
+
log("Invalidating module: id=%s, environment=%s", id, environment);
|
|
7
|
+
const moduleNode = devServer?.environments[environment]?.moduleGraph.idToModuleMap.get(rawId);
|
|
8
|
+
if (moduleNode) {
|
|
9
|
+
devServer?.environments[environment]?.moduleGraph.invalidateModule(moduleNode);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
verboseLog("Module not found: id=%s, environment=%s", id, environment);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { invalidateModule } from "./invalidateModule.mjs";
|
|
2
|
+
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
3
|
+
import { VIRTUAL_SSR_PREFIX } from "./ssrBridgePlugin.mjs";
|
|
4
|
+
export const invalidateSSRModule = (devServer, filePath) => {
|
|
5
|
+
invalidateModule(devServer, "ssr", filePath);
|
|
6
|
+
invalidateModule(devServer, "worker", VIRTUAL_SSR_PREFIX + normalizeModulePath(devServer.config.root, filePath));
|
|
7
|
+
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import colors from "picocolors";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
|
+
import debug from "debug";
|
|
5
|
+
import { VIRTUAL_SSR_PREFIX } from "./ssrBridgePlugin.mjs";
|
|
6
|
+
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
4
7
|
import { getShortName } from "../lib/getShortName.mjs";
|
|
5
8
|
import { pathExists } from "fs-extra";
|
|
9
|
+
const verboseLog = debug("verbose:rwsdk:vite:hmr-plugin");
|
|
6
10
|
const hasEntryAsAncestor = (module, entryFile, seen = new Set()) => {
|
|
7
11
|
// Prevent infinite recursion
|
|
8
12
|
if (seen.has(module))
|
|
@@ -68,10 +72,11 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
68
72
|
{
|
|
69
73
|
name: "rwsdk:miniflare-hmr",
|
|
70
74
|
async hotUpdate(ctx) {
|
|
75
|
+
verboseLog("Hot update: (env=%s) %s\nModule graph:\n\n%s", this.environment.name, ctx.file, dumpFullModuleGraph(ctx.server, this.environment.name));
|
|
71
76
|
const environment = givenOptions.viteEnvironment.name;
|
|
72
77
|
const entry = givenOptions.workerEntryPathname;
|
|
73
78
|
if (!["client", environment].includes(this.environment.name)) {
|
|
74
|
-
return;
|
|
79
|
+
return [];
|
|
75
80
|
}
|
|
76
81
|
// todo(justinvdm, 12 Dec 2024): Skip client references
|
|
77
82
|
const modules = Array.from(ctx.server.environments[environment].moduleGraph.getModulesByFile(ctx.file) ?? []);
|
|
@@ -119,6 +124,11 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
119
124
|
if (m) {
|
|
120
125
|
ctx.server.environments.client.moduleGraph.invalidateModule(m, new Set(), ctx.timestamp, true);
|
|
121
126
|
}
|
|
127
|
+
const virtualSSRModule = ctx.server.environments[environment].moduleGraph.idToModuleMap.get(VIRTUAL_SSR_PREFIX +
|
|
128
|
+
normalizeModulePath(givenOptions.rootDir, ctx.file));
|
|
129
|
+
if (virtualSSRModule) {
|
|
130
|
+
ctx.server.environments.worker.moduleGraph.invalidateModule(virtualSSRModule, new Set(), ctx.timestamp, true);
|
|
131
|
+
}
|
|
122
132
|
ctx.server.environments.client.hot.send({
|
|
123
133
|
type: "custom",
|
|
124
134
|
event: "rsc:update",
|
|
@@ -131,3 +141,35 @@ export const miniflareHMRPlugin = (givenOptions) => [
|
|
|
131
141
|
},
|
|
132
142
|
},
|
|
133
143
|
];
|
|
144
|
+
function dumpFullModuleGraph(server, environment, { includeDisconnected = true } = {}) {
|
|
145
|
+
const moduleGraph = server.environments[environment].moduleGraph;
|
|
146
|
+
const seen = new Set();
|
|
147
|
+
const output = [];
|
|
148
|
+
function walk(node, depth = 0) {
|
|
149
|
+
const id = node.id || node.url;
|
|
150
|
+
if (!id || seen.has(id))
|
|
151
|
+
return;
|
|
152
|
+
seen.add(id);
|
|
153
|
+
const pad = " ".repeat(depth);
|
|
154
|
+
const suffix = node.id?.startsWith("virtual:") ? " [virtual]" : "";
|
|
155
|
+
output.push(`${pad}- ${id}${suffix}`);
|
|
156
|
+
for (const dep of node.importedModules) {
|
|
157
|
+
walk(dep, depth + 1);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Start with all modules with no importers (roots)
|
|
161
|
+
const roots = Array.from(moduleGraph.urlToModuleMap.values()).filter((mod) => mod.importers.size === 0);
|
|
162
|
+
for (const root of roots) {
|
|
163
|
+
walk(root);
|
|
164
|
+
}
|
|
165
|
+
// If requested, show disconnected modules too
|
|
166
|
+
if (includeDisconnected) {
|
|
167
|
+
for (const mod of moduleGraph.urlToModuleMap.values()) {
|
|
168
|
+
const id = mod.id || mod.url;
|
|
169
|
+
if (!seen.has(id)) {
|
|
170
|
+
output.push(`- ${id} [disconnected]`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return output.join("\n");
|
|
175
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
2
|
import { SSR_BRIDGE_PATH } from "../lib/constants.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { findSsrImportSpecifiers } from "./findSsrSpecifiers.mjs";
|
|
4
4
|
const log = debug("rwsdk:vite:ssr-bridge-plugin");
|
|
5
5
|
const verboseLog = debug("verbose:rwsdk:vite:ssr-bridge-plugin");
|
|
6
6
|
export const VIRTUAL_SSR_PREFIX = "virtual:rwsdk:ssr:";
|
|
@@ -54,7 +54,6 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
|
|
|
54
54
|
// SSR modules, so we return the virtual id so that the dynamic loading
|
|
55
55
|
// can happen in load()
|
|
56
56
|
if (id.startsWith(VIRTUAL_SSR_PREFIX)) {
|
|
57
|
-
invalidateModule(devServer, "worker", id);
|
|
58
57
|
log("Returning virtual SSR id for dev: %s", id);
|
|
59
58
|
return id;
|
|
60
59
|
}
|
|
@@ -65,7 +64,6 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
|
|
|
65
64
|
if (id === "rwsdk/__ssr_bridge" && this.environment.name === "worker") {
|
|
66
65
|
const virtualId = `${VIRTUAL_SSR_PREFIX}${id}`;
|
|
67
66
|
log("Bridge module case (dev): id=%s matches rwsdk/__ssr_bridge in worker environment, returning virtual id=%s", id, virtualId);
|
|
68
|
-
invalidateModule(devServer, "worker", virtualId);
|
|
69
67
|
return virtualId;
|
|
70
68
|
}
|
|
71
69
|
}
|
|
@@ -91,14 +89,24 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
|
|
|
91
89
|
log("Dev mode: fetching SSR module for realPath=%s", realId);
|
|
92
90
|
const result = await devServer?.environments.ssr.fetchModule(realId);
|
|
93
91
|
verboseLog("Fetch module result: id=%s, result=%O", realId, result);
|
|
94
|
-
if (!result) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
92
|
const code = "code" in result ? result.code : undefined;
|
|
98
93
|
log("Fetched SSR module code length: %d", code?.length || 0);
|
|
99
|
-
|
|
94
|
+
const { imports, dynamicImports } = findSsrImportSpecifiers(realId, code || "", verboseLog);
|
|
95
|
+
const allSpecifiers = [...new Set([...imports, ...dynamicImports])];
|
|
96
|
+
const switchCases = allSpecifiers
|
|
97
|
+
.map((specifier) => ` case "${specifier}": return import("${VIRTUAL_SSR_PREFIX}${specifier}");`)
|
|
98
|
+
.join("\n");
|
|
100
99
|
const transformedCode = `
|
|
101
|
-
await (async function(__vite_ssr_import__, __vite_ssr_dynamic_import__) {${code}})(
|
|
100
|
+
await (async function(__vite_ssr_import__, __vite_ssr_dynamic_import__) {${code}})(
|
|
101
|
+
(id, ...args) => {ssrImport(id); return __vite_ssr_import__('/@id/${VIRTUAL_SSR_PREFIX}' + id, ...args);},
|
|
102
|
+
(id, ...args) => {ssrImport(id); return __vite_ssr_dynamic_import__('/@id/${VIRTUAL_SSR_PREFIX}' + id, ...args);}
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
function ssrImport(id) {
|
|
106
|
+
switch (id) {
|
|
107
|
+
${switchCases}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
102
110
|
`;
|
|
103
111
|
log("Transformed SSR module code length: %d", transformedCode.length);
|
|
104
112
|
verboseLog("Transformed SSR module code for realId=%s: %s", realId, transformedCode);
|