mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
258 lines
7.2 KiB
TypeScript
258 lines
7.2 KiB
TypeScript
import { $, type Subprocess } from "bun";
|
|
import * as esbuild from "esbuild";
|
|
import postcss from "esbuild-postcss";
|
|
import { entryOutputMeta } from "./internal/esbuild.entry-output-meta.plugin";
|
|
import { guessMimeType } from "./src/media/storage/mime-types";
|
|
|
|
const args = process.argv.slice(2);
|
|
const watch = args.includes("--watch");
|
|
const minify = args.includes("--minify");
|
|
const types = args.includes("--types");
|
|
const sourcemap = args.includes("--sourcemap");
|
|
|
|
type BuildOptions = esbuild.BuildOptions & { name: string };
|
|
|
|
const baseOptions: Partial<Omit<esbuild.BuildOptions, "plugins">> & { plugins?: any[] } = {
|
|
minify,
|
|
sourcemap,
|
|
metafile: true,
|
|
format: "esm",
|
|
drop: ["console", "debugger"],
|
|
loader: {
|
|
".svg": "dataurl",
|
|
},
|
|
define: {
|
|
__isDev: "0",
|
|
},
|
|
};
|
|
|
|
// @ts-ignore
|
|
type BuildFn = (format?: "esm" | "cjs") => BuildOptions;
|
|
|
|
// build BE
|
|
const builds: Record<string, BuildFn> = {
|
|
backend: (format = "esm") => ({
|
|
...baseOptions,
|
|
name: `backend ${format}`,
|
|
entryPoints: [
|
|
"src/index.ts",
|
|
"src/data/index.ts",
|
|
"src/core/index.ts",
|
|
"src/core/utils/index.ts",
|
|
"src/ui/index.ts",
|
|
"src/ui/main.css",
|
|
],
|
|
outdir: "dist",
|
|
outExtension: { ".js": format === "esm" ? ".js" : ".cjs" },
|
|
platform: "browser",
|
|
splitting: false,
|
|
bundle: true,
|
|
plugins: [postcss()],
|
|
//target: "es2022",
|
|
format,
|
|
}),
|
|
/*components: (format = "esm") => ({
|
|
...baseOptions,
|
|
name: `components ${format}`,
|
|
entryPoints: ["src/ui/index.ts", "src/ui/main.css"],
|
|
outdir: "dist/ui",
|
|
outExtension: { ".js": format === "esm" ? ".js" : ".cjs" },
|
|
format,
|
|
platform: "browser",
|
|
splitting: false,
|
|
//target: "es2022",
|
|
bundle: true,
|
|
//external: ["react", "react-dom", "@tanstack/react-query-devtools"],
|
|
plugins: [postcss()],
|
|
loader: {
|
|
".svg": "dataurl",
|
|
".js": "jsx"
|
|
}
|
|
}),*/
|
|
static: (format = "esm") => ({
|
|
...baseOptions,
|
|
name: `static ${format}`,
|
|
entryPoints: ["src/ui/main.tsx", "src/ui/main.css"],
|
|
entryNames: "[dir]/[name]-[hash]",
|
|
outdir: "dist/static",
|
|
outExtension: { ".js": format === "esm" ? ".js" : ".cjs" },
|
|
platform: "browser",
|
|
bundle: true,
|
|
splitting: true,
|
|
inject: ["src/ui/inject.js"],
|
|
target: "es2022",
|
|
format,
|
|
loader: {
|
|
".svg": "dataurl",
|
|
".js": "jsx",
|
|
},
|
|
define: {
|
|
__isDev: "0",
|
|
"process.env.NODE_ENV": '"production"',
|
|
},
|
|
chunkNames: "chunks/[name]-[hash]",
|
|
plugins: [
|
|
postcss(),
|
|
entryOutputMeta(async (info) => {
|
|
const manifest: Record<string, object> = {};
|
|
const toAsset = (output: string) => {
|
|
const name = output.split("/").pop()!;
|
|
return {
|
|
name,
|
|
path: output,
|
|
mime: guessMimeType(name),
|
|
};
|
|
};
|
|
for (const { output, meta } of info) {
|
|
manifest[meta.entryPoint as string] = toAsset(output);
|
|
if (meta.cssBundle) {
|
|
manifest["src/ui/main.css"] = toAsset(meta.cssBundle);
|
|
}
|
|
}
|
|
|
|
const manifest_file = "dist/static/manifest.json";
|
|
await Bun.write(manifest_file, JSON.stringify(manifest, null, 2));
|
|
console.log(`Manifest written to ${manifest_file}`, manifest);
|
|
}),
|
|
],
|
|
}),
|
|
};
|
|
|
|
function adapter(adapter: string, overrides: Partial<esbuild.BuildOptions> = {}): BuildOptions {
|
|
return {
|
|
...baseOptions,
|
|
name: `adapter ${adapter} ${overrides?.format === "cjs" ? "cjs" : "esm"}`,
|
|
entryPoints: [`src/adapter/${adapter}`],
|
|
platform: "neutral",
|
|
outfile: `dist/adapter/${adapter}/index.${overrides?.format === "cjs" ? "cjs" : "js"}`,
|
|
external: [
|
|
"cloudflare:workers",
|
|
"@hono*",
|
|
"hono*",
|
|
"bknd*",
|
|
"*.html",
|
|
"node*",
|
|
"react*",
|
|
"next*",
|
|
"libsql",
|
|
"@libsql*",
|
|
],
|
|
splitting: false,
|
|
treeShaking: true,
|
|
bundle: true,
|
|
...overrides,
|
|
};
|
|
}
|
|
const adapters = [
|
|
adapter("vite", { platform: "node" }),
|
|
adapter("cloudflare"),
|
|
adapter("nextjs", { platform: "node", format: "esm" }),
|
|
adapter("nextjs", { platform: "node", format: "cjs" }),
|
|
adapter("remix", { format: "esm" }),
|
|
adapter("remix", { format: "cjs" }),
|
|
adapter("bun"),
|
|
adapter("node", { platform: "node", format: "esm" }),
|
|
adapter("node", { platform: "node", format: "cjs" }),
|
|
];
|
|
|
|
const collect = [
|
|
builds.static(),
|
|
builds.backend(),
|
|
//builds.components(),
|
|
builds.backend("cjs"),
|
|
//builds.components("cjs"),
|
|
...adapters,
|
|
];
|
|
|
|
if (watch) {
|
|
const _state: {
|
|
timeout: Timer | undefined;
|
|
cleanup: Subprocess | undefined;
|
|
building: Subprocess | undefined;
|
|
} = {
|
|
timeout: undefined,
|
|
cleanup: undefined,
|
|
building: undefined,
|
|
};
|
|
|
|
async function rebuildTypes() {
|
|
if (!types) return;
|
|
if (_state.timeout) {
|
|
clearTimeout(_state.timeout);
|
|
if (_state.cleanup) _state.cleanup.kill();
|
|
if (_state.building) _state.building.kill();
|
|
}
|
|
_state.timeout = setTimeout(async () => {
|
|
_state.cleanup = Bun.spawn(["bun", "clean:types"], {
|
|
onExit: () => {
|
|
_state.cleanup = undefined;
|
|
_state.building = Bun.spawn(["bun", "build:types"], {
|
|
onExit: () => {
|
|
_state.building = undefined;
|
|
console.log("Types rebuilt");
|
|
},
|
|
});
|
|
},
|
|
});
|
|
}, 1000);
|
|
}
|
|
|
|
for (const { name, ...build } of collect) {
|
|
const ctx = await esbuild.context({
|
|
...build,
|
|
plugins: [
|
|
...(build.plugins ?? []),
|
|
{
|
|
name: "rebuild-notify",
|
|
setup(build) {
|
|
build.onEnd((result) => {
|
|
console.log(`rebuilt ${name} with ${result.errors.length} errors`);
|
|
rebuildTypes();
|
|
});
|
|
},
|
|
},
|
|
],
|
|
});
|
|
ctx.watch();
|
|
}
|
|
} else {
|
|
await $`rm -rf dist`;
|
|
|
|
async function _build() {
|
|
let i = 0;
|
|
const count = collect.length;
|
|
for await (const { name, ...build } of collect) {
|
|
await esbuild.build({
|
|
...build,
|
|
plugins: [
|
|
...(build.plugins || []),
|
|
{
|
|
name: "progress",
|
|
setup(build) {
|
|
i++;
|
|
build.onEnd((result) => {
|
|
const errors = result.errors.length;
|
|
const from = String(i).padStart(String(count).length);
|
|
console.log(`[${from}/${count}] built ${name} with ${errors} errors`);
|
|
});
|
|
},
|
|
},
|
|
],
|
|
});
|
|
}
|
|
|
|
console.log("All builds complete");
|
|
}
|
|
|
|
async function _buildtypes() {
|
|
if (!types) return;
|
|
Bun.spawn(["bun", "build:types"], {
|
|
onExit: () => {
|
|
console.log("Types rebuilt");
|
|
},
|
|
});
|
|
}
|
|
|
|
await Promise.all([_build(), _buildtypes()]);
|
|
}
|