mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 12:37:20 +00:00
cloudflare: enable fs with @cloudflare/vite-plugin (#239)
* init dev vite write plugin * reorganized cf proxy, fixed dev write
This commit is contained in:
@@ -15,7 +15,7 @@ export {
|
||||
export { constants } from "./config";
|
||||
export { StorageR2Adapter, registerMedia } from "./storage/StorageR2Adapter";
|
||||
export { registries } from "bknd";
|
||||
export { withPlatformProxy } from "./proxy";
|
||||
export { devFsPlugin, devFsWrite } from "./vite";
|
||||
|
||||
// for compatibility with old code
|
||||
export function d1<DB extends D1Database | D1DatabaseSession = D1Database>(
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
registerMedia,
|
||||
type CloudflareBkndConfig,
|
||||
type CloudflareEnv,
|
||||
} from ".";
|
||||
} from "bknd/adapter/cloudflare";
|
||||
import type { PlatformProxy } from "wrangler";
|
||||
import process from "node:process";
|
||||
|
||||
@@ -41,12 +41,13 @@ export function withPlatformProxy<Env extends CloudflareEnv>(
|
||||
beforeBuild: async (app, registries) => {
|
||||
if (!use_proxy) return;
|
||||
const env = await getEnv();
|
||||
registerMedia(env, registries);
|
||||
registerMedia(env, registries as any);
|
||||
await config?.beforeBuild?.(app, registries);
|
||||
},
|
||||
bindings: async (env) => {
|
||||
return (await config?.bindings?.(await getEnv(env))) || {};
|
||||
},
|
||||
// @ts-ignore
|
||||
app: async (_env) => {
|
||||
const env = await getEnv(_env);
|
||||
|
||||
|
||||
135
app/src/adapter/cloudflare/vite.ts
Normal file
135
app/src/adapter/cloudflare/vite.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import type { Plugin } from "vite";
|
||||
import { writeFile as nodeWriteFile } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
/**
|
||||
* Vite plugin that provides Node.js filesystem access during development
|
||||
* by injecting a polyfill into the SSR environment
|
||||
*/
|
||||
export function devFsPlugin({
|
||||
verbose = false,
|
||||
configFile = "bknd.config.ts",
|
||||
}: {
|
||||
verbose?: boolean;
|
||||
configFile?: string;
|
||||
}): Plugin {
|
||||
let isDev = false;
|
||||
let projectRoot = "";
|
||||
|
||||
return {
|
||||
name: "dev-fs-plugin",
|
||||
enforce: "pre",
|
||||
configResolved(config) {
|
||||
isDev = config.command === "serve";
|
||||
projectRoot = config.root;
|
||||
},
|
||||
configureServer(server) {
|
||||
if (!isDev) return;
|
||||
|
||||
// Intercept stdout to watch for our write requests
|
||||
const originalStdoutWrite = process.stdout.write;
|
||||
process.stdout.write = function (chunk: any, encoding?: any, callback?: any) {
|
||||
const output = chunk.toString();
|
||||
|
||||
// Check if this output contains our special write request
|
||||
if (output.includes("{{DEV_FS_WRITE_REQUEST}}")) {
|
||||
try {
|
||||
// Extract the JSON from the log line
|
||||
const match = output.match(/{{DEV_FS_WRITE_REQUEST}} ({.*})/);
|
||||
if (match) {
|
||||
const writeRequest = JSON.parse(match[1]);
|
||||
if (writeRequest.type === "DEV_FS_WRITE_REQUEST") {
|
||||
if (verbose) {
|
||||
console.debug("[dev-fs-plugin] Intercepted write request via stdout");
|
||||
}
|
||||
|
||||
// Process the write request immediately
|
||||
(async () => {
|
||||
try {
|
||||
const fullPath = resolve(projectRoot, writeRequest.filename);
|
||||
await nodeWriteFile(fullPath, writeRequest.data);
|
||||
if (verbose) {
|
||||
console.debug("[dev-fs-plugin] File written successfully!");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[dev-fs-plugin] Error writing file:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
// Don't output the raw write request to console
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Not a valid write request, continue with normal output
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// biome-ignore lint:
|
||||
return originalStdoutWrite.apply(process.stdout, arguments);
|
||||
};
|
||||
|
||||
// Restore stdout when server closes
|
||||
server.httpServer?.on("close", () => {
|
||||
process.stdout.write = originalStdoutWrite;
|
||||
});
|
||||
},
|
||||
// @ts-ignore
|
||||
transform(code, id, options) {
|
||||
// Only transform in SSR mode during development
|
||||
if (!isDev || !options?.ssr) return;
|
||||
|
||||
// Check if this is the bknd config file
|
||||
if (id.includes(configFile)) {
|
||||
if (verbose) {
|
||||
console.debug("[dev-fs-plugin] Transforming", configFile);
|
||||
}
|
||||
|
||||
// Inject our filesystem polyfill at the top of the file
|
||||
const polyfill = `
|
||||
// Dev-fs polyfill injected by vite-plugin-dev-fs
|
||||
if (typeof globalThis !== 'undefined') {
|
||||
globalThis.__devFsPolyfill = {
|
||||
writeFile: async (filename, data) => {
|
||||
${verbose ? "console.debug('dev-fs polyfill: Intercepting write request for', filename);" : ""}
|
||||
|
||||
// Use console logging as a communication channel
|
||||
// The main process will watch for this specific log pattern
|
||||
const writeRequest = {
|
||||
type: 'DEV_FS_WRITE_REQUEST',
|
||||
filename: filename,
|
||||
data: data,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
// Output as a specially formatted console message
|
||||
console.log('{{DEV_FS_WRITE_REQUEST}}', JSON.stringify(writeRequest));
|
||||
${verbose ? "console.debug('dev-fs polyfill: Write request sent via console');" : ""}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
}
|
||||
`;
|
||||
return polyfill + code;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Write function that uses the dev-fs polyfill injected by our Vite plugin
|
||||
export async function devFsWrite(filename: string, data: string): Promise<void> {
|
||||
try {
|
||||
// Check if the dev-fs polyfill is available (injected by our Vite plugin)
|
||||
if (typeof globalThis !== "undefined" && (globalThis as any).__devFsPolyfill) {
|
||||
return (globalThis as any).__devFsPolyfill.writeFile(filename, data);
|
||||
}
|
||||
|
||||
// Fallback to Node.js fs for other environments (Node.js, Bun)
|
||||
const { writeFile } = await import("node:fs/promises");
|
||||
return writeFile(filename, data);
|
||||
} catch (error) {
|
||||
console.error("[dev-fs-write] Error writing file:", error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user