mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
changed build workflow – for auth it's required to have better control over html and assets
This commit is contained in:
@@ -5,7 +5,8 @@ export default {
|
|||||||
connection: {
|
connection: {
|
||||||
type: "libsql",
|
type: "libsql",
|
||||||
config: {
|
config: {
|
||||||
url: "http://localhost:8080"
|
//url: "http://localhost:8080"
|
||||||
|
url: ":memory:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import process from "node:process";
|
|
||||||
import { $ } from "bun";
|
|
||||||
import * as esbuild from "esbuild";
|
|
||||||
import type { BuildOptions } from "esbuild";
|
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV !== "production";
|
|
||||||
|
|
||||||
const metafile = true;
|
|
||||||
const sourcemap = false;
|
|
||||||
|
|
||||||
const config: BuildOptions = {
|
|
||||||
entryPoints: ["worker.ts"],
|
|
||||||
bundle: true,
|
|
||||||
format: "esm",
|
|
||||||
external: ["__STATIC_CONTENT_MANIFEST", "@xyflow/react"],
|
|
||||||
platform: "browser",
|
|
||||||
conditions: ["worker", "browser"],
|
|
||||||
target: "es2022",
|
|
||||||
sourcemap,
|
|
||||||
metafile,
|
|
||||||
minify: !isDev,
|
|
||||||
loader: {
|
|
||||||
".html": "copy"
|
|
||||||
},
|
|
||||||
outfile: "dist/worker.js"
|
|
||||||
};
|
|
||||||
|
|
||||||
const dist = config.outfile!.split("/")[0];
|
|
||||||
if (!isDev) {
|
|
||||||
await $`rm -rf ${dist}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await esbuild.build(config);
|
|
||||||
|
|
||||||
if (result.metafile) {
|
|
||||||
console.log("writing metafile to", `${dist}/meta.json`);
|
|
||||||
await Bun.write(`${dist}/meta.json`, JSON.stringify(result.metafile!));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDev) {
|
|
||||||
await $`gzip ${dist}/worker.js -c > ${dist}/worker.js.gz`;
|
|
||||||
}
|
|
||||||
257
app/build.esbuild.ts
Normal file
257
app/build.esbuild.ts
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
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()]);
|
||||||
|
}
|
||||||
175
app/build.ts
Normal file
175
app/build.ts
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
import { $ } from "bun";
|
||||||
|
import * as esbuild from "esbuild";
|
||||||
|
import postcss from "esbuild-postcss";
|
||||||
|
import * as tsup from "tsup";
|
||||||
|
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");
|
||||||
|
|
||||||
|
await $`rm -rf dist`;
|
||||||
|
if (types) {
|
||||||
|
Bun.spawn(["bun", "build:types"], {
|
||||||
|
onExit: () => {
|
||||||
|
console.log("Types built");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build static assets
|
||||||
|
* Using esbuild because tsup doesn't include "react"
|
||||||
|
*/
|
||||||
|
const result = await esbuild.build({
|
||||||
|
minify,
|
||||||
|
sourcemap,
|
||||||
|
entryPoints: ["src/ui/main.tsx"],
|
||||||
|
entryNames: "[dir]/[name]-[hash]",
|
||||||
|
outdir: "dist/static",
|
||||||
|
platform: "browser",
|
||||||
|
bundle: true,
|
||||||
|
splitting: true,
|
||||||
|
metafile: true,
|
||||||
|
drop: ["console", "debugger"],
|
||||||
|
inject: ["src/ui/inject.js"],
|
||||||
|
target: "es2022",
|
||||||
|
format: "esm",
|
||||||
|
plugins: [postcss()],
|
||||||
|
loader: {
|
||||||
|
".svg": "dataurl",
|
||||||
|
".js": "jsx"
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
__isDev: "0",
|
||||||
|
"process.env.NODE_ENV": '"production"'
|
||||||
|
},
|
||||||
|
chunkNames: "chunks/[name]-[hash]"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write manifest
|
||||||
|
{
|
||||||
|
const manifest: Record<string, object> = {};
|
||||||
|
const toAsset = (output: string) => {
|
||||||
|
const name = output.split("/").pop()!;
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
path: output,
|
||||||
|
mime: guessMimeType(name)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const info = Object.entries(result.metafile.outputs)
|
||||||
|
.filter(([, meta]) => {
|
||||||
|
return meta.entryPoint && meta.entryPoint === "src/ui/main.tsx";
|
||||||
|
})
|
||||||
|
.map(([output, meta]) => ({ output, meta }));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Building backend and general API
|
||||||
|
*/
|
||||||
|
await tsup.build({
|
||||||
|
minify,
|
||||||
|
sourcemap,
|
||||||
|
watch,
|
||||||
|
entry: ["src/index.ts", "src/data/index.ts", "src/core/index.ts", "src/core/utils/index.ts"],
|
||||||
|
outDir: "dist",
|
||||||
|
external: ["bun:test"],
|
||||||
|
metafile: true,
|
||||||
|
platform: "browser",
|
||||||
|
format: ["esm", "cjs"],
|
||||||
|
splitting: false,
|
||||||
|
loader: {
|
||||||
|
".svg": "dataurl"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Building UI for direct imports
|
||||||
|
*/
|
||||||
|
await tsup.build({
|
||||||
|
minify,
|
||||||
|
sourcemap,
|
||||||
|
watch,
|
||||||
|
entry: ["src/ui/index.ts", "src/ui/client/index.ts", "src/ui/main.css"],
|
||||||
|
outDir: "dist/ui",
|
||||||
|
external: ["bun:test"],
|
||||||
|
metafile: true,
|
||||||
|
platform: "browser",
|
||||||
|
format: ["esm", "cjs"],
|
||||||
|
splitting: true,
|
||||||
|
loader: {
|
||||||
|
".svg": "dataurl"
|
||||||
|
},
|
||||||
|
onSuccess: async () => {
|
||||||
|
console.log("--- ui built");
|
||||||
|
},
|
||||||
|
esbuildOptions: (options) => {
|
||||||
|
options.chunkNames = "chunks/[name]-[hash]";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Building adapters
|
||||||
|
*/
|
||||||
|
function baseConfig(adapter: string): tsup.Options {
|
||||||
|
return {
|
||||||
|
minify,
|
||||||
|
sourcemap,
|
||||||
|
watch,
|
||||||
|
entry: [`src/adapter/${adapter}`],
|
||||||
|
format: ["esm"],
|
||||||
|
platform: "neutral",
|
||||||
|
outDir: `dist/adapter/${adapter}`,
|
||||||
|
define: {
|
||||||
|
__isDev: "0"
|
||||||
|
},
|
||||||
|
external: [
|
||||||
|
/^cloudflare*/,
|
||||||
|
/^@?(hono|libsql).*?/,
|
||||||
|
/^(bknd|react|next|node).*?/,
|
||||||
|
/.*\.(html)$/
|
||||||
|
],
|
||||||
|
metafile: true,
|
||||||
|
splitting: false,
|
||||||
|
treeshake: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await tsup.build({
|
||||||
|
...baseConfig("vite"),
|
||||||
|
platform: "node"
|
||||||
|
});
|
||||||
|
|
||||||
|
await tsup.build({
|
||||||
|
...baseConfig("cloudflare")
|
||||||
|
});
|
||||||
|
|
||||||
|
await tsup.build({
|
||||||
|
...baseConfig("nextjs"),
|
||||||
|
format: ["esm", "cjs"],
|
||||||
|
platform: "node"
|
||||||
|
});
|
||||||
|
|
||||||
|
await tsup.build({
|
||||||
|
...baseConfig("remix"),
|
||||||
|
format: ["esm", "cjs"]
|
||||||
|
});
|
||||||
|
|
||||||
|
await tsup.build({
|
||||||
|
...baseConfig("bun")
|
||||||
|
});
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en" class="light">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
||||||
<title>BKND</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- BKND_CONTEXT -->
|
|
||||||
<script type="module" src="/src/ui/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
33
app/internal/esbuild.entry-output-meta.plugin.ts
Normal file
33
app/internal/esbuild.entry-output-meta.plugin.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { Metafile, Plugin } from "esbuild";
|
||||||
|
|
||||||
|
export const entryOutputMeta = (
|
||||||
|
onComplete?: (
|
||||||
|
outputs: {
|
||||||
|
output: string;
|
||||||
|
meta: Metafile["outputs"][string];
|
||||||
|
}[]
|
||||||
|
) => void | Promise<void>
|
||||||
|
): Plugin => ({
|
||||||
|
name: "report-entry-output-plugin",
|
||||||
|
setup(build) {
|
||||||
|
build.initialOptions.metafile = true; // Ensure metafile is enabled
|
||||||
|
|
||||||
|
build.onEnd(async (result) => {
|
||||||
|
console.log("result", result);
|
||||||
|
if (result?.metafile?.outputs) {
|
||||||
|
const entries = build.initialOptions.entryPoints! as string[];
|
||||||
|
|
||||||
|
const outputs = Object.entries(result.metafile.outputs)
|
||||||
|
.filter(([, meta]) => {
|
||||||
|
return meta.entryPoint && entries.includes(meta.entryPoint);
|
||||||
|
})
|
||||||
|
.map(([output, meta]) => ({ output, meta }));
|
||||||
|
if (outputs.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await onComplete?.(outputs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -5,18 +5,16 @@
|
|||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"version": "0.0.13",
|
"version": "0.0.13",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:all": "rm -rf dist && bun build:css && bun run build && bun build:vite && bun build:adapters && bun build:cli",
|
"build:all": "bun run build && bun run build:cli",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"test": "ALL_TESTS=1 bun test --bail",
|
"test": "ALL_TESTS=1 bun test --bail",
|
||||||
"build": "bun tsup && bun build:types",
|
"build": "bun run build.ts --minify --types",
|
||||||
"watch": "bun tsup --watch --onSuccess 'bun run build:types'",
|
"watch": "bun run build.ts --types --watch",
|
||||||
"types": "bun tsc --noEmit",
|
"types": "bun tsc --noEmit",
|
||||||
|
"clean:types": "find ./dist -name '*.d.ts' -delete && rm -f ./dist/tsconfig.tsbuildinfo",
|
||||||
"build:types": "tsc --emitDeclarationOnly",
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
"build:css": "bun tailwindcss -i ./src/ui/styles.css -o ./dist/styles.css",
|
"build:css": "bun tailwindcss -i src/ui/main.css -o ./dist/static/styles.css",
|
||||||
"watch:css": "bun tailwindcss --watch -i ./src/ui/styles.css -o ./dist/styles.css",
|
"watch:css": "bun tailwindcss --watch -i src/ui/main.css -o ./dist/styles.css",
|
||||||
"build:vite": "NODE_ENV=production vite build",
|
|
||||||
"build:adapters": "bun tsup.adapters.ts --minify",
|
|
||||||
"watch:adapters": "bun tsup.adapters.ts --watch",
|
|
||||||
"updater": "bun x npm-check-updates -ui",
|
"updater": "bun x npm-check-updates -ui",
|
||||||
"build:cli": "bun build src/cli/index.ts --target node --outdir dist/cli --minify",
|
"build:cli": "bun build src/cli/index.ts --target node --outdir dist/cli --minify",
|
||||||
"cli": "LOCAL=1 bun src/cli/index.ts"
|
"cli": "LOCAL=1 bun src/cli/index.ts"
|
||||||
@@ -77,6 +75,7 @@
|
|||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.3.3",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
|
"esbuild-postcss": "^0.0.4",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
@@ -88,20 +87,6 @@
|
|||||||
"vite-plugin-static-copy": "^2.0.0",
|
"vite-plugin-static-copy": "^2.0.0",
|
||||||
"vite-tsconfig-paths": "^5.0.1"
|
"vite-tsconfig-paths": "^5.0.1"
|
||||||
},
|
},
|
||||||
"tsup": {
|
|
||||||
"entry": ["src/index.ts", "src/ui/index.ts", "src/data/index.ts", "src/core/index.ts", "src/core/utils/index.ts"],
|
|
||||||
"minify": true,
|
|
||||||
"outDir": "dist",
|
|
||||||
"external": ["bun:test", "bknd/dist/manifest.json"],
|
|
||||||
"sourcemap": true,
|
|
||||||
"metafile": true,
|
|
||||||
"platform": "browser",
|
|
||||||
"format": ["esm", "cjs"],
|
|
||||||
"splitting": true,
|
|
||||||
"loader": {
|
|
||||||
".svg": "dataurl"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
"react-dom": ">=18"
|
"react-dom": ">=18"
|
||||||
@@ -120,6 +105,11 @@
|
|||||||
"import": "./dist/ui/index.js",
|
"import": "./dist/ui/index.js",
|
||||||
"require": "./dist/ui/index.cjs"
|
"require": "./dist/ui/index.cjs"
|
||||||
},
|
},
|
||||||
|
"./client": {
|
||||||
|
"types": "./dist/ui/client/index.d.ts",
|
||||||
|
"import": "./dist/ui/client/index.js",
|
||||||
|
"require": "./dist/ui/client/index.cjs"
|
||||||
|
},
|
||||||
"./data": {
|
"./data": {
|
||||||
"types": "./dist/data/index.d.ts",
|
"types": "./dist/data/index.d.ts",
|
||||||
"import": "./dist/data/index.js",
|
"import": "./dist/data/index.js",
|
||||||
@@ -170,10 +160,8 @@
|
|||||||
"import": "./dist/adapter/node/index.js",
|
"import": "./dist/adapter/node/index.js",
|
||||||
"require": "./dist/adapter/node/index.cjs"
|
"require": "./dist/adapter/node/index.cjs"
|
||||||
},
|
},
|
||||||
"./dist/static/manifest.json": "./dist/static/.vite/manifest.json",
|
"./dist/styles.css": "./dist/ui/main.css",
|
||||||
"./dist/styles.css": "./dist/styles.css",
|
"./dist/manifest.json": "./dist/static/manifest.json"
|
||||||
"./dist/index.html": "./dist/static/index.html",
|
|
||||||
"./dist/manifest.json": "./dist/static/.vite/manifest.json"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,59 +1,34 @@
|
|||||||
import { readFile } from "node:fs/promises";
|
|
||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import type { BkndConfig } from "bknd";
|
import type { BkndConfig } from "bknd";
|
||||||
import { App } from "bknd";
|
import { App } from "bknd";
|
||||||
|
|
||||||
async function getHtml() {
|
|
||||||
return readFile("index.html", "utf8");
|
|
||||||
}
|
|
||||||
function addViteScripts(html: string) {
|
|
||||||
return html.replace(
|
|
||||||
"<head>",
|
|
||||||
`<script type="module">
|
|
||||||
import RefreshRuntime from "/@react-refresh"
|
|
||||||
RefreshRuntime.injectIntoGlobalHook(window)
|
|
||||||
window.$RefreshReg$ = () => {}
|
|
||||||
window.$RefreshSig$ = () => (type) => type
|
|
||||||
window.__vite_plugin_react_preamble_installed__ = true
|
|
||||||
</script>
|
|
||||||
<script type="module" src="/@vite/client"></script>
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createApp(config: BkndConfig, env: any) {
|
function createApp(config: BkndConfig, env: any) {
|
||||||
const create_config = typeof config.app === "function" ? config.app(env) : config.app;
|
const create_config = typeof config.app === "function" ? config.app(env) : config.app;
|
||||||
return App.create(create_config);
|
return App.create(create_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAppBuildListener(app: App, config: BkndConfig, html: string) {
|
function setAppBuildListener(app: App, config: BkndConfig, html?: string) {
|
||||||
app.emgr.on(
|
app.emgr.on(
|
||||||
"app-built",
|
"app-built",
|
||||||
async () => {
|
async () => {
|
||||||
await config.onBuilt?.(app);
|
await config.onBuilt?.(app);
|
||||||
app.registerAdminController();
|
if (config.setAdminHtml) {
|
||||||
app.module.server.client.get("/assets/!*", serveStatic({ root: "./" }));
|
app.registerAdminController({ html, forceDev: true });
|
||||||
|
app.module.server.client.get("/assets/*", serveStatic({ root: "./" }));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"sync"
|
"sync"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function serveFresh(config: BkndConfig, _html?: string) {
|
export async function serveFresh(config: BkndConfig, _html?: string) {
|
||||||
let html = _html;
|
|
||||||
if (!html) {
|
|
||||||
html = await getHtml();
|
|
||||||
}
|
|
||||||
|
|
||||||
html = addViteScripts(html);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
||||||
const app = createApp(config, env);
|
const app = createApp(config, env);
|
||||||
|
|
||||||
setAppBuildListener(app, config, html);
|
setAppBuildListener(app, config, _html);
|
||||||
await app.build();
|
await app.build();
|
||||||
|
|
||||||
//console.log("routes", app.module.server.client.routes);
|
|
||||||
return app.fetch(request, env, ctx);
|
return app.fetch(request, env, ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -61,18 +36,11 @@ export async function serveFresh(config: BkndConfig, _html?: string) {
|
|||||||
|
|
||||||
let app: App;
|
let app: App;
|
||||||
export async function serveCached(config: BkndConfig, _html?: string) {
|
export async function serveCached(config: BkndConfig, _html?: string) {
|
||||||
let html = _html;
|
|
||||||
if (!html) {
|
|
||||||
html = await getHtml();
|
|
||||||
}
|
|
||||||
|
|
||||||
html = addViteScripts(html);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
||||||
if (!app) {
|
if (!app) {
|
||||||
app = createApp(config, env);
|
app = createApp(config, env);
|
||||||
setAppBuildListener(app, config, html);
|
setAppBuildListener(app, config, _html);
|
||||||
await app.build();
|
await app.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export async function serveStatic(server: Platform): Promise<MiddlewareHandler>
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function attachServeStatic(app: any, platform: Platform) {
|
export async function attachServeStatic(app: any, platform: Platform) {
|
||||||
app.module.server.client.get("/assets/*", await serveStatic(platform));
|
app.module.server.client.get("/*", await serveStatic(platform));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startServer(server: Platform, app: any, options: { port: number }) {
|
export async function startServer(server: Platform, app: any, options: { port: number }) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async function makeApp(config: MakeAppConfig) {
|
|||||||
"app-built",
|
"app-built",
|
||||||
async () => {
|
async () => {
|
||||||
await attachServeStatic(app, config.server?.platform ?? "node");
|
await attachServeStatic(app, config.server?.platform ?? "node");
|
||||||
app.registerAdminController({ html: await getHtml() });
|
app.registerAdminController();
|
||||||
|
|
||||||
if (config.onBuilt) {
|
if (config.onBuilt) {
|
||||||
await config.onBuilt(app);
|
await config.onBuilt(app);
|
||||||
@@ -75,7 +75,7 @@ export async function makeConfigApp(config: BkndConfig, platform?: Platform) {
|
|||||||
"app-built",
|
"app-built",
|
||||||
async () => {
|
async () => {
|
||||||
await attachServeStatic(app, platform ?? "node");
|
await attachServeStatic(app, platform ?? "node");
|
||||||
app.registerAdminController({ html: await getHtml() });
|
app.registerAdminController();
|
||||||
|
|
||||||
if (config.onBuilt) {
|
if (config.onBuilt) {
|
||||||
await config.onBuilt(app);
|
await config.onBuilt(app);
|
||||||
|
|||||||
@@ -7,20 +7,12 @@ import { Hono } from "hono";
|
|||||||
import { html } from "hono/html";
|
import { html } from "hono/html";
|
||||||
import { Fragment } from "hono/jsx";
|
import { Fragment } from "hono/jsx";
|
||||||
import * as SystemPermissions from "modules/permissions";
|
import * as SystemPermissions from "modules/permissions";
|
||||||
import type { Manifest } from "vite";
|
|
||||||
|
|
||||||
const viteInject = `
|
|
||||||
import RefreshRuntime from "/@react-refresh"
|
|
||||||
RefreshRuntime.injectIntoGlobalHook(window)
|
|
||||||
window.$RefreshReg$ = () => {}
|
|
||||||
window.$RefreshSig$ = () => (type) => type
|
|
||||||
window.__vite_plugin_react_preamble_installed__ = true
|
|
||||||
`;
|
|
||||||
const htmlBkndContextReplace = "<!-- BKND_CONTEXT -->";
|
const htmlBkndContextReplace = "<!-- BKND_CONTEXT -->";
|
||||||
|
|
||||||
export type AdminControllerOptions = {
|
export type AdminControllerOptions = {
|
||||||
html?: string;
|
html?: string;
|
||||||
viteManifest?: Manifest;
|
forceDev?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class AdminController implements ClassController {
|
export class AdminController implements ClassController {
|
||||||
@@ -114,44 +106,36 @@ export class AdminController implements ClassController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.warn(
|
console.warn(
|
||||||
"Custom HTML needs to include '<!-- BKND_CONTEXT -->' to inject BKND context"
|
`Custom HTML needs to include '${htmlBkndContextReplace}' to inject BKND context`
|
||||||
);
|
);
|
||||||
return this.options.html as string;
|
return this.options.html as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const configs = this.app.modules.configs();
|
const configs = this.app.modules.configs();
|
||||||
|
const isProd = !isDebug() && !this.options.forceDev;
|
||||||
|
|
||||||
// @todo: implement guard redirect once cookie sessions arrive
|
const assets = {
|
||||||
|
js: "main.js",
|
||||||
|
css: "styles.css"
|
||||||
|
};
|
||||||
|
|
||||||
const isProd = !isDebug();
|
|
||||||
let script: string | undefined;
|
|
||||||
let css: string[] = [];
|
|
||||||
|
|
||||||
// @todo: check why nextjs imports manifest, it's not required
|
|
||||||
if (isProd) {
|
if (isProd) {
|
||||||
const manifest: Manifest = this.options.viteManifest
|
try {
|
||||||
? this.options.viteManifest
|
// @ts-ignore
|
||||||
: isProd
|
const manifest = await import("bknd/dist/manifest.json", {
|
||||||
? // @ts-ignore cases issues when building types
|
assert: { type: "json" }
|
||||||
await import("bknd/dist/manifest.json", { assert: { type: "json" } }).then(
|
}).then((m) => m.default);
|
||||||
(m) => m.default
|
assets.js = manifest["src/ui/main.tsx"].name;
|
||||||
)
|
assets.css = manifest["src/ui/main.css"].name;
|
||||||
: {};
|
} catch (e) {
|
||||||
//console.log("manifest", manifest, manifest["index.html"]);
|
console.error("Error loading manifest", e);
|
||||||
const entry = Object.values(manifest).find((f: any) => f.isEntry === true);
|
|
||||||
if (!entry) {
|
|
||||||
// do something smart
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
script = "/" + entry.file;
|
|
||||||
css = entry.css?.map((c: string) => "/" + c) ?? [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{/* dnd complains otherwise */}
|
{/* dnd complains otherwise */}
|
||||||
{html`<!doctype html>`}
|
{html`<!DOCTYPE html>`}
|
||||||
<html lang="en" class={configs.server.admin.color_scheme ?? "light"}>
|
<html lang="en" class={configs.server.admin.color_scheme ?? "light"}>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
@@ -162,14 +146,21 @@ export class AdminController implements ClassController {
|
|||||||
<title>BKND</title>
|
<title>BKND</title>
|
||||||
{isProd ? (
|
{isProd ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<script type="module" CrossOrigin src={script} />
|
<script type="module" CrossOrigin src={"/" + assets?.js} />
|
||||||
{css.map((c) => (
|
<link rel="stylesheet" crossOrigin href={"/" + assets?.css} />
|
||||||
<link rel="stylesheet" CrossOrigin href={c} key={c} />
|
|
||||||
))}
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<script type="module" dangerouslySetInnerHTML={{ __html: viteInject }} />
|
<script
|
||||||
|
type="module"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `import RefreshRuntime from "/@react-refresh"
|
||||||
|
RefreshRuntime.injectIntoGlobalHook(window)
|
||||||
|
window.$RefreshReg$ = () => {}
|
||||||
|
window.$RefreshSig$ = () => (type) => type
|
||||||
|
window.__vite_plugin_react_preamble_installed__ = true`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<script type="module" src={"/@vite/client"} />
|
<script type="module" src={"/@vite/client"} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export { ClientProvider, useClient, useBaseUrl } from "./ClientProvider";
|
|||||||
export { BkndProvider, useBknd } from "./BkndProvider";
|
export { BkndProvider, useBknd } from "./BkndProvider";
|
||||||
|
|
||||||
export { useAuth } from "./schema/auth/use-auth";
|
export { useAuth } from "./schema/auth/use-auth";
|
||||||
|
export { Api } from "../../Api";
|
||||||
|
|||||||
5
app/src/ui/inject.js
Normal file
5
app/src/ui/inject.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// react shim
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
|
||||||
|
export { React, ReactDOM };
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
@import "@mantine/core/styles.css";
|
@import "@mantine/core/styles.css";
|
||||||
@import '@mantine/notifications/styles.css';
|
@import '@mantine/notifications/styles.css';
|
||||||
|
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { StrictMode } from "react";
|
import * as React from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import * as ReactDOM from "react-dom/client";
|
||||||
import "./styles.css";
|
import "./main.css";
|
||||||
|
|
||||||
import Admin from "./Admin";
|
import Admin from "./Admin";
|
||||||
|
|
||||||
@@ -13,9 +13,9 @@ const rootElement = document.getElementById("app")!;
|
|||||||
if (!rootElement.innerHTML) {
|
if (!rootElement.innerHTML) {
|
||||||
const root = ReactDOM.createRoot(rootElement);
|
const root = ReactDOM.createRoot(rootElement);
|
||||||
root.render(
|
root.render(
|
||||||
<StrictMode>
|
<React.StrictMode>
|
||||||
<ClientApp />
|
<ClientApp />
|
||||||
</StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./env.d.ts"],
|
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./env.d.ts"],
|
||||||
"exclude": ["node_modules", "./dist/**/*", "../examples/bun"]
|
"exclude": ["node_modules", "dist/**/*", "../examples/bun"]
|
||||||
}
|
}
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import { type Options, build } from "tsup";
|
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
const watch = args.includes("--watch");
|
|
||||||
const minify = args.includes("--minify");
|
|
||||||
|
|
||||||
function baseConfig(adapter: string): Options {
|
|
||||||
return {
|
|
||||||
entry: [`src/adapter/${adapter}`],
|
|
||||||
format: ["esm"],
|
|
||||||
platform: "neutral",
|
|
||||||
minify: false,
|
|
||||||
outDir: `dist/adapter/${adapter}`,
|
|
||||||
watch,
|
|
||||||
define: {
|
|
||||||
__isDev: "0"
|
|
||||||
},
|
|
||||||
external: [
|
|
||||||
"cloudflare:workers",
|
|
||||||
/^@?hono.*?/,
|
|
||||||
/^bknd.*?/,
|
|
||||||
/.*\.html$/,
|
|
||||||
/^node.*/,
|
|
||||||
/^react.*?/
|
|
||||||
],
|
|
||||||
metafile: true,
|
|
||||||
splitting: false,
|
|
||||||
treeshake: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("vite"),
|
|
||||||
platform: "node"
|
|
||||||
});
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("cloudflare")
|
|
||||||
});
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("nextjs"),
|
|
||||||
format: ["esm", "cjs"],
|
|
||||||
platform: "node",
|
|
||||||
external: [...baseConfig("nextjs").external!, /^next.*/]
|
|
||||||
});
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("remix"),
|
|
||||||
format: ["esm", "cjs"]
|
|
||||||
});
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("bun"),
|
|
||||||
external: [/^hono.*?/, /^bknd.*?/, "node:path"]
|
|
||||||
});
|
|
||||||
|
|
||||||
await build({
|
|
||||||
...baseConfig("node"),
|
|
||||||
format: ["esm", "cjs"],
|
|
||||||
platform: "node"
|
|
||||||
});
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import devServer from "@hono/vite-dev-server";
|
import devServer from "@hono/vite-dev-server";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig, loadEnv } from "vite";
|
||||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
@@ -45,18 +44,5 @@ export default defineConfig(async () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
throw new Error("Don't use vite for building in production");
|
||||||
define: {
|
|
||||||
__isDev: "0"
|
|
||||||
},
|
|
||||||
publicDir: "./src/ui/assets",
|
|
||||||
build: {
|
|
||||||
manifest: true,
|
|
||||||
outDir: "dist/static"
|
|
||||||
/*rollupOptions: { // <-- use this to not require index.html
|
|
||||||
input: "./src/ui/main.tsx"
|
|
||||||
}*/
|
|
||||||
},
|
|
||||||
plugins: [react(), tsconfigPaths()]
|
|
||||||
} as any;
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { createClient } from "@libsql/client/node";
|
import { createClient } from "@libsql/client/node";
|
||||||
import { App, type BkndConfig, type CreateAppConfig } from "./src";
|
import { App } from "./src";
|
||||||
import { LibsqlConnection } from "./src/data";
|
import { LibsqlConnection } from "./src/data";
|
||||||
import { StorageLocalAdapter } from "./src/media/storage/adapters/StorageLocalAdapter";
|
import { StorageLocalAdapter } from "./src/media/storage/adapters/StorageLocalAdapter";
|
||||||
import { registries } from "./src/modules/registries";
|
import { registries } from "./src/modules/registries";
|
||||||
@@ -10,41 +10,30 @@ registries.media.add("local", {
|
|||||||
schema: StorageLocalAdapter.prototype.getSchema()
|
schema: StorageLocalAdapter.prototype.getSchema()
|
||||||
});
|
});
|
||||||
|
|
||||||
const connection = new LibsqlConnection(
|
const credentials = {
|
||||||
createClient({
|
url: import.meta.env.VITE_DB_URL!,
|
||||||
url: "file:.db/new.db"
|
authToken: import.meta.env.VITE_DB_TOKEN!
|
||||||
})
|
};
|
||||||
);
|
if (!credentials.url) {
|
||||||
|
throw new Error("Missing VITE_DB_URL env variable. Add it to .env file");
|
||||||
function createApp(config: BkndConfig, env: any) {
|
|
||||||
const create_config = typeof config.app === "function" ? config.app(env) : config.app;
|
|
||||||
return App.create(create_config as CreateAppConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function serveFresh(config: BkndConfig) {
|
const connection = new LibsqlConnection(createClient(credentials));
|
||||||
return {
|
|
||||||
async fetch(request: Request, env: any) {
|
export default {
|
||||||
const app = createApp(config, env);
|
async fetch(request: Request) {
|
||||||
|
const app = App.create({ connection });
|
||||||
|
|
||||||
app.emgr.on(
|
app.emgr.on(
|
||||||
"app-built",
|
"app-built",
|
||||||
async () => {
|
async () => {
|
||||||
await config.onBuilt?.(app as any);
|
app.registerAdminController({ forceDev: true });
|
||||||
app.registerAdminController();
|
|
||||||
app.module.server.client.get("/assets/*", serveStatic({ root: "./" }));
|
app.module.server.client.get("/assets/*", serveStatic({ root: "./" }));
|
||||||
},
|
},
|
||||||
"sync"
|
"sync"
|
||||||
);
|
);
|
||||||
await app.build();
|
await app.build();
|
||||||
|
|
||||||
return app.fetch(request, env);
|
return app.fetch(request);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default await serveFresh({
|
|
||||||
app: {
|
|
||||||
connection
|
|
||||||
},
|
|
||||||
setAdminHtml: true
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { LoaderFunctionArgs } from "@remix-run/node";
|
import type { LoaderFunctionArgs } from "@remix-run/node";
|
||||||
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
|
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
|
||||||
import { Api } from "bknd";
|
import { Api, ClientProvider } from "bknd/client";
|
||||||
import { ClientProvider } from "bknd/ui";
|
|
||||||
|
|
||||||
declare module "@remix-run/server-runtime" {
|
declare module "@remix-run/server-runtime" {
|
||||||
export interface AppLoadContext {
|
export interface AppLoadContext {
|
||||||
|
|||||||
Reference in New Issue
Block a user