mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-02 16:16:02 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dedfb77884 | |||
| b5b4c5eef0 | |||
| 7af8e09468 | |||
| fd966b6aef | |||
| 6bed2e4fca | |||
| dfb1457dfa | |||
| 4f945842a9 | |||
| 44fdfcc8d9 | |||
| 143d6a55ff | |||
| 8fa905a8f1 | |||
| ad0d2e6ff8 | |||
| aa0e6f90d9 | |||
| bd48bb7a18 | |||
| a298b65abf | |||
| daaaae82b6 | |||
| 79ace4f1e5 | |||
| f19977ac28 | |||
| a3782728f9 | |||
| 8b832f02ac | |||
| cec32ae881 | |||
| 0fffa26d55 | |||
| 2b6f520f46 | |||
| 7379bf2b1b | |||
| db3c2cea10 |
+3
-1
@@ -31,4 +31,6 @@ packages/media/.env
|
|||||||
.git_old
|
.git_old
|
||||||
docker/tmp
|
docker/tmp
|
||||||
.debug
|
.debug
|
||||||
.history
|
.history
|
||||||
|
.aider*
|
||||||
|
.vercel
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[](https://npmjs.org/package/bknd)
|
[](https://npmjs.org/package/bknd)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<p align="center" width="100%">
|
<p align="center" width="100%">
|
||||||
<a href="https://stackblitz.com/github/bknd-io/bknd-examples?hideExplorer=1&embed=1&view=preview&startScript=example-admin-rich&initialPath=%2Fdata%2Fschema" target="_blank">
|
<a href="https://stackblitz.com/github/bknd-io/bknd-examples?hideExplorer=1&embed=1&view=preview&startScript=example-admin-rich&initialPath=%2Fdata%2Fschema" target="_blank">
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ beforeAll(disableConsoleLog);
|
|||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
|
|
||||||
describe("adapter", () => {
|
describe("adapter", () => {
|
||||||
it("makes config", () => {
|
it("makes config", async () => {
|
||||||
expect(omitKeys(adapter.makeConfig({}), ["connection"])).toEqual({});
|
expect(omitKeys(await adapter.makeConfig({}), ["connection"])).toEqual({});
|
||||||
expect(omitKeys(adapter.makeConfig({}, { env: { TEST: "test" } }), ["connection"])).toEqual(
|
expect(
|
||||||
{},
|
omitKeys(await adapter.makeConfig({}, { env: { TEST: "test" } }), ["connection"]),
|
||||||
);
|
).toEqual({});
|
||||||
|
|
||||||
// merges everything returned from `app` with the config
|
// merges everything returned from `app` with the config
|
||||||
expect(
|
expect(
|
||||||
omitKeys(
|
omitKeys(
|
||||||
adapter.makeConfig(
|
await adapter.makeConfig(
|
||||||
{ app: (a) => ({ initialConfig: { server: { cors: { origin: a.env.TEST } } } }) },
|
{ app: (a) => ({ initialConfig: { server: { cors: { origin: a.env.TEST } } } }) },
|
||||||
{ env: { TEST: "test" } },
|
{ env: { TEST: "test" } },
|
||||||
),
|
),
|
||||||
|
|||||||
+75
-74
@@ -1,6 +1,7 @@
|
|||||||
import { $ } from "bun";
|
import { $ } from "bun";
|
||||||
import * as tsup from "tsup";
|
import * as tsup from "tsup";
|
||||||
import pkg from "./package.json" with { type: "json" };
|
import pkg from "./package.json" with { type: "json" };
|
||||||
|
import c from "picocolors";
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const watch = args.includes("--watch");
|
const watch = args.includes("--watch");
|
||||||
@@ -9,6 +10,14 @@ const types = args.includes("--types");
|
|||||||
const sourcemap = args.includes("--sourcemap");
|
const sourcemap = args.includes("--sourcemap");
|
||||||
const clean = args.includes("--clean");
|
const clean = args.includes("--clean");
|
||||||
|
|
||||||
|
// silence tsup
|
||||||
|
const oldConsole = {
|
||||||
|
log: console.log,
|
||||||
|
warn: console.warn,
|
||||||
|
};
|
||||||
|
console.log = () => {};
|
||||||
|
console.warn = () => {};
|
||||||
|
|
||||||
const define = {
|
const define = {
|
||||||
__isDev: "0",
|
__isDev: "0",
|
||||||
__version: JSON.stringify(pkg.version),
|
__version: JSON.stringify(pkg.version),
|
||||||
@@ -27,11 +36,11 @@ function buildTypes() {
|
|||||||
Bun.spawn(["bun", "build:types"], {
|
Bun.spawn(["bun", "build:types"], {
|
||||||
stdout: "inherit",
|
stdout: "inherit",
|
||||||
onExit: () => {
|
onExit: () => {
|
||||||
console.info("Types built");
|
oldConsole.log(c.cyan("[Types]"), c.green("built"));
|
||||||
Bun.spawn(["bun", "tsc-alias"], {
|
Bun.spawn(["bun", "tsc-alias"], {
|
||||||
stdout: "inherit",
|
stdout: "inherit",
|
||||||
onExit: () => {
|
onExit: () => {
|
||||||
console.info("Types aliased");
|
oldConsole.log(c.cyan("[Types]"), c.green("aliased"));
|
||||||
types_running = false;
|
types_running = false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -39,6 +48,10 @@ function buildTypes() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (types && !watch) {
|
||||||
|
buildTypes();
|
||||||
|
}
|
||||||
|
|
||||||
let watcher_timeout: any;
|
let watcher_timeout: any;
|
||||||
function delayTypes() {
|
function delayTypes() {
|
||||||
if (!watch || !types) return;
|
if (!watch || !types) return;
|
||||||
@@ -48,17 +61,6 @@ function delayTypes() {
|
|||||||
watcher_timeout = setTimeout(buildTypes, 1000);
|
watcher_timeout = setTimeout(buildTypes, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types && !watch) {
|
|
||||||
buildTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
function banner(title: string) {
|
|
||||||
console.info("");
|
|
||||||
console.info("=".repeat(40));
|
|
||||||
console.info(title.toUpperCase());
|
|
||||||
console.info("-".repeat(40));
|
|
||||||
}
|
|
||||||
|
|
||||||
// collection of always-external packages
|
// collection of always-external packages
|
||||||
const external = [
|
const external = [
|
||||||
"bun:test",
|
"bun:test",
|
||||||
@@ -73,7 +75,6 @@ const external = [
|
|||||||
* Building backend and general API
|
* Building backend and general API
|
||||||
*/
|
*/
|
||||||
async function buildApi() {
|
async function buildApi() {
|
||||||
banner("Building API");
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
minify,
|
minify,
|
||||||
sourcemap,
|
sourcemap,
|
||||||
@@ -92,6 +93,7 @@ async function buildApi() {
|
|||||||
},
|
},
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
delayTypes();
|
delayTypes();
|
||||||
|
oldConsole.log(c.cyan("[API]"), c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -135,7 +137,6 @@ async function buildUi() {
|
|||||||
},
|
},
|
||||||
} satisfies tsup.Options;
|
} satisfies tsup.Options;
|
||||||
|
|
||||||
banner("Building UI");
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
...base,
|
...base,
|
||||||
entry: ["src/ui/index.ts", "src/ui/main.css", "src/ui/styles.css"],
|
entry: ["src/ui/index.ts", "src/ui/main.css", "src/ui/styles.css"],
|
||||||
@@ -143,10 +144,10 @@ async function buildUi() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await rewriteClient("./dist/ui/index.js");
|
await rewriteClient("./dist/ui/index.js");
|
||||||
delayTypes();
|
delayTypes();
|
||||||
|
oldConsole.log(c.cyan("[UI]"), c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
banner("Building Client");
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
...base,
|
...base,
|
||||||
entry: ["src/ui/client/index.ts"],
|
entry: ["src/ui/client/index.ts"],
|
||||||
@@ -154,6 +155,7 @@ async function buildUi() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await rewriteClient("./dist/ui/client/index.js");
|
await rewriteClient("./dist/ui/client/index.js");
|
||||||
delayTypes();
|
delayTypes();
|
||||||
|
oldConsole.log(c.cyan("[UI]"), "Client", c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -164,7 +166,6 @@ async function buildUi() {
|
|||||||
* - ui/client is external, and after built replaced with "bknd/client"
|
* - ui/client is external, and after built replaced with "bknd/client"
|
||||||
*/
|
*/
|
||||||
async function buildUiElements() {
|
async function buildUiElements() {
|
||||||
banner("Building UI Elements");
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
minify,
|
minify,
|
||||||
sourcemap,
|
sourcemap,
|
||||||
@@ -198,6 +199,7 @@ async function buildUiElements() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await rewriteClient("./dist/ui/elements/index.js");
|
await rewriteClient("./dist/ui/elements/index.js");
|
||||||
delayTypes();
|
delayTypes();
|
||||||
|
oldConsole.log(c.cyan("[UI]"), "Elements", c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -218,6 +220,7 @@ function baseConfig(adapter: string, overrides: Partial<tsup.Options> = {}): tsu
|
|||||||
splitting: false,
|
splitting: false,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
delayTypes();
|
delayTypes();
|
||||||
|
oldConsole.log(c.cyan("[Adapter]"), adapter || "base", c.green("built"));
|
||||||
},
|
},
|
||||||
...overrides,
|
...overrides,
|
||||||
define: {
|
define: {
|
||||||
@@ -236,65 +239,63 @@ function baseConfig(adapter: string, overrides: Partial<tsup.Options> = {}): tsu
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function buildAdapters() {
|
async function buildAdapters() {
|
||||||
banner("Building Adapters");
|
await Promise.all([
|
||||||
// base adapter handles
|
// base adapter handles
|
||||||
await tsup.build({
|
tsup.build({
|
||||||
...baseConfig(""),
|
...baseConfig(""),
|
||||||
entry: ["src/adapter/index.ts"],
|
entry: ["src/adapter/index.ts"],
|
||||||
outDir: "dist/adapter",
|
outDir: "dist/adapter",
|
||||||
});
|
}),
|
||||||
|
|
||||||
// specific adatpers
|
// specific adatpers
|
||||||
await tsup.build(baseConfig("react-router"));
|
tsup.build(baseConfig("react-router")),
|
||||||
await tsup.build(
|
tsup.build(
|
||||||
baseConfig("bun", {
|
baseConfig("bun", {
|
||||||
|
external: [/^bun\:.*/],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
tsup.build(baseConfig("astro")),
|
||||||
|
tsup.build(baseConfig("aws")),
|
||||||
|
tsup.build(baseConfig("cloudflare")),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("vite"),
|
||||||
|
platform: "node",
|
||||||
|
}),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("nextjs"),
|
||||||
|
platform: "node",
|
||||||
|
}),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("node"),
|
||||||
|
platform: "node",
|
||||||
|
}),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("sqlite/edge"),
|
||||||
|
entry: ["src/adapter/sqlite/edge.ts"],
|
||||||
|
outDir: "dist/adapter/sqlite",
|
||||||
|
metafile: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("sqlite/node"),
|
||||||
|
entry: ["src/adapter/sqlite/node.ts"],
|
||||||
|
outDir: "dist/adapter/sqlite",
|
||||||
|
platform: "node",
|
||||||
|
metafile: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("sqlite/bun"),
|
||||||
|
entry: ["src/adapter/sqlite/bun.ts"],
|
||||||
|
outDir: "dist/adapter/sqlite",
|
||||||
|
metafile: false,
|
||||||
external: [/^bun\:.*/],
|
external: [/^bun\:.*/],
|
||||||
}),
|
}),
|
||||||
);
|
]);
|
||||||
await tsup.build(baseConfig("astro"));
|
|
||||||
await tsup.build(baseConfig("aws"));
|
|
||||||
await tsup.build(baseConfig("cloudflare"));
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("vite"),
|
|
||||||
platform: "node",
|
|
||||||
});
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("nextjs"),
|
|
||||||
platform: "node",
|
|
||||||
});
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("node"),
|
|
||||||
platform: "node",
|
|
||||||
});
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("sqlite/edge"),
|
|
||||||
entry: ["src/adapter/sqlite/edge.ts"],
|
|
||||||
outDir: "dist/adapter/sqlite",
|
|
||||||
metafile: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("sqlite/node"),
|
|
||||||
entry: ["src/adapter/sqlite/node.ts"],
|
|
||||||
outDir: "dist/adapter/sqlite",
|
|
||||||
platform: "node",
|
|
||||||
metafile: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
await tsup.build({
|
|
||||||
...baseConfig("sqlite/bun"),
|
|
||||||
entry: ["src/adapter/sqlite/bun.ts"],
|
|
||||||
outDir: "dist/adapter/sqlite",
|
|
||||||
metafile: false,
|
|
||||||
external: [/^bun\:.*/],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await buildApi();
|
await Promise.all([buildApi(), buildUi(), buildUiElements(), buildAdapters()]);
|
||||||
await buildUi();
|
|
||||||
await buildUiElements();
|
|
||||||
await buildAdapters();
|
|
||||||
|
|||||||
+4
-3
@@ -3,7 +3,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"version": "0.16.0-rc.0",
|
"version": "0.16.1",
|
||||||
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
|
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
|
||||||
"homepage": "https://bknd.io",
|
"homepage": "https://bknd.io",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -64,7 +64,8 @@
|
|||||||
"hono": "4.8.3",
|
"hono": "4.8.3",
|
||||||
"json-schema-library": "10.0.0-rc7",
|
"json-schema-library": "10.0.0-rc7",
|
||||||
"json-schema-to-ts": "^3.1.1",
|
"json-schema-to-ts": "^3.1.1",
|
||||||
"kysely": "^0.27.6",
|
"jsonv-ts": "0.3.2",
|
||||||
|
"kysely": "0.27.6",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"oauth4webapi": "^2.11.1",
|
"oauth4webapi": "^2.11.1",
|
||||||
"object-path-immutable": "^4.1.2",
|
"object-path-immutable": "^4.1.2",
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.758.0",
|
"@aws-sdk/client-s3": "^3.758.0",
|
||||||
"@bluwy/giget-core": "^0.1.2",
|
"@bluwy/giget-core": "^0.1.2",
|
||||||
|
"@clack/prompts": "^0.11.0",
|
||||||
"@cloudflare/vitest-pool-workers": "^0.8.38",
|
"@cloudflare/vitest-pool-workers": "^0.8.38",
|
||||||
"@cloudflare/workers-types": "^4.20250606.0",
|
"@cloudflare/workers-types": "^4.20250606.0",
|
||||||
"@dagrejs/dagre": "^1.1.4",
|
"@dagrejs/dagre": "^1.1.4",
|
||||||
@@ -100,7 +102,6 @@
|
|||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"jotai": "^2.12.2",
|
"jotai": "^2.12.2",
|
||||||
"jsdom": "^26.0.0",
|
"jsdom": "^26.0.0",
|
||||||
"jsonv-ts": "^0.3.2",
|
|
||||||
"kysely-d1": "^0.3.0",
|
"kysely-d1": "^0.3.0",
|
||||||
"kysely-generic-sqlite": "^1.2.1",
|
"kysely-generic-sqlite": "^1.2.1",
|
||||||
"libsql-stateless-easy": "^1.8.0",
|
"libsql-stateless-easy": "^1.8.0",
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ export class AppConfigUpdatedEvent extends AppEvent<{
|
|||||||
}> {
|
}> {
|
||||||
static override slug = "app-config-updated";
|
static override slug = "app-config-updated";
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @type {Event<{ app: App }>}
|
||||||
|
*/
|
||||||
export class AppBuiltEvent extends AppEvent {
|
export class AppBuiltEvent extends AppEvent {
|
||||||
static override slug = "app-built";
|
static override slug = "app-built";
|
||||||
}
|
}
|
||||||
@@ -71,6 +74,9 @@ export type AppOptions = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type CreateAppConfig = {
|
export type CreateAppConfig = {
|
||||||
|
/**
|
||||||
|
* bla
|
||||||
|
*/
|
||||||
connection?: Connection | { url: string };
|
connection?: Connection | { url: string };
|
||||||
initialConfig?: InitialModuleConfigs;
|
initialConfig?: InitialModuleConfigs;
|
||||||
options?: AppOptions;
|
options?: AppOptions;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe("cf adapter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("makes config", async () => {
|
it("makes config", async () => {
|
||||||
const staticConfig = makeConfig(
|
const staticConfig = await makeConfig(
|
||||||
{
|
{
|
||||||
connection: { url: DB_URL },
|
connection: { url: DB_URL },
|
||||||
initialConfig: { data: { basepath: DB_URL } },
|
initialConfig: { data: { basepath: DB_URL } },
|
||||||
@@ -28,7 +28,7 @@ describe("cf adapter", () => {
|
|||||||
expect(staticConfig.initialConfig).toEqual({ data: { basepath: DB_URL } });
|
expect(staticConfig.initialConfig).toEqual({ data: { basepath: DB_URL } });
|
||||||
expect(staticConfig.connection).toBeDefined();
|
expect(staticConfig.connection).toBeDefined();
|
||||||
|
|
||||||
const dynamicConfig = makeConfig(
|
const dynamicConfig = await makeConfig(
|
||||||
{
|
{
|
||||||
app: (env) => ({
|
app: (env) => ({
|
||||||
initialConfig: { data: { basepath: env.DB_URL } },
|
initialConfig: { data: { basepath: env.DB_URL } },
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { Hono } from "hono";
|
|||||||
import { serveStatic } from "hono/cloudflare-workers";
|
import { serveStatic } from "hono/cloudflare-workers";
|
||||||
import { getFresh } from "./modes/fresh";
|
import { getFresh } from "./modes/fresh";
|
||||||
import { getCached } from "./modes/cached";
|
import { getCached } from "./modes/cached";
|
||||||
import { getDurable } from "./modes/durable";
|
|
||||||
import type { App } from "bknd";
|
import type { App } from "bknd";
|
||||||
import { $console } from "core/utils";
|
import { $console } from "core/utils";
|
||||||
|
|
||||||
@@ -17,10 +16,9 @@ declare global {
|
|||||||
|
|
||||||
export type CloudflareEnv = Cloudflare.Env;
|
export type CloudflareEnv = Cloudflare.Env;
|
||||||
export type CloudflareBkndConfig<Env = CloudflareEnv> = RuntimeBkndConfig<Env> & {
|
export type CloudflareBkndConfig<Env = CloudflareEnv> = RuntimeBkndConfig<Env> & {
|
||||||
mode?: "warm" | "fresh" | "cache" | "durable";
|
mode?: "warm" | "fresh" | "cache";
|
||||||
bindings?: (args: Env) => {
|
bindings?: (args: Env) => {
|
||||||
kv?: KVNamespace;
|
kv?: KVNamespace;
|
||||||
dobj?: DurableObjectNamespace;
|
|
||||||
db?: D1Database;
|
db?: D1Database;
|
||||||
};
|
};
|
||||||
d1?: {
|
d1?: {
|
||||||
@@ -93,8 +91,6 @@ export function serve<Env extends CloudflareEnv = CloudflareEnv>(
|
|||||||
case "cache":
|
case "cache":
|
||||||
app = await getCached(config, context);
|
app = await getCached(config, context);
|
||||||
break;
|
break;
|
||||||
case "durable":
|
|
||||||
return await getDurable(config, context);
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown mode ${mode}`);
|
throw new Error(`Unknown mode ${mode}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export function d1SessionHelper(config: CloudflareBkndConfig<any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let media_registered: boolean = false;
|
let media_registered: boolean = false;
|
||||||
export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
export async function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
||||||
config: CloudflareBkndConfig<Env>,
|
config: CloudflareBkndConfig<Env>,
|
||||||
args?: CfMakeConfigArgs<Env>,
|
args?: CfMakeConfigArgs<Env>,
|
||||||
) {
|
) {
|
||||||
@@ -102,7 +102,7 @@ export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
|||||||
media_registered = true;
|
media_registered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appConfig = makeAdapterConfig(config, args?.env);
|
const appConfig = await makeAdapterConfig(config, args?.env);
|
||||||
|
|
||||||
// if connection instance is given, don't do anything
|
// if connection instance is given, don't do anything
|
||||||
// other than checking if D1 session is defined
|
// other than checking if D1 session is defined
|
||||||
@@ -115,7 +115,7 @@ export function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
|||||||
}
|
}
|
||||||
// if connection is given, try to open with unified sqlite adapter
|
// if connection is given, try to open with unified sqlite adapter
|
||||||
} else if (appConfig.connection) {
|
} else if (appConfig.connection) {
|
||||||
appConfig.connection = sqlite(appConfig.connection);
|
appConfig.connection = sqlite(appConfig.connection) as any;
|
||||||
|
|
||||||
// if connection is not given, but env is set
|
// if connection is not given, but env is set
|
||||||
// try to make D1 from bindings
|
// try to make D1 from bindings
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { d1Sqlite, type D1ConnectionConfig } from "./connection/D1Connection";
|
|||||||
export * from "./cloudflare-workers.adapter";
|
export * from "./cloudflare-workers.adapter";
|
||||||
export { makeApp, getFresh } from "./modes/fresh";
|
export { makeApp, getFresh } from "./modes/fresh";
|
||||||
export { getCached } from "./modes/cached";
|
export { getCached } from "./modes/cached";
|
||||||
export { DurableBkndApp, getDurable } from "./modes/durable";
|
|
||||||
export { d1Sqlite, type D1ConnectionConfig };
|
export { d1Sqlite, type D1ConnectionConfig };
|
||||||
export {
|
export {
|
||||||
getBinding,
|
getBinding,
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
import { DurableObject } from "cloudflare:workers";
|
|
||||||
import type { App, CreateAppConfig } from "bknd";
|
|
||||||
import { createRuntimeApp, makeConfig } from "bknd/adapter";
|
|
||||||
import type { CloudflareBkndConfig, Context, CloudflareEnv } from "../index";
|
|
||||||
import { constants, registerAsyncsExecutionContext } from "../config";
|
|
||||||
import { $console } from "core/utils";
|
|
||||||
|
|
||||||
export async function getDurable<Env extends CloudflareEnv = CloudflareEnv>(
|
|
||||||
config: CloudflareBkndConfig<Env>,
|
|
||||||
ctx: Context<Env>,
|
|
||||||
) {
|
|
||||||
const { dobj } = config.bindings?.(ctx.env)!;
|
|
||||||
if (!dobj) throw new Error("durable object is not defined in cloudflare.bindings");
|
|
||||||
const key = config.key ?? "app";
|
|
||||||
|
|
||||||
if ([config.onBuilt, config.beforeBuild].some((x) => x)) {
|
|
||||||
$console.warn("onBuilt and beforeBuild are not supported with DurableObject mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = performance.now();
|
|
||||||
|
|
||||||
const id = dobj.idFromName(key);
|
|
||||||
const stub = dobj.get(id) as unknown as DurableBkndApp;
|
|
||||||
|
|
||||||
const create_config = makeConfig(config, ctx.env);
|
|
||||||
|
|
||||||
const res = await stub.fire(ctx.request, {
|
|
||||||
config: create_config,
|
|
||||||
keepAliveSeconds: config.keepAliveSeconds,
|
|
||||||
});
|
|
||||||
|
|
||||||
const headers = new Headers(res.headers);
|
|
||||||
headers.set("X-TTDO", String(performance.now() - start));
|
|
||||||
|
|
||||||
return new Response(res.body, {
|
|
||||||
status: res.status,
|
|
||||||
statusText: res.statusText,
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DurableBkndApp extends DurableObject {
|
|
||||||
protected id = Math.random().toString(36).slice(2);
|
|
||||||
protected app?: App;
|
|
||||||
protected interval?: any;
|
|
||||||
|
|
||||||
async fire(
|
|
||||||
request: Request,
|
|
||||||
options: {
|
|
||||||
config: CreateAppConfig;
|
|
||||||
html?: string;
|
|
||||||
keepAliveSeconds?: number;
|
|
||||||
setAdminHtml?: boolean;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
let buildtime = 0;
|
|
||||||
if (!this.app) {
|
|
||||||
const start = performance.now();
|
|
||||||
const config = options.config;
|
|
||||||
|
|
||||||
// change protocol to websocket if libsql
|
|
||||||
if (
|
|
||||||
config?.connection &&
|
|
||||||
"type" in config.connection &&
|
|
||||||
config.connection.type === "libsql"
|
|
||||||
) {
|
|
||||||
//config.connection.config.protocol = "wss";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.app = await createRuntimeApp({
|
|
||||||
...config,
|
|
||||||
onBuilt: async (app) => {
|
|
||||||
registerAsyncsExecutionContext(app, this.ctx);
|
|
||||||
app.modules.server.get(constants.do_endpoint, async (c) => {
|
|
||||||
// @ts-ignore
|
|
||||||
const context: any = c.req.raw.cf ? c.req.raw.cf : c.env.cf;
|
|
||||||
return c.json({
|
|
||||||
id: this.id,
|
|
||||||
keepAliveSeconds: options?.keepAliveSeconds ?? 0,
|
|
||||||
colo: context.colo,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.onBuilt(app);
|
|
||||||
},
|
|
||||||
adminOptions: { html: options.html },
|
|
||||||
beforeBuild: async (app) => {
|
|
||||||
await this.beforeBuild(app);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
buildtime = performance.now() - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options?.keepAliveSeconds) {
|
|
||||||
this.keepAlive(options.keepAliveSeconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await this.app!.fetch(request);
|
|
||||||
const headers = new Headers(res.headers);
|
|
||||||
headers.set("X-BuildTime", buildtime.toString());
|
|
||||||
headers.set("X-DO-ID", this.id);
|
|
||||||
|
|
||||||
return new Response(res.body, {
|
|
||||||
status: res.status,
|
|
||||||
statusText: res.statusText,
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async onBuilt(app: App) {}
|
|
||||||
|
|
||||||
async beforeBuild(app: App) {}
|
|
||||||
|
|
||||||
protected keepAlive(seconds: number) {
|
|
||||||
if (this.interval) {
|
|
||||||
clearInterval(this.interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
this.interval = setInterval(() => {
|
|
||||||
i += 1;
|
|
||||||
if (i === seconds) {
|
|
||||||
console.log("cleared");
|
|
||||||
clearInterval(this.interval);
|
|
||||||
|
|
||||||
// ping every 30 seconds
|
|
||||||
} else if (i % 30 === 0) {
|
|
||||||
console.log("ping");
|
|
||||||
this.app?.modules.ctx().connection.ping();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ export async function makeApp<Env extends CloudflareEnv = CloudflareEnv>(
|
|||||||
args?: CfMakeConfigArgs<Env>,
|
args?: CfMakeConfigArgs<Env>,
|
||||||
opts?: RuntimeOptions,
|
opts?: RuntimeOptions,
|
||||||
) {
|
) {
|
||||||
return await createRuntimeApp<Env>(makeConfig(config, args), args?.env, opts);
|
return await createRuntimeApp<Env>(await makeConfig(config, args), args?.env, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFresh<Env extends CloudflareEnv = CloudflareEnv>(
|
export async function getFresh<Env extends CloudflareEnv = CloudflareEnv>(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { registries, isDebug, guessMimeType } from "bknd";
|
import { registries as $registries, isDebug, guessMimeType } from "bknd";
|
||||||
import { getBindings } from "../bindings";
|
import { getBindings } from "../bindings";
|
||||||
import { s } from "bknd/utils";
|
import { s } from "bknd/utils";
|
||||||
import { StorageAdapter, type FileBody } from "bknd";
|
import { StorageAdapter, type FileBody } from "bknd";
|
||||||
@@ -12,7 +12,10 @@ export function makeSchema(bindings: string[] = []) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerMedia(env: Record<string, any>) {
|
export function registerMedia(
|
||||||
|
env: Record<string, any>,
|
||||||
|
registries: typeof $registries = $registries,
|
||||||
|
) {
|
||||||
const r2_bindings = getBindings(env, "R2Bucket");
|
const r2_bindings = getBindings(env, "R2Bucket");
|
||||||
|
|
||||||
registries.media.register(
|
registries.media.register(
|
||||||
|
|||||||
+19
-12
@@ -1,13 +1,21 @@
|
|||||||
import { config as $config, App, type CreateAppConfig, Connection, guessMimeType } from "bknd";
|
import {
|
||||||
|
config as $config,
|
||||||
|
App,
|
||||||
|
type CreateAppConfig,
|
||||||
|
Connection,
|
||||||
|
guessMimeType,
|
||||||
|
type MaybePromise,
|
||||||
|
registries as $registries,
|
||||||
|
} from "bknd";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "bknd/utils";
|
||||||
import type { Context, MiddlewareHandler, Next } from "hono";
|
import type { Context, MiddlewareHandler, Next } from "hono";
|
||||||
import type { AdminControllerOptions } from "modules/server/AdminController";
|
import type { AdminControllerOptions } from "modules/server/AdminController";
|
||||||
import type { Manifest } from "vite";
|
import type { Manifest } from "vite";
|
||||||
|
|
||||||
export type BkndConfig<Args = any> = CreateAppConfig & {
|
export type BkndConfig<Args = any> = CreateAppConfig & {
|
||||||
app?: CreateAppConfig | ((args: Args) => CreateAppConfig);
|
app?: CreateAppConfig | ((args: Args) => MaybePromise<CreateAppConfig>);
|
||||||
onBuilt?: (app: App) => Promise<void>;
|
onBuilt?: (app: App) => Promise<void>;
|
||||||
beforeBuild?: (app: App) => Promise<void>;
|
beforeBuild?: (app: App, registries?: typeof $registries) => Promise<void>;
|
||||||
buildConfig?: Parameters<App["build"]>[0];
|
buildConfig?: Parameters<App["build"]>[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,10 +38,10 @@ export type DefaultArgs = {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function makeConfig<Args = DefaultArgs>(
|
export async function makeConfig<Args = DefaultArgs>(
|
||||||
config: BkndConfig<Args>,
|
config: BkndConfig<Args>,
|
||||||
args?: Args,
|
args?: Args,
|
||||||
): CreateAppConfig {
|
): Promise<CreateAppConfig> {
|
||||||
let additionalConfig: CreateAppConfig = {};
|
let additionalConfig: CreateAppConfig = {};
|
||||||
const { app, ...rest } = config;
|
const { app, ...rest } = config;
|
||||||
if (app) {
|
if (app) {
|
||||||
@@ -41,7 +49,7 @@ export function makeConfig<Args = DefaultArgs>(
|
|||||||
if (!args) {
|
if (!args) {
|
||||||
throw new Error("args is required when config.app is a function");
|
throw new Error("args is required when config.app is a function");
|
||||||
}
|
}
|
||||||
additionalConfig = app(args);
|
additionalConfig = await app(args);
|
||||||
} else {
|
} else {
|
||||||
additionalConfig = app;
|
additionalConfig = app;
|
||||||
}
|
}
|
||||||
@@ -60,7 +68,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
|
|||||||
const id = opts?.id ?? "app";
|
const id = opts?.id ?? "app";
|
||||||
let app = apps.get(id);
|
let app = apps.get(id);
|
||||||
if (!app || opts?.force) {
|
if (!app || opts?.force) {
|
||||||
const appConfig = makeConfig(config, args);
|
const appConfig = await makeConfig(config, args);
|
||||||
if (!appConfig.connection || !Connection.isConnection(appConfig.connection)) {
|
if (!appConfig.connection || !Connection.isConnection(appConfig.connection)) {
|
||||||
let connection: Connection | undefined;
|
let connection: Connection | undefined;
|
||||||
if (Connection.isConnection(config.connection)) {
|
if (Connection.isConnection(config.connection)) {
|
||||||
@@ -68,7 +76,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
|
|||||||
} else {
|
} else {
|
||||||
const sqlite = (await import("bknd/adapter/sqlite")).sqlite;
|
const sqlite = (await import("bknd/adapter/sqlite")).sqlite;
|
||||||
const conf = appConfig.connection ?? { url: ":memory:" };
|
const conf = appConfig.connection ?? { url: ":memory:" };
|
||||||
connection = sqlite(conf);
|
connection = sqlite(conf) as any;
|
||||||
$console.info(`Using ${connection!.name} connection`, conf.url);
|
$console.info(`Using ${connection!.name} connection`, conf.url);
|
||||||
}
|
}
|
||||||
appConfig.connection = connection;
|
appConfig.connection = connection;
|
||||||
@@ -98,7 +106,7 @@ export async function createFrameworkApp<Args = DefaultArgs>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await config.beforeBuild?.(app);
|
await config.beforeBuild?.(app, $registries);
|
||||||
await app.build(config.buildConfig);
|
await app.build(config.buildConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +139,7 @@ export async function createRuntimeApp<Args = DefaultArgs>(
|
|||||||
"sync",
|
"sync",
|
||||||
);
|
);
|
||||||
|
|
||||||
await config.beforeBuild?.(app);
|
await config.beforeBuild?.(app, $registries);
|
||||||
await app.build(config.buildConfig);
|
await app.build(config.buildConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,8 +176,7 @@ export function serveStaticViaImport(opts?: { manifest?: Manifest }) {
|
|||||||
const path = c.req.path.substring(1);
|
const path = c.req.path.substring(1);
|
||||||
if (files.includes(path)) {
|
if (files.includes(path)) {
|
||||||
try {
|
try {
|
||||||
const content = await import(`bknd/static/${path}?raw`, {
|
const content = await import(/* @vite-ignore */ `bknd/static/${path}?raw`, {
|
||||||
/* @vite-ignore */
|
|
||||||
assert: { type: "text" },
|
assert: { type: "text" },
|
||||||
}).then((m) => m.default);
|
}).then((m) => m.default);
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ async function makeApp(config: MakeAppConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function makeConfigApp(_config: CliBkndConfig, platform?: Platform) {
|
export async function makeConfigApp(_config: CliBkndConfig, platform?: Platform) {
|
||||||
const config = makeConfig(_config, process.env);
|
const config = await makeConfig(_config, process.env);
|
||||||
return makeApp({
|
return makeApp({
|
||||||
...config,
|
...config,
|
||||||
server: { platform },
|
server: { platform },
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class SchemaObject<Schema extends TSchema = TSchema> {
|
|||||||
this._value = deepFreeze(
|
this._value = deepFreeze(
|
||||||
parse(_schema, structuredClone(initial ?? {}), {
|
parse(_schema, structuredClone(initial ?? {}), {
|
||||||
withDefaults: true,
|
withDefaults: true,
|
||||||
withExtendedDefaults: true,
|
//withExtendedDefaults: true,
|
||||||
forceParse: this.isForceParse(),
|
forceParse: this.isForceParse(),
|
||||||
skipMark: this.isForceParse(),
|
skipMark: this.isForceParse(),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -256,12 +256,10 @@ export class DataController extends Controller {
|
|||||||
// read many
|
// read many
|
||||||
const saveRepoQuery = s
|
const saveRepoQuery = s
|
||||||
.object({
|
.object({
|
||||||
...omitKeys(repoQuery.properties, ["with", "where"]),
|
...omitKeys(repoQuery.properties, ["with"]),
|
||||||
sort: s.string({ default: "id" }),
|
sort: s.string({ default: "id" }),
|
||||||
select: s.array(s.string()),
|
select: s.array(s.string()),
|
||||||
join: s.array(s.string()),
|
join: s.array(s.string()),
|
||||||
with: s.anyOf([s.array(s.string()), s.record(s.object({}))]),
|
|
||||||
where: s.object({}),
|
|
||||||
})
|
})
|
||||||
.partial();
|
.partial();
|
||||||
const saveRepoQueryParams = (pick: string[] = Object.keys(repoQuery.properties)) => [
|
const saveRepoQueryParams = (pick: string[] = Object.keys(repoQuery.properties)) => [
|
||||||
@@ -275,15 +273,7 @@ export class DataController extends Controller {
|
|||||||
"/:entity",
|
"/:entity",
|
||||||
describeRoute({
|
describeRoute({
|
||||||
summary: "Read many",
|
summary: "Read many",
|
||||||
parameters: saveRepoQueryParams([
|
parameters: saveRepoQueryParams(["limit", "offset", "sort", "select", "join"]),
|
||||||
"limit",
|
|
||||||
"offset",
|
|
||||||
"sort",
|
|
||||||
"select",
|
|
||||||
"join",
|
|
||||||
"with",
|
|
||||||
"where",
|
|
||||||
]),
|
|
||||||
tags: ["data"],
|
tags: ["data"],
|
||||||
}),
|
}),
|
||||||
permission(DataPermissions.entityRead),
|
permission(DataPermissions.entityRead),
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export class EntityTypescript {
|
|||||||
const strings: string[] = [];
|
const strings: string[] = [];
|
||||||
const tables: Record<string, string> = {};
|
const tables: Record<string, string> = {};
|
||||||
const imports: Record<string, string[]> = {
|
const imports: Record<string, string[]> = {
|
||||||
"bknd/core": ["DB"],
|
bknd: ["DB"],
|
||||||
kysely: ["Insertable", "Selectable", "Updateable", "Generated"],
|
kysely: ["Insertable", "Selectable", "Updateable", "Generated"],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ export class EntityTypescript {
|
|||||||
strings.push(tables_string);
|
strings.push(tables_string);
|
||||||
|
|
||||||
// merge
|
// merge
|
||||||
let merge = `declare module "bknd/core" {\n`;
|
let merge = `declare module "bknd" {\n`;
|
||||||
for (const systemEntity of system_entities) {
|
for (const systemEntity of system_entities) {
|
||||||
const system_fields = Object.keys(systemEntities[systemEntity.name]);
|
const system_fields = Object.keys(systemEntities[systemEntity.name]);
|
||||||
const additional_fields = systemEntity.fields
|
const additional_fields = systemEntity.fields
|
||||||
|
|||||||
+8
-2
@@ -39,6 +39,7 @@ export { registries } from "modules/registries";
|
|||||||
/**
|
/**
|
||||||
* Core
|
* Core
|
||||||
*/
|
*/
|
||||||
|
export type { MaybePromise } from "core/types";
|
||||||
export { Exception, BkndError } from "core/errors";
|
export { Exception, BkndError } from "core/errors";
|
||||||
export { isDebug, env } from "core/env";
|
export { isDebug, env } from "core/env";
|
||||||
export { type PrimaryFieldType, config, type DB, type AppEntity } from "core/config";
|
export { type PrimaryFieldType, config, type DB, type AppEntity } from "core/config";
|
||||||
@@ -77,7 +78,10 @@ export * as AuthPermissions from "auth/auth-permissions";
|
|||||||
* Media
|
* Media
|
||||||
*/
|
*/
|
||||||
export { getExtensionFromName, getRandomizedFilename } from "media/utils";
|
export { getExtensionFromName, getRandomizedFilename } from "media/utils";
|
||||||
export * as StorageEvents from "media/storage/events";
|
import * as StorageEvents from "media/storage/events";
|
||||||
|
export const MediaEvents = {
|
||||||
|
...StorageEvents,
|
||||||
|
};
|
||||||
export * as MediaPermissions from "media/media-permissions";
|
export * as MediaPermissions from "media/media-permissions";
|
||||||
export type { FileUploadedEventData } from "media/storage/events";
|
export type { FileUploadedEventData } from "media/storage/events";
|
||||||
export { guess as guessMimeType } from "media/storage/mime-types-tiny";
|
export { guess as guessMimeType } from "media/storage/mime-types-tiny";
|
||||||
@@ -90,12 +94,14 @@ export {
|
|||||||
type FileUploadPayload,
|
type FileUploadPayload,
|
||||||
} from "media/storage/Storage";
|
} from "media/storage/Storage";
|
||||||
export { StorageAdapter } from "media/storage/StorageAdapter";
|
export { StorageAdapter } from "media/storage/StorageAdapter";
|
||||||
|
export { StorageS3Adapter } from "media/storage/adapters/s3/StorageS3Adapter";
|
||||||
|
export { StorageCloudinaryAdapter } from "media/storage/adapters/cloudinary/StorageCloudinaryAdapter";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data
|
* Data
|
||||||
*/
|
*/
|
||||||
import { MutatorEvents, RepositoryEvents } from "data/events";
|
import { MutatorEvents, RepositoryEvents } from "data/events";
|
||||||
export const DataEvents = { ...MutatorEvents, ...RepositoryEvents };
|
export const DatabaseEvents = { ...MutatorEvents, ...RepositoryEvents };
|
||||||
export type {
|
export type {
|
||||||
RepoQuery,
|
RepoQuery,
|
||||||
RepoQueryIn,
|
RepoQueryIn,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export class MediaApi extends ModuleApi<MediaApiOptions> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected uploadFile(
|
protected uploadFile(
|
||||||
body: File | Blob | ReadableStream,
|
body: File | Blob | ReadableStream | Buffer<ArrayBufferLike>,
|
||||||
opts?: {
|
opts?: {
|
||||||
filename?: string;
|
filename?: string;
|
||||||
path?: TInput;
|
path?: TInput;
|
||||||
@@ -110,7 +110,7 @@ export class MediaApi extends ModuleApi<MediaApiOptions> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async upload(
|
async upload(
|
||||||
item: Request | Response | string | File | Blob | ReadableStream,
|
item: Request | Response | string | File | Blob | ReadableStream | Buffer<ArrayBufferLike>,
|
||||||
opts: {
|
opts: {
|
||||||
filename?: string;
|
filename?: string;
|
||||||
_init?: Omit<RequestInit, "body">;
|
_init?: Omit<RequestInit, "body">;
|
||||||
@@ -148,7 +148,7 @@ export class MediaApi extends ModuleApi<MediaApiOptions> {
|
|||||||
entity: string,
|
entity: string,
|
||||||
id: PrimaryFieldType,
|
id: PrimaryFieldType,
|
||||||
field: string,
|
field: string,
|
||||||
item: Request | Response | string | File | ReadableStream,
|
item: Request | Response | string | File | ReadableStream | Buffer<ArrayBufferLike>,
|
||||||
opts?: {
|
opts?: {
|
||||||
_init?: Omit<RequestInit, "body">;
|
_init?: Omit<RequestInit, "body">;
|
||||||
fetcher?: typeof fetch;
|
fetcher?: typeof fetch;
|
||||||
|
|||||||
@@ -183,13 +183,13 @@ export class StorageS3Adapter extends StorageAdapter {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
headers: pickHeaders2(headers, [
|
headers: pickHeaders2(headers, [
|
||||||
"if-none-match",
|
"if-none-match",
|
||||||
"accept-encoding",
|
//"accept-encoding", (causes 403 on r2)
|
||||||
"accept",
|
"accept",
|
||||||
"if-modified-since",
|
"if-modified-since",
|
||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Response has to be copied, because of middlewares that might set headers
|
// response has to be copied, because of middlewares that might set headers
|
||||||
return new Response(res.body, {
|
return new Response(res.body, {
|
||||||
status: res.status,
|
status: res.status,
|
||||||
statusText: res.statusText,
|
statusText: res.statusText,
|
||||||
|
|||||||
@@ -662,7 +662,7 @@ export class ModuleManager {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$console.error(`[Safe Mutate] failed "${name}":`, String(e));
|
$console.error(`[Safe Mutate] failed "${name}":`, e);
|
||||||
|
|
||||||
// revert to previous config & rebuild using original listener
|
// revert to previous config & rebuild using original listener
|
||||||
this.revertModules();
|
this.revertModules();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export type DropzoneRenderProps = {
|
|||||||
uploadFile: (file: { path: string }) => Promise<void>;
|
uploadFile: (file: { path: string }) => Promise<void>;
|
||||||
deleteFile: (file: { path: string }) => Promise<void>;
|
deleteFile: (file: { path: string }) => Promise<void>;
|
||||||
openFileInput: () => void;
|
openFileInput: () => void;
|
||||||
|
addFiles: (files: (File | FileWithPath)[]) => void;
|
||||||
};
|
};
|
||||||
showPlaceholder: boolean;
|
showPlaceholder: boolean;
|
||||||
onClick?: (file: { path: string }) => void;
|
onClick?: (file: { path: string }) => void;
|
||||||
@@ -55,7 +56,8 @@ export type DropzoneProps = {
|
|||||||
autoUpload?: boolean;
|
autoUpload?: boolean;
|
||||||
onRejected?: (files: FileWithPath[]) => void;
|
onRejected?: (files: FileWithPath[]) => void;
|
||||||
onDeleted?: (file: { path: string }) => void;
|
onDeleted?: (file: { path: string }) => void;
|
||||||
onUploaded?: (files: FileStateWithData[]) => void;
|
onUploadedAll?: (files: FileStateWithData[]) => void;
|
||||||
|
onUploaded?: (file: FileStateWithData) => void;
|
||||||
onClick?: (file: FileState) => void;
|
onClick?: (file: FileState) => void;
|
||||||
placeholder?: {
|
placeholder?: {
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
@@ -86,6 +88,7 @@ export function Dropzone({
|
|||||||
placeholder,
|
placeholder,
|
||||||
onRejected,
|
onRejected,
|
||||||
onDeleted,
|
onDeleted,
|
||||||
|
onUploadedAll,
|
||||||
onUploaded,
|
onUploaded,
|
||||||
children,
|
children,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -123,8 +126,8 @@ export function Dropzone({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { handleFileInputChange, ref } = useDropzone({
|
const addFiles = useCallback(
|
||||||
onDropped: (newFiles: FileWithPath[]) => {
|
(newFiles: (File | FileWithPath)[]) => {
|
||||||
console.log("onDropped", newFiles);
|
console.log("onDropped", newFiles);
|
||||||
if (!isAllowed(newFiles)) return;
|
if (!isAllowed(newFiles)) return;
|
||||||
|
|
||||||
@@ -162,10 +165,10 @@ export function Dropzone({
|
|||||||
// prep new files
|
// prep new files
|
||||||
const currentPaths = _prev.map((f) => f.path);
|
const currentPaths = _prev.map((f) => f.path);
|
||||||
const filteredFiles: FileState[] = newFiles
|
const filteredFiles: FileState[] = newFiles
|
||||||
.filter((f) => f.path && !currentPaths.includes(f.path))
|
.filter((f) => !("path" in f) || (f.path && !currentPaths.includes(f.path)))
|
||||||
.map((f) => ({
|
.map((f) => ({
|
||||||
body: f,
|
body: f,
|
||||||
path: f.path!,
|
path: "path" in f ? f.path! : f.name,
|
||||||
name: f.name,
|
name: f.name,
|
||||||
size: f.size,
|
size: f.size,
|
||||||
type: f.type,
|
type: f.type,
|
||||||
@@ -184,6 +187,14 @@ export function Dropzone({
|
|||||||
return updatedFiles;
|
return updatedFiles;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
[autoUpload, flow, maxItems, overwrite],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { handleFileInputChange, ref } = useDropzone({
|
||||||
|
onDropped: (newFiles: FileWithPath[]) => {
|
||||||
|
console.log("onDropped", newFiles);
|
||||||
|
addFiles(newFiles);
|
||||||
|
},
|
||||||
onOver: (items) => {
|
onOver: (items) => {
|
||||||
if (!isAllowed(items)) {
|
if (!isAllowed(items)) {
|
||||||
setIsOver(true, false);
|
setIsOver(true, false);
|
||||||
@@ -220,13 +231,15 @@ export function Dropzone({
|
|||||||
const uploaded: FileStateWithData[] = [];
|
const uploaded: FileStateWithData[] = [];
|
||||||
for (const file of pendingFiles) {
|
for (const file of pendingFiles) {
|
||||||
try {
|
try {
|
||||||
uploaded.push(await uploadFileProgress(file));
|
const progress = await uploadFileProgress(file);
|
||||||
|
uploaded.push(progress);
|
||||||
|
onUploaded?.(progress);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleUploadError(e);
|
handleUploadError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setUploading(false);
|
setUploading(false);
|
||||||
onUploaded?.(uploaded);
|
onUploadedAll?.(uploaded);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -342,7 +355,8 @@ export function Dropzone({
|
|||||||
|
|
||||||
const uploadFile = useCallback(async (file: FileState) => {
|
const uploadFile = useCallback(async (file: FileState) => {
|
||||||
const result = await uploadFileProgress(file);
|
const result = await uploadFileProgress(file);
|
||||||
onUploaded?.([result]);
|
onUploadedAll?.([result]);
|
||||||
|
onUploaded?.(result);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const openFileInput = useCallback(() => inputRef.current?.click(), [inputRef]);
|
const openFileInput = useCallback(() => inputRef.current?.click(), [inputRef]);
|
||||||
@@ -367,6 +381,7 @@ export function Dropzone({
|
|||||||
uploadFile,
|
uploadFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
openFileInput,
|
openFileInput,
|
||||||
|
addFiles,
|
||||||
},
|
},
|
||||||
dropzoneProps: {
|
dropzoneProps: {
|
||||||
maxItems,
|
maxItems,
|
||||||
@@ -406,11 +421,13 @@ export const useDropzoneState = () => {
|
|||||||
const files = useStore(store, (state) => state.files);
|
const files = useStore(store, (state) => state.files);
|
||||||
const isOver = useStore(store, (state) => state.isOver);
|
const isOver = useStore(store, (state) => state.isOver);
|
||||||
const isOverAccepted = useStore(store, (state) => state.isOverAccepted);
|
const isOverAccepted = useStore(store, (state) => state.isOverAccepted);
|
||||||
|
const uploading = useStore(store, (state) => state.uploading);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
files,
|
files,
|
||||||
isOver,
|
isOver,
|
||||||
isOverAccepted,
|
isOverAccepted,
|
||||||
|
uploading,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ export const TriggerNode = (props: NodeProps<Node<TAppFlowTriggerSchema & { labe
|
|||||||
control={control}
|
control={control}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{data.type === "manual" && <Manual />}
|
{data?.type === "manual" && <Manual />}
|
||||||
{data.type === "http" && (
|
{data?.type === "http" && (
|
||||||
<Http form={{ watch, register, setValue, getValues, control }} />
|
<Http form={{ watch, register, setValue, getValues, control }} />
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"name": "bknd",
|
"name": "bknd",
|
||||||
"version": "0.16.0-rc.0",
|
"version": "0.16.1",
|
||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cfworker/json-schema": "^4.1.1",
|
"@cfworker/json-schema": "^4.1.1",
|
||||||
@@ -35,7 +35,8 @@
|
|||||||
"hono": "4.8.3",
|
"hono": "4.8.3",
|
||||||
"json-schema-library": "10.0.0-rc7",
|
"json-schema-library": "10.0.0-rc7",
|
||||||
"json-schema-to-ts": "^3.1.1",
|
"json-schema-to-ts": "^3.1.1",
|
||||||
"kysely": "^0.27.6",
|
"jsonv-ts": "0.3.2",
|
||||||
|
"kysely": "0.27.6",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"oauth4webapi": "^2.11.1",
|
"oauth4webapi": "^2.11.1",
|
||||||
"object-path-immutable": "^4.1.2",
|
"object-path-immutable": "^4.1.2",
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.758.0",
|
"@aws-sdk/client-s3": "^3.758.0",
|
||||||
"@bluwy/giget-core": "^0.1.2",
|
"@bluwy/giget-core": "^0.1.2",
|
||||||
|
"@clack/prompts": "^0.11.0",
|
||||||
"@cloudflare/vitest-pool-workers": "^0.8.38",
|
"@cloudflare/vitest-pool-workers": "^0.8.38",
|
||||||
"@cloudflare/workers-types": "^4.20250606.0",
|
"@cloudflare/workers-types": "^4.20250606.0",
|
||||||
"@dagrejs/dagre": "^1.1.4",
|
"@dagrejs/dagre": "^1.1.4",
|
||||||
@@ -71,7 +73,6 @@
|
|||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"jotai": "^2.12.2",
|
"jotai": "^2.12.2",
|
||||||
"jsdom": "^26.0.0",
|
"jsdom": "^26.0.0",
|
||||||
"jsonv-ts": "^0.3.2",
|
|
||||||
"kysely-d1": "^0.3.0",
|
"kysely-d1": "^0.3.0",
|
||||||
"kysely-generic-sqlite": "^1.2.1",
|
"kysely-generic-sqlite": "^1.2.1",
|
||||||
"libsql-stateless-easy": "^1.8.0",
|
"libsql-stateless-easy": "^1.8.0",
|
||||||
@@ -123,6 +124,7 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
|
"bknd": "workspace:*",
|
||||||
"tsdx": "^0.14.1",
|
"tsdx": "^0.14.1",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
},
|
},
|
||||||
@@ -502,6 +504,10 @@
|
|||||||
|
|
||||||
"@cfworker/json-schema": ["@cfworker/json-schema@4.1.1", "", {}, "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og=="],
|
"@cfworker/json-schema": ["@cfworker/json-schema@4.1.1", "", {}, "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og=="],
|
||||||
|
|
||||||
|
"@clack/core": ["@clack/core@0.5.0", "https://registry.npmmirror.com/@clack/core/-/core-0.5.0.tgz", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
|
||||||
|
|
||||||
|
"@clack/prompts": ["@clack/prompts@0.11.0", "https://registry.npmmirror.com/@clack/prompts/-/prompts-0.11.0.tgz", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
||||||
|
|
||||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="],
|
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="],
|
||||||
|
|
||||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.3.2", "", { "peerDependencies": { "unenv": "2.0.0-rc.17", "workerd": "^1.20250508.0" }, "optionalPeers": ["workerd"] }, "sha512-MtUgNl+QkQyhQvv5bbWP+BpBC1N0me4CHHuP2H4ktmOMKdB/6kkz/lo+zqiA4mEazb4y+1cwyNjVrQ2DWeE4mg=="],
|
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.3.2", "", { "peerDependencies": { "unenv": "2.0.0-rc.17", "workerd": "^1.20250508.0" }, "optionalPeers": ["workerd"] }, "sha512-MtUgNl+QkQyhQvv5bbWP+BpBC1N0me4CHHuP2H4ktmOMKdB/6kkz/lo+zqiA4mEazb4y+1cwyNjVrQ2DWeE4mg=="],
|
||||||
@@ -564,7 +570,7 @@
|
|||||||
|
|
||||||
"@dagrejs/graphlib": ["@dagrejs/graphlib@2.2.4", "", {}, "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw=="],
|
"@dagrejs/graphlib": ["@dagrejs/graphlib@2.2.4", "", {}, "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
|
||||||
|
|
||||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="],
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="],
|
||||||
|
|
||||||
@@ -638,43 +644,49 @@
|
|||||||
|
|
||||||
"@hookform/resolvers": ["@hookform/resolvers@4.1.3", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ=="],
|
"@hookform/resolvers": ["@hookform/resolvers@4.1.3", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.0" }, "os": "darwin", "cpu": "x64" }, "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
|
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
|
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
|
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q=="],
|
||||||
|
|
||||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q=="],
|
||||||
|
|
||||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.0" }, "os": "linux", "cpu": "arm" }, "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A=="],
|
||||||
|
|
||||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
|
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA=="],
|
||||||
|
|
||||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.0" }, "os": "linux", "cpu": "ppc64" }, "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA=="],
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
|
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.0" }, "os": "linux", "cpu": "s390x" }, "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ=="],
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
|
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ=="],
|
||||||
|
|
||||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
|
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ=="],
|
||||||
|
|
||||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
|
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ=="],
|
||||||
|
|
||||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.3", "", { "dependencies": { "@emnapi/runtime": "^1.4.4" }, "cpu": "none" }, "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g=="],
|
||||||
|
|
||||||
"@inquirer/confirm": ["@inquirer/confirm@5.1.7", "", { "dependencies": { "@inquirer/core": "^10.1.8", "@inquirer/type": "^3.0.5" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Xrfbrw9eSiHb+GsesO8TQIeHSMTP0xyvTCeeYevgZ4sKW+iz9w/47bgfG9b0niQm+xaLY2EWPBINUPldLwvYiw=="],
|
"@inquirer/confirm": ["@inquirer/confirm@5.1.7", "", { "dependencies": { "@inquirer/core": "^10.1.8", "@inquirer/type": "^3.0.5" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Xrfbrw9eSiHb+GsesO8TQIeHSMTP0xyvTCeeYevgZ4sKW+iz9w/47bgfG9b0niQm+xaLY2EWPBINUPldLwvYiw=="],
|
||||||
|
|
||||||
@@ -686,6 +698,8 @@
|
|||||||
|
|
||||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||||
|
|
||||||
|
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||||
|
|
||||||
"@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
|
"@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
|
||||||
|
|
||||||
"@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
|
"@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
|
||||||
@@ -782,23 +796,23 @@
|
|||||||
|
|
||||||
"@neondatabase/serverless": ["@neondatabase/serverless@0.4.26", "", { "dependencies": { "@types/pg": "8.6.6" } }, "sha512-6DYEKos2GYn8NTgcJf33BLAx//LcgqzHVavQWe6ZkaDqmEq0I0Xtub6pzwFdq9iayNdCj7e2b0QKr5a8QKB8kQ=="],
|
"@neondatabase/serverless": ["@neondatabase/serverless@0.4.26", "", { "dependencies": { "@types/pg": "8.6.6" } }, "sha512-6DYEKos2GYn8NTgcJf33BLAx//LcgqzHVavQWe6ZkaDqmEq0I0Xtub6pzwFdq9iayNdCj7e2b0QKr5a8QKB8kQ=="],
|
||||||
|
|
||||||
"@next/env": ["@next/env@15.2.1", "", {}, "sha512-JmY0qvnPuS2NCWOz2bbby3Pe0VzdAQ7XpEB6uLIHmtXNfAsAO0KLQLkuAoc42Bxbo3/jMC3dcn9cdf+piCcG2Q=="],
|
"@next/env": ["@next/env@15.3.5", "", {}, "sha512-7g06v8BUVtN2njAX/r8gheoVffhiKFVt4nx74Tt6G4Hqw9HCLYQVx/GkH2qHvPtAHZaUNZ0VXAa0pQP6v1wk7g=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-aWXT+5KEREoy3K5AKtiKwioeblmOvFFjd+F3dVleLvvLiQ/mD//jOOuUcx5hzcO9ISSw4lrqtUPntTpK32uXXQ=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-E/w8ervu4fcG5SkLhvn1NE/2POuDCDEy5gFbfhmnYXkyONZR68qbUlJlZwuN82o7BrBVAw+tkR8nTIjGiMW1jQ=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gXDX5lIboebbjhiMT6kFgu4svQyjoSed6dHyjx5uZsjlvTwOAnZpn13w9XDaIMFFHw7K8CpBK7HfDKw0VZvUXQ=="],
|
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-3v0pF/adKZkBWfUffmB/ROa+QcNTrnmYG4/SS+r52HPwAK479XcWoES2I+7F7lcbqc7mTeVXrIvb4h6rR/iDKg=="],
|
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-RbsVq2iB6KFJRZ2cHrU67jLVLKeuOIhnQB05ygu5fCNgg8oTewxweJE8XlLV+Ii6Y6u4EHwETdUiRNXIAfpBww=="],
|
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-QHsMLAyAIu6/fWjHmkN/F78EFPKmhQlyX5C8pRIS2RwVA7z+t9cTb0IaYWC3EHLOTjsU7MNQW+n2xGXr11QPpg=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gk42XZXo1cE89i3hPLa/9KZ8OuupTjkDmhLaMKFohjf9brOeZVEa3BQy1J9s9TWUqPhgAEbwv6B2+ciGfe54Vw=="],
|
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.3.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ=="],
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-YjqXCl8QGhVlMR8uBftWk0iTmvtntr41PhG1kvzGp0sUP/5ehTM+cwx25hKE54J0CRnHYjSGjSH3gkHEaHIN9g=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.5", "", { "os": "win32", "cpu": "x64" }, "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw=="],
|
||||||
|
|
||||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
@@ -1156,33 +1170,35 @@
|
|||||||
|
|
||||||
"@tabler/icons-react": ["@tabler/icons-react@3.18.0", "", { "dependencies": { "@tabler/icons": "3.18.0" }, "peerDependencies": { "react": ">= 16" } }, "sha512-2gGMWJe67T7q6Sgb+4r/OsAjbq6hH30D6D2l02kOnl9kAauSsp/u6Gx1zteQ/GiwqRYSTEIhYMOhOV4LLa8rAw=="],
|
"@tabler/icons-react": ["@tabler/icons-react@3.18.0", "", { "dependencies": { "@tabler/icons": "3.18.0" }, "peerDependencies": { "react": ">= 16" } }, "sha512-2gGMWJe67T7q6Sgb+4r/OsAjbq6hH30D6D2l02kOnl9kAauSsp/u6Gx1zteQ/GiwqRYSTEIhYMOhOV4LLa8rAw=="],
|
||||||
|
|
||||||
"@tailwindcss/node": ["@tailwindcss/node@4.0.12", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "tailwindcss": "4.0.12" } }, "sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg=="],
|
"@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.0.12", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.0.12", "@tailwindcss/oxide-darwin-arm64": "4.0.12", "@tailwindcss/oxide-darwin-x64": "4.0.12", "@tailwindcss/oxide-freebsd-x64": "4.0.12", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.12", "@tailwindcss/oxide-linux-arm64-gnu": "4.0.12", "@tailwindcss/oxide-linux-arm64-musl": "4.0.12", "@tailwindcss/oxide-linux-x64-gnu": "4.0.12", "@tailwindcss/oxide-linux-x64-musl": "4.0.12", "@tailwindcss/oxide-win32-arm64-msvc": "4.0.12", "@tailwindcss/oxide-win32-x64-msvc": "4.0.12" } }, "sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A=="],
|
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.0.12", "", { "os": "android", "cpu": "arm64" }, "sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ=="],
|
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.0.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ=="],
|
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.0.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A=="],
|
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.0.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA=="],
|
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12", "", { "os": "linux", "cpu": "arm" }, "sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ=="],
|
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.0.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ=="],
|
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.0.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw=="],
|
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.0.12", "", { "os": "linux", "cpu": "x64" }, "sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw=="],
|
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.0.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA=="],
|
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.0.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g=="],
|
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.0.12", "", { "os": "win32", "cpu": "x64" }, "sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw=="],
|
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="],
|
||||||
|
|
||||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.0.12", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.0.12", "@tailwindcss/oxide": "4.0.12", "lightningcss": "^1.29.1", "postcss": "^8.4.41", "tailwindcss": "4.0.12" } }, "sha512-r59Sdr8djCW4dL3kvc4aWU8PHdUAVM3O3te2nbYzXsWwKLlHPCuUoZAc9FafXb/YyNDZOMI7sTbKTKFmwOrMjw=="],
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.11", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "postcss": "^8.4.41", "tailwindcss": "4.1.11" } }, "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA=="],
|
||||||
|
|
||||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.0.12", "", { "dependencies": { "@tailwindcss/node": "4.0.12", "@tailwindcss/oxide": "4.0.12", "lightningcss": "^1.29.1", "tailwindcss": "4.0.12" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-JM3gp601UJiryIZ9R2bSqalzcOy15RCybQ1Q+BJqDEwVyo4LkWKeqQAcrpHapWXY31OJFTuOUVBFDWMhzHm2Bg=="],
|
"@tailwindcss/vite": ["@tailwindcss/vite@4.0.12", "", { "dependencies": { "@tailwindcss/node": "4.0.12", "@tailwindcss/oxide": "4.0.12", "lightningcss": "^1.29.1", "tailwindcss": "4.0.12" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-JM3gp601UJiryIZ9R2bSqalzcOy15RCybQ1Q+BJqDEwVyo4LkWKeqQAcrpHapWXY31OJFTuOUVBFDWMhzHm2Bg=="],
|
||||||
|
|
||||||
@@ -1232,6 +1248,8 @@
|
|||||||
|
|
||||||
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
||||||
|
|
||||||
|
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
|
||||||
|
|
||||||
"@types/eslint-visitor-keys": ["@types/eslint-visitor-keys@1.0.0", "", {}, "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag=="],
|
"@types/eslint-visitor-keys": ["@types/eslint-visitor-keys@1.0.0", "", {}, "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
|
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
|
||||||
@@ -1254,6 +1272,8 @@
|
|||||||
|
|
||||||
"@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
|
"@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
|
||||||
|
|
||||||
|
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="],
|
"@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="],
|
||||||
|
|
||||||
"@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="],
|
"@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="],
|
||||||
@@ -1264,9 +1284,9 @@
|
|||||||
|
|
||||||
"@types/prettier": ["@types/prettier@1.19.1", "", {}, "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ=="],
|
"@types/prettier": ["@types/prettier@1.19.1", "", {}, "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="],
|
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.0.4", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg=="],
|
"@types/react-dom": ["@types/react-dom@19.1.6", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw=="],
|
||||||
|
|
||||||
"@types/resolve": ["@types/resolve@1.17.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw=="],
|
"@types/resolve": ["@types/resolve@1.17.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw=="],
|
||||||
|
|
||||||
@@ -1748,7 +1768,7 @@
|
|||||||
|
|
||||||
"cross-port-killer": ["cross-port-killer@1.4.0", "", { "bin": { "kill-port": "source/cli.js" } }, "sha512-ujqfftKsSeorFMVI6JP25xMBixHEaDWVK+NarRZAGnJjR5AhebRQU+g+k/Lj8OHwM6f+wrrs8u5kkCdI7RLtxQ=="],
|
"cross-port-killer": ["cross-port-killer@1.4.0", "", { "bin": { "kill-port": "source/cli.js" } }, "sha512-ujqfftKsSeorFMVI6JP25xMBixHEaDWVK+NarRZAGnJjR5AhebRQU+g+k/Lj8OHwM6f+wrrs8u5kkCdI7RLtxQ=="],
|
||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="],
|
||||||
|
|
||||||
"css-box-model": ["css-box-model@1.2.1", "", { "dependencies": { "tiny-invariant": "^1.0.6" } }, "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw=="],
|
"css-box-model": ["css-box-model@1.2.1", "", { "dependencies": { "tiny-invariant": "^1.0.6" } }, "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw=="],
|
||||||
|
|
||||||
@@ -2720,7 +2740,7 @@
|
|||||||
|
|
||||||
"netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
|
"netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
|
||||||
|
|
||||||
"next": ["next@15.2.1", "", { "dependencies": { "@next/env": "15.2.1", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.2.1", "@next/swc-darwin-x64": "15.2.1", "@next/swc-linux-arm64-gnu": "15.2.1", "@next/swc-linux-arm64-musl": "15.2.1", "@next/swc-linux-x64-gnu": "15.2.1", "@next/swc-linux-x64-musl": "15.2.1", "@next/swc-win32-arm64-msvc": "15.2.1", "@next/swc-win32-x64-msvc": "15.2.1", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-zxbsdQv3OqWXybK5tMkPCBKyhIz63RstJ+NvlfkaLMc/m5MwXgz2e92k+hSKcyBpyADhMk2C31RIiaDjUZae7g=="],
|
"next": ["next@15.3.5", "", { "dependencies": { "@next/env": "15.3.5", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.3.5", "@next/swc-darwin-x64": "15.3.5", "@next/swc-linux-arm64-gnu": "15.3.5", "@next/swc-linux-arm64-musl": "15.3.5", "@next/swc-linux-x64-gnu": "15.3.5", "@next/swc-linux-x64-musl": "15.3.5", "@next/swc-win32-arm64-msvc": "15.3.5", "@next/swc-win32-x64-msvc": "15.3.5", "sharp": "^0.34.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-RkazLBMMDJSJ4XZQ81kolSpwiCt907l0xcgcpF4xC2Vml6QVcPNXW0NQRwQ80FFtSn7UM52XN0anaw8TEJXaiw=="],
|
||||||
|
|
||||||
"nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="],
|
"nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="],
|
||||||
|
|
||||||
@@ -2846,7 +2866,7 @@
|
|||||||
|
|
||||||
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
||||||
|
|
||||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
"path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
||||||
|
|
||||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||||
|
|
||||||
@@ -2880,7 +2900,7 @@
|
|||||||
|
|
||||||
"pg-protocol": ["pg-protocol@1.8.0", "", {}, "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g=="],
|
"pg-protocol": ["pg-protocol@1.8.0", "", {}, "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g=="],
|
||||||
|
|
||||||
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
"pg-types": ["pg-types@4.0.2", "", { "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" } }, "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng=="],
|
||||||
|
|
||||||
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
||||||
|
|
||||||
@@ -2914,7 +2934,7 @@
|
|||||||
|
|
||||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||||
|
|
||||||
"postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="],
|
"postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="],
|
||||||
|
|
||||||
@@ -2934,13 +2954,13 @@
|
|||||||
|
|
||||||
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
|
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
|
||||||
|
|
||||||
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
"postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="],
|
||||||
|
|
||||||
"postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
|
"postgres-bytea": ["postgres-bytea@3.0.0", "", { "dependencies": { "obuf": "~1.1.2" } }, "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw=="],
|
||||||
|
|
||||||
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
"postgres-date": ["postgres-date@2.1.0", "", {}, "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA=="],
|
||||||
|
|
||||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
"postgres-interval": ["postgres-interval@3.0.0", "", {}, "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw=="],
|
||||||
|
|
||||||
"postgres-range": ["postgres-range@1.1.4", "", {}, "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w=="],
|
"postgres-range": ["postgres-range@1.1.4", "", {}, "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w=="],
|
||||||
|
|
||||||
@@ -3014,15 +3034,15 @@
|
|||||||
|
|
||||||
"raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="],
|
"raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="],
|
||||||
|
|
||||||
"react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="],
|
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||||
|
|
||||||
"react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="],
|
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||||
|
|
||||||
"react-hook-form": ["react-hook-form@7.54.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg=="],
|
"react-hook-form": ["react-hook-form@7.61.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-o8S/HcCeuaAQVib36fPCgOLaaQN/v7Anj8zlYjcLMcz+4FnNfMsoDAEvVCefLb3KDnS43wq3pwcifehhkwowuQ=="],
|
||||||
|
|
||||||
"react-icons": ["react-icons@5.2.1", "", { "peerDependencies": { "react": "*" } }, "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw=="],
|
"react-icons": ["react-icons@5.2.1", "", { "peerDependencies": { "react": "*" } }, "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw=="],
|
||||||
|
|
||||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
"react-json-view-lite": ["react-json-view-lite@2.4.1", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA=="],
|
"react-json-view-lite": ["react-json-view-lite@2.4.1", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA=="],
|
||||||
|
|
||||||
@@ -3172,7 +3192,7 @@
|
|||||||
|
|
||||||
"saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
|
"saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
|
||||||
|
|
||||||
"scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
|
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||||
|
|
||||||
"semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
|
"semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
|
||||||
|
|
||||||
@@ -3202,11 +3222,11 @@
|
|||||||
|
|
||||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||||
|
|
||||||
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
"sharp": ["sharp@0.34.3", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.3", "@img/sharp-darwin-x64": "0.34.3", "@img/sharp-libvips-darwin-arm64": "1.2.0", "@img/sharp-libvips-darwin-x64": "1.2.0", "@img/sharp-libvips-linux-arm": "1.2.0", "@img/sharp-libvips-linux-arm64": "1.2.0", "@img/sharp-libvips-linux-ppc64": "1.2.0", "@img/sharp-libvips-linux-s390x": "1.2.0", "@img/sharp-libvips-linux-x64": "1.2.0", "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", "@img/sharp-libvips-linuxmusl-x64": "1.2.0", "@img/sharp-linux-arm": "0.34.3", "@img/sharp-linux-arm64": "0.34.3", "@img/sharp-linux-ppc64": "0.34.3", "@img/sharp-linux-s390x": "0.34.3", "@img/sharp-linux-x64": "0.34.3", "@img/sharp-linuxmusl-arm64": "0.34.3", "@img/sharp-linuxmusl-x64": "0.34.3", "@img/sharp-wasm32": "0.34.3", "@img/sharp-win32-arm64": "0.34.3", "@img/sharp-win32-ia32": "0.34.3", "@img/sharp-win32-x64": "0.34.3" } }, "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg=="],
|
||||||
|
|
||||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
"shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="],
|
||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
"shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="],
|
||||||
|
|
||||||
"shelljs": ["shelljs@0.8.5", "", { "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" } }, "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow=="],
|
"shelljs": ["shelljs@0.8.5", "", { "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" } }, "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow=="],
|
||||||
|
|
||||||
@@ -3374,9 +3394,9 @@
|
|||||||
|
|
||||||
"table": ["table@5.4.6", "", { "dependencies": { "ajv": "^6.10.2", "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" } }, "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug=="],
|
"table": ["table@5.4.6", "", { "dependencies": { "ajv": "^6.10.2", "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" } }, "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug=="],
|
||||||
|
|
||||||
"tailwind-merge": ["tailwind-merge@3.0.2", "", {}, "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw=="],
|
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.0.12", "", {}, "sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg=="],
|
"tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
|
||||||
|
|
||||||
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
|
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
|
||||||
|
|
||||||
@@ -3604,7 +3624,7 @@
|
|||||||
|
|
||||||
"vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="],
|
"vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="],
|
||||||
|
|
||||||
"vitest": ["vitest@3.0.8", "", { "dependencies": { "@vitest/expect": "3.0.8", "@vitest/mocker": "3.0.8", "@vitest/pretty-format": "^3.0.8", "@vitest/runner": "3.0.8", "@vitest/snapshot": "3.0.8", "@vitest/spy": "3.0.8", "@vitest/utils": "3.0.8", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.8", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.8", "@vitest/ui": "3.0.8", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA=="],
|
"vitest": ["vitest@3.0.9", "", { "dependencies": { "@vitest/expect": "3.0.9", "@vitest/mocker": "3.0.9", "@vitest/pretty-format": "^3.0.9", "@vitest/runner": "3.0.9", "@vitest/snapshot": "3.0.9", "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.9", "@vitest/ui": "3.0.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ=="],
|
||||||
|
|
||||||
"w3c-hr-time": ["w3c-hr-time@1.0.2", "", { "dependencies": { "browser-process-hrtime": "^1.0.0" } }, "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ=="],
|
"w3c-hr-time": ["w3c-hr-time@1.0.2", "", { "dependencies": { "browser-process-hrtime": "^1.0.0" } }, "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ=="],
|
||||||
|
|
||||||
@@ -3634,7 +3654,7 @@
|
|||||||
|
|
||||||
"whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
|
"whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
|
||||||
|
|
||||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
"which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
||||||
|
|
||||||
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
||||||
|
|
||||||
@@ -3810,7 +3830,11 @@
|
|||||||
|
|
||||||
"@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
|
"@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
|
||||||
|
|
||||||
"@bknd/postgres/@types/bun": ["@types/bun@1.2.15", "", { "dependencies": { "bun-types": "1.2.15" } }, "sha512-U1ljPdBEphF0nw1MIk0hI7kPg7dFdPyM7EenHsp6W5loNHl7zqy6JQf/RKCgnUn2KDzUpkBwHPnEJEjII594bA=="],
|
"@bknd/plasmic/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
|
"@bknd/postgres/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
|
"@bknd/sqlocal/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
"@bundled-es-modules/cookie/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
"@bundled-es-modules/cookie/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||||
|
|
||||||
@@ -3838,6 +3862,8 @@
|
|||||||
|
|
||||||
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||||
|
|
||||||
|
"@isaacs/fs-minipass/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|
||||||
"@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
"@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
||||||
|
|
||||||
"@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
"@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
@@ -3874,8 +3900,12 @@
|
|||||||
|
|
||||||
"@neondatabase/serverless/@types/pg": ["@types/pg@8.6.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw=="],
|
"@neondatabase/serverless/@types/pg": ["@types/pg@8.6.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw=="],
|
||||||
|
|
||||||
|
"@plasmicapp/nextjs-app-router/cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"@plasmicapp/query/swr": ["swr@1.3.0", "", { "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } }, "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw=="],
|
"@plasmicapp/query/swr": ["swr@1.3.0", "", { "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } }, "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw=="],
|
||||||
|
|
||||||
|
"@plasmicapp/react-ssr-prepass/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="],
|
||||||
|
|
||||||
"@puppeteer/browsers/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
"@puppeteer/browsers/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||||
|
|
||||||
"@remix-run/node/cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
"@remix-run/node/cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||||
@@ -3890,6 +3920,8 @@
|
|||||||
|
|
||||||
"@remix-run/web-fetch/mrmime": ["mrmime@1.0.1", "", {}, "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw=="],
|
"@remix-run/web-fetch/mrmime": ["mrmime@1.0.1", "", {}, "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw=="],
|
||||||
|
|
||||||
|
"@rjsf/utils/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||||
|
|
||||||
"@rollup/plugin-babel/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="],
|
"@rollup/plugin-babel/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="],
|
||||||
|
|
||||||
"@rollup/plugin-commonjs/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="],
|
"@rollup/plugin-commonjs/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="],
|
||||||
@@ -4012,6 +4044,30 @@
|
|||||||
|
|
||||||
"@tailwindcss/node/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
"@tailwindcss/node/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" }, "bundled": true }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/node": ["@tailwindcss/node@4.0.12", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "tailwindcss": "4.0.12" } }, "sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide": ["@tailwindcss/oxide@4.0.12", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.0.12", "@tailwindcss/oxide-darwin-arm64": "4.0.12", "@tailwindcss/oxide-darwin-x64": "4.0.12", "@tailwindcss/oxide-freebsd-x64": "4.0.12", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.12", "@tailwindcss/oxide-linux-arm64-gnu": "4.0.12", "@tailwindcss/oxide-linux-arm64-musl": "4.0.12", "@tailwindcss/oxide-linux-x64-gnu": "4.0.12", "@tailwindcss/oxide-linux-x64-musl": "4.0.12", "@tailwindcss/oxide-win32-arm64-msvc": "4.0.12", "@tailwindcss/oxide-win32-x64-msvc": "4.0.12" } }, "sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/tailwindcss": ["tailwindcss@4.0.12", "", {}, "sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg=="],
|
||||||
|
|
||||||
"@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
|
"@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
|
||||||
|
|
||||||
"@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
|
"@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
|
||||||
@@ -4022,8 +4078,6 @@
|
|||||||
|
|
||||||
"@types/bun/bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
|
"@types/bun/bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
|
||||||
|
|
||||||
"@types/pg/pg-types": ["pg-types@4.0.2", "", { "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" } }, "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng=="],
|
|
||||||
|
|
||||||
"@typescript-eslint/experimental-utils/eslint-utils": ["eslint-utils@2.1.0", "", { "dependencies": { "eslint-visitor-keys": "^1.1.0" } }, "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg=="],
|
"@typescript-eslint/experimental-utils/eslint-utils": ["eslint-utils@2.1.0", "", { "dependencies": { "eslint-visitor-keys": "^1.1.0" } }, "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||||
@@ -4064,12 +4118,14 @@
|
|||||||
|
|
||||||
"@verdaccio/utils/minimatch": ["minimatch@7.4.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw=="],
|
"@verdaccio/utils/minimatch": ["minimatch@7.4.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw=="],
|
||||||
|
|
||||||
|
"@vitest/browser/vitest": ["vitest@3.0.8", "", { "dependencies": { "@vitest/expect": "3.0.8", "@vitest/mocker": "3.0.8", "@vitest/pretty-format": "^3.0.8", "@vitest/runner": "3.0.8", "@vitest/snapshot": "3.0.8", "@vitest/spy": "3.0.8", "@vitest/utils": "3.0.8", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.8", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.8", "@vitest/ui": "3.0.8", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA=="],
|
||||||
|
|
||||||
"@vitest/browser/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="],
|
"@vitest/browser/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="],
|
||||||
|
|
||||||
"@vitest/coverage-v8/vitest": ["vitest@3.0.9", "", { "dependencies": { "@vitest/expect": "3.0.9", "@vitest/mocker": "3.0.9", "@vitest/pretty-format": "^3.0.9", "@vitest/runner": "3.0.9", "@vitest/snapshot": "3.0.9", "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.9", "@vitest/ui": "3.0.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ=="],
|
|
||||||
|
|
||||||
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||||
|
|
||||||
|
"@vitest/ui/vitest": ["vitest@3.0.8", "", { "dependencies": { "@vitest/expect": "3.0.8", "@vitest/mocker": "3.0.8", "@vitest/pretty-format": "^3.0.8", "@vitest/runner": "3.0.8", "@vitest/snapshot": "3.0.8", "@vitest/spy": "3.0.8", "@vitest/utils": "3.0.8", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.8", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.8", "@vitest/ui": "3.0.8", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA=="],
|
||||||
|
|
||||||
"@wdio/config/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
"@wdio/config/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||||
|
|
||||||
"@wdio/logger/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
|
"@wdio/logger/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
|
||||||
@@ -4114,12 +4170,8 @@
|
|||||||
|
|
||||||
"base/pascalcase": ["pascalcase@0.1.1", "", {}, "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="],
|
"base/pascalcase": ["pascalcase@0.1.1", "", {}, "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="],
|
||||||
|
|
||||||
"bknd/vitest": ["vitest@3.0.9", "", { "dependencies": { "@vitest/expect": "3.0.9", "@vitest/mocker": "3.0.9", "@vitest/pretty-format": "^3.0.9", "@vitest/runner": "3.0.9", "@vitest/snapshot": "3.0.9", "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.9", "@vitest/ui": "3.0.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ=="],
|
|
||||||
|
|
||||||
"bknd-cli/@libsql/client": ["@libsql/client@0.14.0", "", { "dependencies": { "@libsql/core": "^0.14.0", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.4.4", "promise-limit": "^2.7.0" } }, "sha512-/9HEKfn6fwXB5aTEEoMeFh4CtG0ZzbncBb1e++OCdVpgKZ/xyMsIVYXm0w7Pv4RUel803vE6LwniB3PqD72R0Q=="],
|
"bknd-cli/@libsql/client": ["@libsql/client@0.14.0", "", { "dependencies": { "@libsql/core": "^0.14.0", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.4.4", "promise-limit": "^2.7.0" } }, "sha512-/9HEKfn6fwXB5aTEEoMeFh4CtG0ZzbncBb1e++OCdVpgKZ/xyMsIVYXm0w7Pv4RUel803vE6LwniB3PqD72R0Q=="],
|
||||||
|
|
||||||
"bknd-cli/hono": ["hono@4.7.4", "", {}, "sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg=="],
|
|
||||||
|
|
||||||
"body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
"body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
||||||
@@ -4138,12 +4190,16 @@
|
|||||||
|
|
||||||
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
|
"cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
||||||
|
|
||||||
"degenerator/escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
"degenerator/escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
||||||
|
|
||||||
"domexception/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
|
"domexception/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
|
||||||
|
|
||||||
"duplexify/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
"duplexify/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||||
|
|
||||||
|
"edge-paths/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"edgedriver/fast-xml-parser": ["fast-xml-parser@4.5.3", "", { "dependencies": { "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig=="],
|
"edgedriver/fast-xml-parser": ["fast-xml-parser@4.5.3", "", { "dependencies": { "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig=="],
|
||||||
|
|
||||||
"edgedriver/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
"edgedriver/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||||
@@ -4162,8 +4218,6 @@
|
|||||||
|
|
||||||
"eslint/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"eslint/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
|
|
||||||
"eslint/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="],
|
|
||||||
|
|
||||||
"eslint/globals": ["globals@12.4.0", "", { "dependencies": { "type-fest": "^0.8.1" } }, "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg=="],
|
"eslint/globals": ["globals@12.4.0", "", { "dependencies": { "type-fest": "^0.8.1" } }, "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg=="],
|
||||||
|
|
||||||
"eslint/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
"eslint/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
@@ -4206,6 +4260,8 @@
|
|||||||
|
|
||||||
"espree/acorn": ["acorn@7.4.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="],
|
"espree/acorn": ["acorn@7.4.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="],
|
||||||
|
|
||||||
|
"execa/cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="],
|
"expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="],
|
||||||
@@ -4230,6 +4286,8 @@
|
|||||||
|
|
||||||
"flat-cache/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="],
|
"flat-cache/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="],
|
||||||
|
|
||||||
|
"foreground-child/cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||||
|
|
||||||
"fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
"fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||||
@@ -4286,6 +4344,8 @@
|
|||||||
|
|
||||||
"jest-haste-map/jest-worker": ["jest-worker@25.5.0", "", { "dependencies": { "merge-stream": "^2.0.0", "supports-color": "^7.0.0" } }, "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw=="],
|
"jest-haste-map/jest-worker": ["jest-worker@25.5.0", "", { "dependencies": { "merge-stream": "^2.0.0", "supports-color": "^7.0.0" } }, "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw=="],
|
||||||
|
|
||||||
|
"jest-haste-map/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"jest-jasmine2/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
"jest-jasmine2/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
||||||
|
|
||||||
"jest-matcher-utils/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
"jest-matcher-utils/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
||||||
@@ -4366,10 +4426,10 @@
|
|||||||
|
|
||||||
"node-notifier/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"node-notifier/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
"node-notifier/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
|
||||||
|
|
||||||
"normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
"normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
||||||
|
|
||||||
|
"npm-run-path/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
"object-copy/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="],
|
"object-copy/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="],
|
||||||
|
|
||||||
"object-copy/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
"object-copy/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
||||||
@@ -4384,9 +4444,11 @@
|
|||||||
|
|
||||||
"peek-stream/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
|
"peek-stream/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
|
||||||
|
|
||||||
|
"pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||||
|
|
||||||
"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||||
|
|
||||||
"pretty-format/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
"postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
"progress-estimator/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"progress-estimator/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
|
|
||||||
@@ -4394,8 +4456,6 @@
|
|||||||
|
|
||||||
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
||||||
|
|
||||||
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
|
||||||
|
|
||||||
"pumpify/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
|
"pumpify/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
|
||||||
|
|
||||||
"pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="],
|
"pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="],
|
||||||
@@ -4470,9 +4530,9 @@
|
|||||||
|
|
||||||
"set-value/is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="],
|
"set-value/is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="],
|
||||||
|
|
||||||
"sharp/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
"sharp/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||||
|
|
||||||
"sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
"sharp/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||||
|
|
||||||
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
||||||
|
|
||||||
@@ -4568,6 +4628,8 @@
|
|||||||
|
|
||||||
"verdaccio-htpasswd/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
"verdaccio-htpasswd/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||||
|
|
||||||
|
"vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
||||||
|
|
||||||
"vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
"vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
||||||
|
|
||||||
"vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
"vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
||||||
@@ -4620,10 +4682,10 @@
|
|||||||
|
|
||||||
"@babel/preset-env/babel-plugin-polyfill-regenerator/@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg=="],
|
"@babel/preset-env/babel-plugin-polyfill-regenerator/@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg=="],
|
||||||
|
|
||||||
"@bknd/postgres/@types/bun/bun-types": ["bun-types@1.2.15", "", { "dependencies": { "@types/node": "*" } }, "sha512-NarRIaS+iOaQU1JPfyKhZm4AsUOrwUOqRNHY0XxI8GI8jYxiLXLcdjYMG9UKS+fwWasc1uw1htV9AX24dD+p4w=="],
|
|
||||||
|
|
||||||
"@bundled-es-modules/tough-cookie/tough-cookie/universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
|
"@bundled-es-modules/tough-cookie/tough-cookie/universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||||
|
|
||||||
"@cloudflare/vitest-pool-workers/miniflare/workerd": ["workerd@1.20250604.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250604.0", "@cloudflare/workerd-darwin-arm64": "1.20250604.0", "@cloudflare/workerd-linux-64": "1.20250604.0", "@cloudflare/workerd-linux-arm64": "1.20250604.0", "@cloudflare/workerd-windows-64": "1.20250604.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-sHz9R1sxPpnyq3ptrI/5I96sYTMA2+Ljm75oJDbmEcZQwNyezpu9Emerzt3kzzjCJQqtdscGOidWv4RKGZXzAA=="],
|
"@cloudflare/vitest-pool-workers/miniflare/workerd": ["workerd@1.20250604.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250604.0", "@cloudflare/workerd-darwin-arm64": "1.20250604.0", "@cloudflare/workerd-linux-64": "1.20250604.0", "@cloudflare/workerd-linux-arm64": "1.20250604.0", "@cloudflare/workerd-windows-64": "1.20250604.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-sHz9R1sxPpnyq3ptrI/5I96sYTMA2+Ljm75oJDbmEcZQwNyezpu9Emerzt3kzzjCJQqtdscGOidWv4RKGZXzAA=="],
|
||||||
|
|
||||||
"@cloudflare/vitest-pool-workers/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
"@cloudflare/vitest-pool-workers/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
||||||
@@ -4634,6 +4696,16 @@
|
|||||||
|
|
||||||
"@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
"@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
|
|
||||||
|
"@neondatabase/serverless/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||||
|
|
||||||
|
"@plasmicapp/nextjs-app-router/cross-spawn/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"@plasmicapp/nextjs-app-router/cross-spawn/shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"@plasmicapp/nextjs-app-router/cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
|
"@plasmicapp/query/swr/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="],
|
||||||
|
|
||||||
"@rollup/plugin-babel/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="],
|
"@rollup/plugin-babel/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="],
|
||||||
|
|
||||||
"@rollup/plugin-babel/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"@rollup/plugin-babel/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
@@ -4654,18 +4726,68 @@
|
|||||||
|
|
||||||
"@rollup/plugin-replace/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"@rollup/plugin-replace/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar/minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar/mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/node/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.0.12", "", { "os": "android", "cpu": "arm64" }, "sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.0.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.0.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.0.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12", "", { "os": "linux", "cpu": "arm" }, "sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.0.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.0.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.0.12", "", { "os": "linux", "cpu": "x64" }, "sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.0.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.0.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.0.12", "", { "os": "win32", "cpu": "x64" }, "sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw=="],
|
||||||
|
|
||||||
"@testing-library/dom/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
"@testing-library/dom/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||||
|
|
||||||
"@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
"@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||||
|
|
||||||
"@types/pg/pg-types/postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="],
|
|
||||||
|
|
||||||
"@types/pg/pg-types/postgres-bytea": ["postgres-bytea@3.0.0", "", { "dependencies": { "obuf": "~1.1.2" } }, "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw=="],
|
|
||||||
|
|
||||||
"@types/pg/pg-types/postgres-date": ["postgres-date@2.1.0", "", {}, "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA=="],
|
|
||||||
|
|
||||||
"@types/pg/pg-types/postgres-interval": ["postgres-interval@3.0.0", "", {}, "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw=="],
|
|
||||||
|
|
||||||
"@verdaccio/local-storage-legacy/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
"@verdaccio/local-storage-legacy/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
||||||
|
|
||||||
"@verdaccio/logger/pino/on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
"@verdaccio/logger/pino/on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
||||||
@@ -4686,7 +4808,9 @@
|
|||||||
|
|
||||||
"@verdaccio/middleware/express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"@verdaccio/middleware/express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"@vitest/coverage-v8/vitest/vite": ["vite@6.2.1", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q=="],
|
"@vitest/browser/vitest/vite": ["vite@6.2.1", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q=="],
|
||||||
|
|
||||||
|
"@vitest/ui/vitest/vite": ["vite@6.2.1", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q=="],
|
||||||
|
|
||||||
"@wdio/config/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
"@wdio/config/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|
||||||
@@ -4706,8 +4830,6 @@
|
|||||||
|
|
||||||
"bknd-cli/@libsql/client/libsql": ["libsql@0.4.7", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.4.7", "@libsql/darwin-x64": "0.4.7", "@libsql/linux-arm64-gnu": "0.4.7", "@libsql/linux-arm64-musl": "0.4.7", "@libsql/linux-x64-gnu": "0.4.7", "@libsql/linux-x64-musl": "0.4.7", "@libsql/win32-x64-msvc": "0.4.7" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw=="],
|
"bknd-cli/@libsql/client/libsql": ["libsql@0.4.7", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.4.7", "@libsql/darwin-x64": "0.4.7", "@libsql/linux-arm64-gnu": "0.4.7", "@libsql/linux-arm64-musl": "0.4.7", "@libsql/linux-x64-gnu": "0.4.7", "@libsql/linux-x64-musl": "0.4.7", "@libsql/win32-x64-msvc": "0.4.7" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw=="],
|
||||||
|
|
||||||
"bknd/vitest/vite": ["vite@6.2.1", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q=="],
|
|
||||||
|
|
||||||
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"class-utils/define-property/is-descriptor": ["is-descriptor@0.1.7", "", { "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" } }, "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg=="],
|
"class-utils/define-property/is-descriptor": ["is-descriptor@0.1.7", "", { "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" } }, "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg=="],
|
||||||
@@ -4732,14 +4854,6 @@
|
|||||||
|
|
||||||
"eslint/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
"eslint/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||||
|
|
||||||
"eslint/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
|
||||||
|
|
||||||
"eslint/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
|
||||||
|
|
||||||
"eslint/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="],
|
|
||||||
|
|
||||||
"eslint/cross-spawn/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
|
||||||
|
|
||||||
"eslint/globals/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="],
|
"eslint/globals/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="],
|
||||||
|
|
||||||
"eslint/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
"eslint/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
@@ -4748,6 +4862,12 @@
|
|||||||
|
|
||||||
"eslint/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
"eslint/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||||
|
|
||||||
|
"execa/cross-spawn/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"execa/cross-spawn/shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"execa/cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"expand-brackets/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"expand-brackets/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.7", "", { "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" } }, "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg=="],
|
"expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.7", "", { "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" } }, "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg=="],
|
||||||
@@ -4762,6 +4882,12 @@
|
|||||||
|
|
||||||
"find-cache-dir/make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"find-cache-dir/make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
|
"foreground-child/cross-spawn/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"foreground-child/cross-spawn/shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"foreground-child/cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"geckodriver/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
"geckodriver/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
||||||
|
|
||||||
"glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
"glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||||
@@ -4770,6 +4896,8 @@
|
|||||||
|
|
||||||
"has-values/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
"has-values/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
||||||
|
|
||||||
|
"jest-changed-files/execa/cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"jest-cli/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
|
"jest-cli/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
|
||||||
|
|
||||||
"jest-cli/yargs/decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
|
"jest-cli/yargs/decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
|
||||||
@@ -4838,6 +4966,14 @@
|
|||||||
|
|
||||||
"peek-stream/duplexify/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
"peek-stream/duplexify/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||||
|
|
||||||
|
"pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||||
|
|
||||||
|
"pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
|
||||||
|
|
||||||
|
"pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||||
|
|
||||||
|
"pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||||
|
|
||||||
"progress-estimator/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
"progress-estimator/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||||
|
|
||||||
"progress-estimator/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
"progress-estimator/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||||
@@ -4862,8 +4998,6 @@
|
|||||||
|
|
||||||
"sane/anymatch/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="],
|
"sane/anymatch/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="],
|
||||||
|
|
||||||
"sane/execa/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="],
|
|
||||||
|
|
||||||
"sane/execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="],
|
"sane/execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="],
|
||||||
|
|
||||||
"sane/execa/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="],
|
"sane/execa/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="],
|
||||||
@@ -4920,8 +5054,12 @@
|
|||||||
|
|
||||||
"verdaccio-audit/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
"verdaccio-audit/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||||
|
|
||||||
|
"vite-node/vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
||||||
|
|
||||||
"vite-node/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
"vite-node/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
||||||
|
|
||||||
|
"vitest/vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
||||||
|
|
||||||
"vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
"vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
||||||
|
|
||||||
"webdriver/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
|
"webdriver/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
|
||||||
@@ -4978,6 +5116,8 @@
|
|||||||
|
|
||||||
"wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="],
|
"wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||||
|
|
||||||
"wrangler/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
"wrangler/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
||||||
|
|
||||||
"wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250604.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-PI6AWAzhHg75KVhYkSWFBf3HKCHstpaKg4nrx6LYZaEvz0TaTz+JQpYU2fNAgGFmVsK5xEzwFTGh3DAVAKONPw=="],
|
"wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250604.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-PI6AWAzhHg75KVhYkSWFBf3HKCHstpaKg4nrx6LYZaEvz0TaTz+JQpYU2fNAgGFmVsK5xEzwFTGh3DAVAKONPw=="],
|
||||||
@@ -5000,6 +5140,46 @@
|
|||||||
|
|
||||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
||||||
|
|
||||||
"@cloudflare/vitest-pool-workers/miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250604.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-PI6AWAzhHg75KVhYkSWFBf3HKCHstpaKg4nrx6LYZaEvz0TaTz+JQpYU2fNAgGFmVsK5xEzwFTGh3DAVAKONPw=="],
|
"@cloudflare/vitest-pool-workers/miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250604.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-PI6AWAzhHg75KVhYkSWFBf3HKCHstpaKg4nrx6LYZaEvz0TaTz+JQpYU2fNAgGFmVsK5xEzwFTGh3DAVAKONPw=="],
|
||||||
|
|
||||||
"@cloudflare/vitest-pool-workers/miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250604.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hOiZZSop7QRQgGERtTIy9eU5GvPpIsgE2/BDsUdHMl7OBZ7QLniqvgDzLNDzj0aTkCldm9Yl/Z+C7aUgRdOccw=="],
|
"@cloudflare/vitest-pool-workers/miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250604.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hOiZZSop7QRQgGERtTIy9eU5GvPpIsgE2/BDsUdHMl7OBZ7QLniqvgDzLNDzj0aTkCldm9Yl/Z+C7aUgRdOccw=="],
|
||||||
@@ -5012,9 +5192,25 @@
|
|||||||
|
|
||||||
"@cloudflare/vitest-pool-workers/miniflare/youch/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
"@cloudflare/vitest-pool-workers/miniflare/youch/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||||
|
|
||||||
|
"@neondatabase/serverless/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||||
|
|
||||||
|
"@neondatabase/serverless/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
|
||||||
|
|
||||||
|
"@neondatabase/serverless/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||||
|
|
||||||
|
"@neondatabase/serverless/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||||
|
|
||||||
|
"@plasmicapp/nextjs-app-router/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
"@verdaccio/middleware/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"@verdaccio/middleware/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"@vitest/coverage-v8/vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
"@vitest/browser/vitest/vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
||||||
|
|
||||||
|
"@vitest/browser/vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
||||||
|
|
||||||
|
"@vitest/ui/vitest/vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
||||||
|
|
||||||
|
"@vitest/ui/vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
||||||
|
|
||||||
"babel-plugin-istanbul/test-exclude/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
"babel-plugin-istanbul/test-exclude/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|
||||||
@@ -5032,13 +5228,19 @@
|
|||||||
|
|
||||||
"bknd-cli/@libsql/client/libsql/@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.4.7", "", { "os": "win32", "cpu": "x64" }, "sha512-7pJzOWzPm6oJUxml+PCDRzYQ4A1hTMHAciTAHfFK4fkbDZX33nWPVG7Y3vqdKtslcwAzwmrNDc6sXy2nwWnbiw=="],
|
"bknd-cli/@libsql/client/libsql/@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.4.7", "", { "os": "win32", "cpu": "x64" }, "sha512-7pJzOWzPm6oJUxml+PCDRzYQ4A1hTMHAciTAHfFK4fkbDZX33nWPVG7Y3vqdKtslcwAzwmrNDc6sXy2nwWnbiw=="],
|
||||||
|
|
||||||
"bknd/vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="],
|
|
||||||
|
|
||||||
"eslint/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
"eslint/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||||
|
|
||||||
"eslint/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
"eslint/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||||
|
|
||||||
"eslint/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="],
|
"execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
|
"foreground-child/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
|
"jest-changed-files/execa/cross-spawn/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"jest-changed-files/execa/cross-spawn/shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"jest-changed-files/execa/cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"jest-cli/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
"jest-cli/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
||||||
|
|
||||||
@@ -5070,16 +5272,6 @@
|
|||||||
|
|
||||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||||
|
|
||||||
"sane/execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
|
||||||
|
|
||||||
"sane/execa/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
|
||||||
|
|
||||||
"sane/execa/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="],
|
|
||||||
|
|
||||||
"sane/execa/cross-spawn/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
|
||||||
|
|
||||||
"sane/execa/npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
|
||||||
|
|
||||||
"sane/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="],
|
"sane/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="],
|
||||||
|
|
||||||
"sane/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ=="],
|
"sane/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ=="],
|
||||||
@@ -5092,24 +5284,74 @@
|
|||||||
|
|
||||||
"verdaccio-audit/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"verdaccio-audit/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||||
|
|
||||||
"wrangler/miniflare/youch/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
"wrangler/miniflare/youch/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="],
|
||||||
|
|
||||||
"eslint/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"eslint/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
|
"jest-changed-files/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
"log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"log-update/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
"log-update/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
||||||
|
|
||||||
"progress-estimator/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"progress-estimator/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"sane/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="],
|
|
||||||
|
|
||||||
"sane/micromatch/braces/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
|
"sane/micromatch/braces/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
|
||||||
|
|
||||||
"sane/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg=="],
|
"sane/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg=="],
|
||||||
|
|
||||||
"sane/micromatch/braces/fill-range/to-regex-range": ["to-regex-range@2.1.1", "", { "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg=="],
|
"sane/micromatch/braces/fill-range/to-regex-range": ["to-regex-range@2.1.1", "", { "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="],
|
||||||
|
|
||||||
|
"@cloudflare/vitest-pool-workers/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"sane/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
"sane/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
|
||||||
|
|
||||||
|
"wrangler/miniflare/sharp/@img/sharp-wasm32/@emnapi/runtime/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
# Stage 1: Build stage
|
# Stage 1: Build stage
|
||||||
FROM node:20 as builder
|
FROM node:24 as builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ RUN npm install --omit=dev bknd@${VERSION}
|
|||||||
RUN mkdir /output && cp -r node_modules/bknd/dist /output/dist
|
RUN mkdir /output && cp -r node_modules/bknd/dist /output/dist
|
||||||
|
|
||||||
# Stage 2: Final minimal image
|
# Stage 2: Final minimal image
|
||||||
FROM node:20-alpine
|
FROM node:24-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -29,4 +29,4 @@ ENV DEFAULT_ARGS="--db-url file:/data/data.db"
|
|||||||
COPY --from=builder /output/dist ./dist
|
COPY --from=builder /output/dist ./dist
|
||||||
|
|
||||||
EXPOSE 1337
|
EXPOSE 1337
|
||||||
CMD ["pm2-runtime", "dist/cli/index.js run ${ARGS:-${DEFAULT_ARGS}} --no-open"]
|
CMD ["pm2-runtime", "dist/cli/index.js run ${ARGS:-${DEFAULT_ARGS}} --no-open"]
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": ["next/core-web-vitals", "next/typescript"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# deps
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# generated content
|
||||||
|
.contentlayer
|
||||||
|
.content-collections
|
||||||
|
.source
|
||||||
|
.twoslash-cache
|
||||||
|
|
||||||
|
# test & build
|
||||||
|
/coverage
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
/build
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# others
|
||||||
|
.env*.local
|
||||||
|
.vercel
|
||||||
|
next-env.d.ts
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# bknd-docs
|
||||||
|
|
||||||
|
This is a Next.js application generated with
|
||||||
|
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
|
||||||
|
|
||||||
|
Run development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open http://localhost:3000 with your browser to see the result.
|
||||||
|
|
||||||
|
## Explore
|
||||||
|
|
||||||
|
In the project, you can see:
|
||||||
|
|
||||||
|
- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
|
||||||
|
- `app/layout.config.tsx`: Shared options for layouts, optional but preferred to keep.
|
||||||
|
|
||||||
|
| Route | Description |
|
||||||
|
| ------------------------- | ------------------------------------------------------ |
|
||||||
|
| `app/(home)` | The route group for your landing page and other pages. |
|
||||||
|
| `app/docs` | The documentation layout and pages. |
|
||||||
|
| `app/api/search/route.ts` | The Route Handler for search. |
|
||||||
|
|
||||||
|
### Fumadocs MDX
|
||||||
|
|
||||||
|
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
|
||||||
|
|
||||||
|
Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js and Fumadocs, take a look at the following
|
||||||
|
resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
|
||||||
|
features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
- [Fumadocs](https://fumadocs.vercel.app) - learn about Fumadocs
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB |
@@ -1,161 +0,0 @@
|
|||||||
<svg width="700" height="320" viewBox="0 0 700 320" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g clip-path="url(#clip0_2862_30)">
|
|
||||||
<rect width="700" height="320" rx="16" fill="url(#paint0_linear_2862_30)"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="white"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="url(#paint1_radial_2862_30)"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="black" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="url(#paint2_linear_2862_30)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M311.72 247.034C283.108 246.887 258.409 231.208 246.538 201.531C234.656 171.825 238.271 134.702 253.583 101.377C282.195 101.524 306.894 117.203 318.765 146.88C330.647 176.586 327.031 213.709 311.72 247.034Z" stroke="url(#paint3_linear_2862_30)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<path d="M305.839 247.174C343.92 237.419 377.154 210.619 393.585 171.64C410.017 132.661 405.98 90.1988 386.347 56.1934C348.266 65.9477 315.032 92.7486 298.601 131.728C282.169 170.706 286.206 213.168 305.839 247.174Z" fill="white"/>
|
|
||||||
<path d="M305.839 247.174C343.92 237.419 377.154 210.619 393.585 171.64C410.017 132.661 405.98 90.1988 386.347 56.1934C348.266 65.9477 315.032 92.7486 298.601 131.728C282.169 170.706 286.206 213.168 305.839 247.174Z" fill="url(#paint4_radial_2862_30)"/>
|
|
||||||
<path d="M393.341 171.537C376.971 210.369 343.89 237.091 305.969 246.867C286.462 212.959 282.476 170.663 298.845 131.831C315.215 92.9978 348.295 66.2765 386.217 56.5004C405.724 90.4077 409.71 132.704 393.341 171.537Z" stroke="url(#paint5_linear_2862_30)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<path d="M305.686 246.995C329.749 266.114 361.965 272.832 393.67 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.045 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="white"/>
|
|
||||||
<path d="M305.686 246.995C329.749 266.114 361.965 272.832 393.67 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.045 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="url(#paint6_radial_2862_30)"/>
|
|
||||||
<path d="M305.686 246.995C329.749 266.114 361.965 272.832 393.67 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.045 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="black" fill-opacity="0.2" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M305.686 246.995C329.749 266.114 361.965 272.832 393.67 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.045 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="url(#paint7_linear_2862_30)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M393.586 261.878C362.034 272.529 329.98 265.88 306.002 246.907C317.534 215.919 341.57 190.327 373.13 179.673C404.681 169.023 436.735 175.671 460.714 194.644C449.181 225.632 425.145 251.224 393.586 261.878Z" stroke="url(#paint8_linear_2862_30)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<g opacity="0.8" filter="url(#filter0_f_2862_30)">
|
|
||||||
<circle cx="660" cy="-60" r="160" fill="#18E244" fill-opacity="0.4"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter1_f_2862_30)">
|
|
||||||
<circle cx="20" cy="213" r="160" fill="#18CAE2" fill-opacity="0.33"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter2_f_2862_30)">
|
|
||||||
<circle cx="660" cy="480" r="160" fill="#18E2B2" fill-opacity="0.52"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter3_f_2862_30)">
|
|
||||||
<circle cx="20" cy="413" r="160" fill="#4018E2" fill-opacity="0.22"/>
|
|
||||||
</g>
|
|
||||||
<path opacity="0.2" d="M0 50H700" stroke="url(#paint9_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.1" d="M0 82H700" stroke="url(#paint10_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.2" d="M239 0L239 320" stroke="url(#paint11_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.1" d="M271 0L271 320" stroke="url(#paint12_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.2" d="M461 0L461 320" stroke="url(#paint13_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.1" d="M429 0L429 320" stroke="url(#paint14_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.2" d="M0 271H700" stroke="url(#paint15_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<path opacity="0.1" d="M0 239H700" stroke="url(#paint16_radial_2862_30)" stroke-dasharray="4 4"/>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 160H700" stroke="url(#paint17_linear_2862_30)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.2">
|
|
||||||
<path d="M511 -1L189 321" stroke="url(#paint18_linear_2862_30)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.2">
|
|
||||||
<path d="M511 321L189 -1" stroke="url(#paint19_linear_2862_30)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<circle cx="350" cy="160" r="111" stroke="white"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<circle cx="350" cy="160" r="79" stroke="white"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_2862_30" x="260" y="-460" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_30"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter1_f_2862_30" x="-380" y="-187" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_30"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter2_f_2862_30" x="260" y="80" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_30"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter3_f_2862_30" x="-380" y="13" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_30"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient id="paint0_linear_2862_30" x1="1.04308e-05" y1="320" x2="710.784" y2="26.0793" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299" stop-opacity="0.09"/>
|
|
||||||
<stop offset="0.729167" stop-color="#0D9373" stop-opacity="0.08"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint1_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(208.697 189.703) rotate(-10.029) scale(169.097 167.466)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint2_linear_2862_30" x1="306.587" y1="93.5598" x2="252.341" y2="224.228" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint3_linear_2862_30" x1="311.84" y1="123.717" x2="253.579" y2="224.761" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint4_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(313.407 243.64) rotate(-75.7542) scale(203.632 223.902)">
|
|
||||||
<stop stop-color="#00BBBB"/>
|
|
||||||
<stop offset="0.712616" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint5_linear_2862_30" x1="308.586" y1="102.284" x2="383.487" y2="201.169" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint6_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(311.446 249.925) rotate(-20.3524) scale(174.776 163.096)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint7_linear_2862_30" x1="395.842" y1="169.781" x2="332.121" y2="263.82" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#00B1BC"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint8_linear_2862_30" x1="395.842" y1="169.781" x2="370.99" y2="271.799" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint9_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(350 50) scale(398.125 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint10_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(350 82) scale(398.125 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint11_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(239 160) rotate(90) scale(182 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint12_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(271 160) rotate(90) scale(182 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint13_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(461 160) rotate(90) scale(182 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint14_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(429 160) rotate(90) scale(182 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint15_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(350 271) scale(398.125 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint16_radial_2862_30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(350 239) scale(398.125 182)">
|
|
||||||
<stop offset="0.348958" stop-color="#84FFD3"/>
|
|
||||||
<stop offset="0.880208" stop-color="#18E299" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint17_linear_2862_30" x1="0" y1="160" x2="700" y2="160" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="white" stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5" stop-color="white"/>
|
|
||||||
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint18_linear_2862_30" x1="511" y1="-1" x2="189" y2="321" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="white" stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5" stop-color="white"/>
|
|
||||||
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint19_linear_2862_30" x1="511" y1="321" x2="189" y2="-0.999997" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="white" stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5" stop-color="white"/>
|
|
||||||
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<clipPath id="clip0_2862_30">
|
|
||||||
<rect width="700" height="320" rx="16" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,155 +0,0 @@
|
|||||||
<svg width="700" height="320" viewBox="0 0 700 320" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g clip-path="url(#clip0_2862_278)">
|
|
||||||
<rect width="700" height="320" rx="16" fill="url(#paint0_linear_2862_278)"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="white"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="url(#paint1_radial_2862_278)"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="black" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M311.889 247.3C283.097 247.215 258.226 231.466 246.292 201.629C234.357 171.793 238.02 134.523 253.414 101.112C282.206 101.197 307.077 116.945 319.011 146.782C330.946 176.619 327.283 213.888 311.889 247.3Z" fill="url(#paint2_linear_2862_278)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M311.72 247.034C283.108 246.887 258.409 231.208 246.538 201.531C234.656 171.825 238.271 134.702 253.583 101.377C282.195 101.524 306.894 117.203 318.765 146.88C330.647 176.586 327.031 213.709 311.72 247.034Z" stroke="url(#paint3_linear_2862_278)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<path d="M305.839 247.174C343.92 237.419 377.154 210.619 393.585 171.64C410.017 132.661 405.98 90.1988 386.347 56.1934C348.266 65.9477 315.032 92.7486 298.601 131.728C282.169 170.706 286.206 213.168 305.839 247.174Z" fill="white"/>
|
|
||||||
<path d="M305.839 247.174C343.92 237.419 377.154 210.619 393.585 171.64C410.017 132.661 405.98 90.1988 386.347 56.1934C348.266 65.9477 315.032 92.7486 298.601 131.728C282.169 170.706 286.206 213.168 305.839 247.174Z" fill="url(#paint4_radial_2862_278)"/>
|
|
||||||
<path d="M393.341 171.537C376.971 210.369 343.89 237.091 305.969 246.867C286.462 212.959 282.476 170.663 298.845 131.831C315.215 92.9978 348.295 66.2765 386.217 56.5004C405.724 90.4077 409.71 132.704 393.341 171.537Z" stroke="url(#paint5_linear_2862_278)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<path d="M305.686 246.995C329.75 266.114 361.965 272.832 393.671 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.046 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="white"/>
|
|
||||||
<path d="M305.686 246.995C329.75 266.114 361.965 272.832 393.671 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.046 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="url(#paint6_radial_2862_278)"/>
|
|
||||||
<path d="M305.686 246.995C329.75 266.114 361.965 272.832 393.671 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.046 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="black" fill-opacity="0.2" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M305.686 246.995C329.75 266.114 361.965 272.832 393.671 262.129C425.376 251.426 449.499 225.691 461.03 194.556C436.967 175.437 404.751 168.719 373.046 179.422C341.34 190.125 317.217 215.86 305.686 246.995Z" fill="url(#paint7_linear_2862_278)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M393.586 261.878C362.035 272.529 329.981 265.88 306.002 246.907C317.535 215.919 341.571 190.327 373.13 179.673C404.682 169.023 436.736 175.671 460.715 194.644C449.182 225.632 425.146 251.224 393.586 261.878Z" stroke="url(#paint8_linear_2862_278)" stroke-opacity="0.05" stroke-width="0.530516"/>
|
|
||||||
<g opacity="0.8" filter="url(#filter0_f_2862_278)">
|
|
||||||
<circle cx="660" cy="-60" r="160" fill="#18E299" fill-opacity="0.4"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter1_f_2862_278)">
|
|
||||||
<circle cx="20" cy="213" r="160" fill="#18E299" fill-opacity="0.33"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter2_f_2862_278)">
|
|
||||||
<circle cx="660" cy="480" r="160" fill="#18E299" fill-opacity="0.52"/>
|
|
||||||
</g>
|
|
||||||
<g opacity="0.8" filter="url(#filter3_f_2862_278)">
|
|
||||||
<circle cx="20" cy="413" r="160" fill="#18E299" fill-opacity="0.22"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 50H700" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 82H700" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M239 0L239 320" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M271 0L271 320" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M461 0L461 320" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M350 0L350 320" stroke="url(#paint9_linear_2862_278)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M429 0L429 320" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 271H700" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 239H700" stroke="black" stroke-dasharray="4 4"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M0 160H700" stroke="url(#paint10_linear_2862_278)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M511 -1L189 321" stroke="url(#paint11_linear_2862_278)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.1">
|
|
||||||
<path d="M511 321L189 -1" stroke="url(#paint12_linear_2862_278)"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.05">
|
|
||||||
<circle cx="350" cy="160" r="111" stroke="black"/>
|
|
||||||
</g>
|
|
||||||
<g style="mix-blend-mode:overlay" opacity="0.05">
|
|
||||||
<circle cx="350" cy="160" r="79" stroke="black"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_2862_278" x="260" y="-460" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_278"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter1_f_2862_278" x="-380" y="-187" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_278"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter2_f_2862_278" x="260" y="80" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_278"/>
|
|
||||||
</filter>
|
|
||||||
<filter id="filter3_f_2862_278" x="-380" y="13" width="800" height="800" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="120" result="effect1_foregroundBlur_2862_278"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient id="paint0_linear_2862_278" x1="1.04308e-05" y1="320" x2="710.784" y2="26.0793" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299" stop-opacity="0.09"/>
|
|
||||||
<stop offset="0.729167" stop-color="#0D9373" stop-opacity="0.08"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint1_radial_2862_278" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(208.697 189.703) rotate(-10.029) scale(169.097 167.466)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint2_linear_2862_278" x1="306.587" y1="93.5598" x2="252.341" y2="224.228" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint3_linear_2862_278" x1="311.84" y1="123.717" x2="253.579" y2="224.761" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint4_radial_2862_278" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(313.407 243.64) rotate(-75.7542) scale(203.632 223.902)">
|
|
||||||
<stop stop-color="#00BBBB"/>
|
|
||||||
<stop offset="0.712616" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint5_linear_2862_278" x1="308.586" y1="102.284" x2="383.487" y2="201.169" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint6_radial_2862_278" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(311.447 249.925) rotate(-20.3524) scale(174.776 163.096)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint7_linear_2862_278" x1="395.843" y1="169.781" x2="332.121" y2="263.82" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#00B1BC"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint8_linear_2862_278" x1="395.843" y1="169.781" x2="370.991" y2="271.799" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint9_linear_2862_278" x1="350" y1="0" x2="350" y2="320" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-opacity="0"/>
|
|
||||||
<stop offset="0.0001" stop-opacity="0.3"/>
|
|
||||||
<stop offset="0.333333"/>
|
|
||||||
<stop offset="0.666667"/>
|
|
||||||
<stop offset="1" stop-opacity="0.3"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint10_linear_2862_278" x1="0" y1="160" x2="700" y2="160" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5"/>
|
|
||||||
<stop offset="1" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint11_linear_2862_278" x1="511" y1="-1" x2="189" y2="321" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5"/>
|
|
||||||
<stop offset="1" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint12_linear_2862_278" x1="511" y1="321" x2="189" y2="-0.999997" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-opacity="0.1"/>
|
|
||||||
<stop offset="0.5"/>
|
|
||||||
<stop offset="1" stop-opacity="0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<clipPath id="clip0_2862_278">
|
|
||||||
<rect width="700" height="320" rx="16" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 10 KiB |
@@ -1,55 +0,0 @@
|
|||||||
<svg width="160" height="24" viewBox="0 0 160 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="white"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="url(#paint0_radial_115_109)"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="black" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="url(#paint1_linear_115_109)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.9354 21.1112C4.89702 21.0957 2.27411 19.4306 1.01347 16.279C-0.248375 13.1244 0.135612 9.18218 1.76165 5.64327C4.80004 5.65882 7.42295 7.32385 8.68359 10.4755C9.94543 13.63 9.56144 17.5723 7.9354 21.1112Z" stroke="url(#paint2_linear_115_109)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="white"/>
|
|
||||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="url(#paint3_radial_115_109)"/>
|
|
||||||
<path d="M16.6025 13.2251C14.8642 17.349 11.3512 20.1866 7.32411 21.2248C5.25257 17.624 4.82926 13.1324 6.56764 9.00855C8.30603 4.88472 11.819 2.04706 15.8461 1.00889C17.9176 4.60967 18.3409 9.10131 16.6025 13.2251Z" stroke="url(#paint4_linear_115_109)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="white"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint5_radial_115_109)"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="black" fill-opacity="0.2" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint6_linear_115_109)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M16.5682 22.7874C13.2176 23.9184 9.81361 23.2124 7.2672 21.1975C8.49194 17.9068 11.0444 15.189 14.3959 14.0577C17.7465 12.9266 21.1504 13.6326 23.6968 15.6476C22.4721 18.9383 19.9196 21.656 16.5682 22.7874Z" stroke="url(#paint7_linear_115_109)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M34.2124 19V5.4H39.4924L41.6924 12.2L42.3724 14.74L43.0524 12.2L45.2524 5.4H50.4124V19H46.3324L46.5924 9.98L45.5324 13.68L43.7924 19H40.8324L39.0524 13.6L38.0324 10.02L38.2924 19H34.2124ZM52.4155 7.3V4.6H56.2955V7.3H52.4155ZM52.4155 19V8.14H56.2955V19H52.4155ZM58.1038 19V8.14H61.9838V9.58C62.6638 8.34 63.7438 7.76 65.0038 7.76C66.9638 7.76 68.6238 8.98 68.6238 11.78V19H64.7438V12.56C64.7438 11.34 64.3038 10.86 63.4838 10.86C62.6038 10.86 61.9838 11.58 61.9838 12.88V19H58.1038ZM70.9327 15.22V11.06H69.7327V8.14H70.9327V5.62H74.8127V8.14H76.9327V11.06H74.8127V14.6C74.8127 15.5 75.0327 16.06 76.2127 16.06H76.9327V19C76.4927 19.2 75.6727 19.38 74.6527 19.38C72.1527 19.38 70.9327 17.88 70.9327 15.22Z" fill="url(#paint8_radial_115_109)"/>
|
|
||||||
<path d="M87.232 10.519C87.232 13.687 94.1125 11.2285 94.1125 15.832C94.1125 17.9935 92.3635 19.198 89.971 19.198C87.562 19.198 85.912 18.0925 85.417 15.832H87.001C87.364 17.1685 88.3705 17.8945 89.9875 17.8945C91.6705 17.8945 92.5615 17.152 92.5615 16.03C92.5615 12.598 85.681 15.1555 85.681 10.618C85.681 9.001 87.034 7.582 89.509 7.582C91.6705 7.582 93.403 8.6215 93.8155 11.014H92.215C91.8685 9.529 90.9115 8.8855 89.476 8.8855C88.057 8.8855 87.232 9.529 87.232 10.519ZM96.2499 16.4755V11.3935H95.0289V10.2385H96.2499V8.2255H97.7019V10.2385H99.6324V11.3935H97.7019V16.4755C97.7019 17.5315 98.0154 18.0265 99.3024 18.0265H99.5994V19.066C99.4344 19.1485 99.0714 19.198 98.6589 19.198C97.0254 19.198 96.2499 18.3235 96.2499 16.4755ZM102.516 13.093H101.064C101.345 11.1625 102.615 10.024 104.76 10.024C107.103 10.024 108.242 11.3935 108.242 13.4395V16.888C108.242 17.8945 108.324 18.5215 108.555 19H107.021C106.856 18.6535 106.806 18.142 106.79 17.614C106.047 18.7195 104.859 19.198 103.803 19.198C101.988 19.198 100.767 18.3565 100.767 16.69C100.767 15.4855 101.427 14.611 102.714 14.182C103.902 13.786 105.107 13.687 106.79 13.6705V13.4725C106.79 12.0535 106.13 11.278 104.628 11.278C103.374 11.278 102.698 11.971 102.516 13.093ZM102.252 16.657C102.252 17.4655 102.929 17.944 103.952 17.944C105.569 17.944 106.79 16.6735 106.79 15.172V14.7595C103.061 14.7925 102.252 15.5845 102.252 16.657ZM110.787 19V10.2385H112.239V11.5915C112.833 10.519 113.774 10.024 114.83 10.024C115.176 10.024 115.49 10.1065 115.655 10.2385V11.542C115.407 11.4595 115.094 11.4265 114.747 11.4265C112.998 11.4265 112.239 12.5155 112.239 14.0995V19H110.787ZM117.305 16.4755V11.3935H116.084V10.2385H117.305V8.2255H118.757V10.2385H120.688V11.3935H118.757V16.4755C118.757 17.5315 119.071 18.0265 120.358 18.0265H120.655V19.066C120.49 19.1485 120.127 19.198 119.714 19.198C118.081 19.198 117.305 18.3235 117.305 16.4755ZM129.809 16.1455C129.33 18.1915 127.862 19.198 125.865 19.198C123.324 19.198 121.79 17.482 121.79 14.6275C121.79 11.6575 123.324 10.024 125.783 10.024C128.258 10.024 129.743 11.7235 129.743 14.512V14.875H123.275C123.357 16.8385 124.281 17.944 125.865 17.944C127.103 17.944 127.977 17.35 128.291 16.1455H129.809ZM125.783 11.278C124.38 11.278 123.539 12.1525 123.324 13.786H128.225C128.027 12.169 127.152 11.278 125.783 11.278ZM131.843 19V10.2385H133.295V11.5915C133.889 10.519 134.829 10.024 135.885 10.024C136.232 10.024 136.545 10.1065 136.71 10.2385V11.542C136.463 11.4595 136.149 11.4265 135.803 11.4265C134.054 11.4265 133.295 12.5155 133.295 14.0995V19H131.843ZM141.763 19V7.78H143.281V13.192L148.413 7.78H150.327L145.047 13.291L150.459 19H148.413L143.281 13.621V19H141.763ZM152.06 9.067V7.12H153.512V9.067H152.06ZM152.06 19V10.2385H153.512V19H152.06ZM156.178 16.4755V11.3935H154.957V10.2385H156.178V8.2255H157.63V10.2385H159.56V11.3935H157.63V16.4755C157.63 17.5315 157.943 18.0265 159.23 18.0265H159.527V19.066C159.362 19.1485 158.999 19.198 158.587 19.198C156.953 19.198 156.178 18.3235 156.178 16.4755Z" fill="white" fill-opacity="0.55"/>
|
|
||||||
<defs>
|
|
||||||
<radialGradient id="paint0_radial_115_109" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(-3.00503 15.023) rotate(-10.029) scale(17.9572 17.784)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint1_linear_115_109" x1="7.39036" y1="4.81308" x2="1.62975" y2="18.6894" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint2_linear_115_109" x1="7.94816" y1="8.01562" x2="1.7612" y2="18.746" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint3_radial_115_109" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(8.11404 20.8822) rotate(-75.7542) scale(21.6246 23.7772)">
|
|
||||||
<stop stop-color="#00BBBB"/>
|
|
||||||
<stop offset="0.712616" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint4_linear_115_109" x1="7.60205" y1="5.8709" x2="15.5561" y2="16.3719" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint5_radial_115_109" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.84537 21.5181) rotate(-20.3525) scale(18.5603 17.32)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint6_linear_115_109" x1="16.8078" y1="13.0071" x2="10.0409" y2="22.9937" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#00B1BC"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint7_linear_115_109" x1="16.8078" y1="13.0071" x2="14.1687" y2="23.841" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint8_radial_115_109" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(47.2781 7) rotate(19.0047) scale(67.5582 85.7506)">
|
|
||||||
<stop stop-color="white"/>
|
|
||||||
<stop offset="1" stop-color="white" stop-opacity="0.5"/>
|
|
||||||
</radialGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 9.3 KiB |
@@ -1,51 +0,0 @@
|
|||||||
<svg width="160" height="24" viewBox="0 0 160 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="white"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="url(#paint0_radial_115_86)"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="black" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61504C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5913 7.95343 21.1394Z" fill="url(#paint1_linear_115_86)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.9354 21.1112C4.89702 21.0957 2.27411 19.4306 1.01347 16.279C-0.248375 13.1244 0.135612 9.18218 1.76165 5.64327C4.80004 5.65882 7.42295 7.32385 8.68359 10.4755C9.94543 13.63 9.56144 17.5723 7.9354 21.1112Z" stroke="url(#paint2_linear_115_86)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="white"/>
|
|
||||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="url(#paint3_radial_115_86)"/>
|
|
||||||
<path d="M16.6025 13.2251C14.8642 17.349 11.3512 20.1866 7.32411 21.2248C5.25257 17.624 4.82926 13.1324 6.56764 9.00855C8.30603 4.88472 11.819 2.04706 15.8461 1.00889C17.9176 4.60967 18.3409 9.10131 16.6025 13.2251Z" stroke="url(#paint4_linear_115_86)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="white"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint5_radial_115_86)"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="black" fill-opacity="0.2" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint6_linear_115_86)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
|
||||||
<path d="M16.5682 22.7874C13.2176 23.9184 9.81361 23.2124 7.2672 21.1975C8.49194 17.9068 11.0444 15.189 14.3959 14.0577C17.7465 12.9266 21.1504 13.6326 23.6968 15.6476C22.4721 18.9383 19.9196 21.656 16.5682 22.7874Z" stroke="url(#paint7_linear_115_86)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
|
||||||
<path d="M34.2124 19V5.4H39.4924L41.6924 12.2L42.3724 14.74L43.0524 12.2L45.2524 5.4H50.4124V19H46.3324L46.5924 9.98L45.5324 13.68L43.7924 19H40.8324L39.0524 13.6L38.0324 10.02L38.2924 19H34.2124ZM52.4155 7.3V4.6H56.2955V7.3H52.4155ZM52.4155 19V8.14H56.2955V19H52.4155ZM58.1038 19V8.14H61.9838V9.58C62.6638 8.34 63.7438 7.76 65.0038 7.76C66.9638 7.76 68.6238 8.98 68.6238 11.78V19H64.7438V12.56C64.7438 11.34 64.3038 10.86 63.4838 10.86C62.6038 10.86 61.9838 11.58 61.9838 12.88V19H58.1038ZM70.9327 15.22V11.06H69.7327V8.14H70.9327V5.62H74.8127V8.14H76.9327V11.06H74.8127V14.6C74.8127 15.5 75.0327 16.06 76.2127 16.06H76.9327V19C76.4927 19.2 75.6727 19.38 74.6527 19.38C72.1527 19.38 70.9327 17.88 70.9327 15.22Z" fill="#001E13"/>
|
|
||||||
<path d="M87.232 10.519C87.232 13.687 94.1125 11.2285 94.1125 15.832C94.1125 17.9935 92.3635 19.198 89.971 19.198C87.562 19.198 85.912 18.0925 85.417 15.832H87.001C87.364 17.1685 88.3705 17.8945 89.9875 17.8945C91.6705 17.8945 92.5615 17.152 92.5615 16.03C92.5615 12.598 85.681 15.1555 85.681 10.618C85.681 9.001 87.034 7.582 89.509 7.582C91.6705 7.582 93.403 8.6215 93.8155 11.014H92.215C91.8685 9.529 90.9115 8.8855 89.476 8.8855C88.057 8.8855 87.232 9.529 87.232 10.519ZM96.2499 16.4755V11.3935H95.0289V10.2385H96.2499V8.2255H97.7019V10.2385H99.6324V11.3935H97.7019V16.4755C97.7019 17.5315 98.0154 18.0265 99.3024 18.0265H99.5994V19.066C99.4344 19.1485 99.0714 19.198 98.6589 19.198C97.0254 19.198 96.2499 18.3235 96.2499 16.4755ZM102.516 13.093H101.064C101.345 11.1625 102.615 10.024 104.76 10.024C107.103 10.024 108.242 11.3935 108.242 13.4395V16.888C108.242 17.8945 108.324 18.5215 108.555 19H107.021C106.856 18.6535 106.806 18.142 106.79 17.614C106.047 18.7195 104.859 19.198 103.803 19.198C101.988 19.198 100.767 18.3565 100.767 16.69C100.767 15.4855 101.427 14.611 102.714 14.182C103.902 13.786 105.107 13.687 106.79 13.6705V13.4725C106.79 12.0535 106.13 11.278 104.628 11.278C103.374 11.278 102.698 11.971 102.516 13.093ZM102.252 16.657C102.252 17.4655 102.929 17.944 103.952 17.944C105.569 17.944 106.79 16.6735 106.79 15.172V14.7595C103.061 14.7925 102.252 15.5845 102.252 16.657ZM110.787 19V10.2385H112.239V11.5915C112.833 10.519 113.774 10.024 114.83 10.024C115.176 10.024 115.49 10.1065 115.655 10.2385V11.542C115.407 11.4595 115.094 11.4265 114.747 11.4265C112.998 11.4265 112.239 12.5155 112.239 14.0995V19H110.787ZM117.305 16.4755V11.3935H116.084V10.2385H117.305V8.2255H118.757V10.2385H120.688V11.3935H118.757V16.4755C118.757 17.5315 119.071 18.0265 120.358 18.0265H120.655V19.066C120.49 19.1485 120.127 19.198 119.714 19.198C118.081 19.198 117.305 18.3235 117.305 16.4755ZM129.809 16.1455C129.33 18.1915 127.862 19.198 125.865 19.198C123.324 19.198 121.79 17.482 121.79 14.6275C121.79 11.6575 123.324 10.024 125.783 10.024C128.258 10.024 129.743 11.7235 129.743 14.512V14.875H123.275C123.357 16.8385 124.281 17.944 125.865 17.944C127.103 17.944 127.977 17.35 128.291 16.1455H129.809ZM125.783 11.278C124.38 11.278 123.539 12.1525 123.324 13.786H128.225C128.027 12.169 127.152 11.278 125.783 11.278ZM131.843 19V10.2385H133.295V11.5915C133.889 10.519 134.829 10.024 135.885 10.024C136.232 10.024 136.545 10.1065 136.71 10.2385V11.542C136.463 11.4595 136.149 11.4265 135.803 11.4265C134.054 11.4265 133.295 12.5155 133.295 14.0995V19H131.843ZM141.763 19V7.78H143.281V13.192L148.413 7.78H150.327L145.047 13.291L150.459 19H148.413L143.281 13.621V19H141.763ZM152.06 9.067V7.12H153.512V9.067H152.06ZM152.06 19V10.2385H153.512V19H152.06ZM156.178 16.4755V11.3935H154.957V10.2385H156.178V8.2255H157.63V10.2385H159.56V11.3935H157.63V16.4755C157.63 17.5315 157.943 18.0265 159.23 18.0265H159.527V19.066C159.362 19.1485 158.999 19.198 158.587 19.198C156.953 19.198 156.178 18.3235 156.178 16.4755Z" fill="#002719" fill-opacity="0.6"/>
|
|
||||||
<defs>
|
|
||||||
<radialGradient id="paint0_radial_115_86" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(-3.00503 15.023) rotate(-10.029) scale(17.9572 17.784)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint1_linear_115_86" x1="7.39036" y1="4.81308" x2="1.62975" y2="18.6894" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#18E299"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint2_linear_115_86" x1="7.94816" y1="8.01562" x2="1.7612" y2="18.746" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint3_radial_115_86" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(8.11404 20.8822) rotate(-75.7542) scale(21.6246 23.7772)">
|
|
||||||
<stop stop-color="#00BBBB"/>
|
|
||||||
<stop offset="0.712616" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint4_linear_115_86" x1="7.60205" y1="5.8709" x2="15.5561" y2="16.3719" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint5_radial_115_86" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.84537 21.5181) rotate(-20.3525) scale(18.5603 17.32)">
|
|
||||||
<stop stop-color="#00B0BB"/>
|
|
||||||
<stop offset="1" stop-color="#00DB65"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint6_linear_115_86" x1="16.8078" y1="13.0071" x2="10.0409" y2="22.9937" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#00B1BC"/>
|
|
||||||
<stop offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint7_linear_115_86" x1="16.8078" y1="13.0071" x2="14.1687" y2="23.841" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop/>
|
|
||||||
<stop offset="1" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 9.0 KiB |
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Login (password)'
|
|
||||||
openapi: 'POST /api/auth/password/login'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Me'
|
|
||||||
openapi: 'GET /api/auth/me'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Register (password)'
|
|
||||||
openapi: 'POST /api/auth/password/register'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Strategies'
|
|
||||||
openapi: 'GET /api/auth/strategies'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Create Entity'
|
|
||||||
openapi: 'POST /api/data/entity/{entity}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Delete Entity'
|
|
||||||
openapi: 'DELETE /api/data/entity/{entity}/{id}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Get Entity'
|
|
||||||
openapi: 'GET /api/data/entity/{entity}/{id}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'List Entity'
|
|
||||||
openapi: 'GET /api/data/entity/{entity}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Update Entity'
|
|
||||||
openapi: 'PATCH /api/data/entity/{entity}/{id}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Create Plant'
|
|
||||||
openapi: 'POST /plants'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Delete Plant'
|
|
||||||
openapi: 'DELETE /plants/{id}'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Get Plants'
|
|
||||||
openapi: 'GET /plants'
|
|
||||||
---
|
|
||||||
@@ -1,391 +0,0 @@
|
|||||||
{
|
|
||||||
"openapi": "3.1.0",
|
|
||||||
"info": { "title": "bknd API", "version": "0.0.0" },
|
|
||||||
"paths": {
|
|
||||||
"/api/system/ping": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Ping",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Pong",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"pong": { "default": true, "type": "boolean" }
|
|
||||||
},
|
|
||||||
"required": ["pong"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["system"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/system/config": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get config",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Config",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"version": { "type": "number" },
|
|
||||||
"server": { "type": "object", "properties": {} },
|
|
||||||
"data": { "type": "object", "properties": {} },
|
|
||||||
"auth": { "type": "object", "properties": {} },
|
|
||||||
"flows": { "type": "object", "properties": {} },
|
|
||||||
"media": { "type": "object", "properties": {} }
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"version",
|
|
||||||
"server",
|
|
||||||
"data",
|
|
||||||
"auth",
|
|
||||||
"flows",
|
|
||||||
"media"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["system"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/system/schema": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get config",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Config",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"version": { "type": "number" },
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"server": { "type": "object", "properties": {} },
|
|
||||||
"data": { "type": "object", "properties": {} },
|
|
||||||
"auth": { "type": "object", "properties": {} },
|
|
||||||
"flows": { "type": "object", "properties": {} },
|
|
||||||
"media": { "type": "object", "properties": {} }
|
|
||||||
},
|
|
||||||
"required": ["server", "data", "auth", "flows", "media"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["version", "schema"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["system"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/data/entity/{entity}": {
|
|
||||||
"get": {
|
|
||||||
"summary": "List entities",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "entity",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "List of entities",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": { "id": { "type": "number" } },
|
|
||||||
"required": ["id"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["data"]
|
|
||||||
},
|
|
||||||
"post": {
|
|
||||||
"summary": "Create entity",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "entity",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": { "type": "object", "properties": {} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Entity",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": { "id": { "type": "number" } },
|
|
||||||
"required": ["id"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["data"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/data/entity/{entity}/{id}": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get entity",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "entity",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "number" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Entity",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": { "id": { "type": "number" } },
|
|
||||||
"required": ["id"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["data"]
|
|
||||||
},
|
|
||||||
"patch": {
|
|
||||||
"summary": "Update entity",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "entity",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "number" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": { "type": "object", "properties": {} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Entity",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": { "id": { "type": "number" } },
|
|
||||||
"required": ["id"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["data"]
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"summary": "Delete entity",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "entity",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "number" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": { "200": { "description": "Entity deleted" } },
|
|
||||||
"tags": ["data"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/auth/password/login": {
|
|
||||||
"post": {
|
|
||||||
"summary": "Login",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"email": { "type": "string" },
|
|
||||||
"password": { "type": "string" }
|
|
||||||
},
|
|
||||||
"required": ["email", "password"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "User",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"user": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": { "type": "string" },
|
|
||||||
"email": { "type": "string" },
|
|
||||||
"name": { "type": "string" }
|
|
||||||
},
|
|
||||||
"required": ["id", "email", "name"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["user"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["auth"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/auth/password/register": {
|
|
||||||
"post": {
|
|
||||||
"summary": "Register",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"email": { "type": "string" },
|
|
||||||
"password": { "type": "string" }
|
|
||||||
},
|
|
||||||
"required": ["email", "password"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "User",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"user": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": { "type": "string" },
|
|
||||||
"email": { "type": "string" },
|
|
||||||
"name": { "type": "string" }
|
|
||||||
},
|
|
||||||
"required": ["id", "email", "name"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["user"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["auth"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/auth/me": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get me",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "User",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"user": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": { "type": "string" },
|
|
||||||
"email": { "type": "string" },
|
|
||||||
"name": { "type": "string" }
|
|
||||||
},
|
|
||||||
"required": ["id", "email", "name"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["user"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["auth"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/auth/strategies": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get auth strategies",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Strategies",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"strategies": { "type": "object", "properties": {} }
|
|
||||||
},
|
|
||||||
"required": ["strategies"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tags": ["auth"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Config'
|
|
||||||
openapi: 'GET /api/system/config'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Ping'
|
|
||||||
openapi: 'GET /api/system/ping'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Schema'
|
|
||||||
openapi: 'GET /api/system/schema'
|
|
||||||
---
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { source } from "@/lib/source";
|
||||||
|
import { DocsPage, DocsBody, DocsDescription, DocsTitle } from "fumadocs-ui/page";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import { createRelativeLink } from "fumadocs-ui/mdx";
|
||||||
|
import { getMDXComponents } from "@/mdx-components";
|
||||||
|
import { LLMCopyButton, ViewOptions } from "@/components/ai/page-actions";
|
||||||
|
|
||||||
|
export default async function Page(props: {
|
||||||
|
params: Promise<{ slug?: string[] }>;
|
||||||
|
}) {
|
||||||
|
const params = await props.params;
|
||||||
|
const page = source.getPage(params.slug);
|
||||||
|
if (!page) notFound();
|
||||||
|
|
||||||
|
const MDXContent = page.data.body;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DocsPage
|
||||||
|
toc={page.data.toc}
|
||||||
|
full={page.data.full}
|
||||||
|
tableOfContent={{
|
||||||
|
style: "clerk",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DocsTitle>{page.data.title}</DocsTitle>
|
||||||
|
<DocsDescription className="mb-0">{page.data.description}</DocsDescription>
|
||||||
|
<div className="flex flex-row gap-2 items-center border-b pt-2 pb-6">
|
||||||
|
<LLMCopyButton markdownUrl={`${page.url}.mdx`} />
|
||||||
|
<ViewOptions
|
||||||
|
markdownUrl={`${page.url}.mdx`}
|
||||||
|
githubUrl={`https://github.com/bknd-io/bknd/blob/dev/apps/docs/content/docs/${page.path}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<DocsBody>
|
||||||
|
<MDXContent
|
||||||
|
components={getMDXComponents({
|
||||||
|
// this allows you to link to other pages with relative file paths
|
||||||
|
a: createRelativeLink(source, page),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</DocsBody>
|
||||||
|
</DocsPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateStaticParams() {
|
||||||
|
return source.generateParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateMetadata(props: {
|
||||||
|
params: Promise<{ slug?: string[] }>;
|
||||||
|
}) {
|
||||||
|
const params = await props.params;
|
||||||
|
const page = source.getPage(params.slug);
|
||||||
|
if (!page) notFound();
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: page.data.title,
|
||||||
|
description: page.data.description,
|
||||||
|
icons: {
|
||||||
|
icon: "/favicon.svg",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { motion } from "motion/react";
|
||||||
|
import {
|
||||||
|
ComponentPropsWithoutRef,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useId,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
import { twMerge as cn } from "tailwind-merge";
|
||||||
|
|
||||||
|
export interface AnimatedGridPatternProps
|
||||||
|
extends ComponentPropsWithoutRef<"svg"> {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
strokeDasharray?: string | number;
|
||||||
|
numSquares?: number;
|
||||||
|
maxOpacity?: number;
|
||||||
|
duration?: number;
|
||||||
|
repeatDelay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AnimatedGridPattern({
|
||||||
|
width = 40,
|
||||||
|
height = 40,
|
||||||
|
x = -1,
|
||||||
|
y = -1,
|
||||||
|
strokeDasharray = 0,
|
||||||
|
numSquares = 50,
|
||||||
|
className,
|
||||||
|
maxOpacity = 0.5,
|
||||||
|
duration = 4,
|
||||||
|
repeatDelay = 0.5,
|
||||||
|
...props
|
||||||
|
}: AnimatedGridPatternProps) {
|
||||||
|
const id = useId();
|
||||||
|
const containerRef = useRef<SVGSVGElement>(null);
|
||||||
|
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
|
const getPos = useCallback(() => {
|
||||||
|
return [
|
||||||
|
Math.floor((Math.random() * dimensions.width) / width),
|
||||||
|
Math.floor((Math.random() * dimensions.height) / height),
|
||||||
|
];
|
||||||
|
}, [dimensions.width, dimensions.height, width, height]);
|
||||||
|
|
||||||
|
const generateSquares = useCallback(
|
||||||
|
(count: number) => {
|
||||||
|
return Array.from({ length: count }, (_, i) => ({
|
||||||
|
id: i,
|
||||||
|
pos: getPos(),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
[getPos],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [squares, setSquares] = useState(() => generateSquares(numSquares));
|
||||||
|
|
||||||
|
const updateSquarePosition = (id: number) => {
|
||||||
|
setSquares((currentSquares) =>
|
||||||
|
currentSquares.map((sq) =>
|
||||||
|
sq.id === id
|
||||||
|
? {
|
||||||
|
...sq,
|
||||||
|
pos: getPos(),
|
||||||
|
}
|
||||||
|
: sq,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dimensions.width && dimensions.height) {
|
||||||
|
setSquares(generateSquares(numSquares));
|
||||||
|
}
|
||||||
|
}, [dimensions, numSquares, generateSquares]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const current = containerRef.current;
|
||||||
|
if (!current) return;
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
setDimensions({
|
||||||
|
width: entry.contentRect.width,
|
||||||
|
height: entry.contentRect.height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.observe(current);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.unobserve(current);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
ref={containerRef}
|
||||||
|
aria-hidden="true"
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute inset-0 h-full w-full",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id={id}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={`M.5 ${height}V.5H${width}`}
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeDasharray={strokeDasharray}
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect width="100%" height="100%" fill={`url(#${id})`} />
|
||||||
|
<svg x={x} y={y} className="overflow-visible">
|
||||||
|
{squares.map(({ pos: [x, y], id }, index) => (
|
||||||
|
<motion.rect
|
||||||
|
key={`${x}-${y}-${index}`}
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: maxOpacity }}
|
||||||
|
transition={{
|
||||||
|
duration,
|
||||||
|
repeat: 1,
|
||||||
|
delay: index * 0.1,
|
||||||
|
repeatDelay,
|
||||||
|
repeatType: "reverse",
|
||||||
|
}}
|
||||||
|
onAnimationComplete={() => updateSquarePosition(id)}
|
||||||
|
width={width - 1}
|
||||||
|
height={height - 1}
|
||||||
|
x={x * width + 1}
|
||||||
|
y={y * height + 1}
|
||||||
|
fill="currentColor"
|
||||||
|
strokeWidth="0"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
export function CalloutCaution({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl my-4 px-4 py-3 flex gap-3 border bg-yellow-50 border-yellow-200 text-yellow-900 dark:bg-yellow-900/15 dark:border-yellow-900 dark:text-yellow-100 [&>div>p]:m-0">
|
||||||
|
<div className="pt-1.5 text-yellow-500 dark:text-yellow-100">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="-2 -2 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10s-4.477 10-10 10m0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16m0-13a1 1 0 0 1 1 1v5a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1m0 10a1 1 0 1 1 0-2a1 1 0 0 1 0 2" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{title && <span className="font-semibold">{title}</span>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
export function CalloutDanger({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl my-4 px-4 py-3 flex gap-3 border bg-red-50 border-red-200 text-red-900 dark:bg-red-900/15 dark:border-red-900 dark:text-red-100 [&>div>p]:m-0">
|
||||||
|
<div className="pt-1.5 text-red-500 dark:text-red-100">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M16.34 9.322a1 1 0 1 0-1.364-1.463l-2.926 2.728L9.322 7.66A1 1 0 0 0 7.86 9.024l2.728 2.926l-2.927 2.728a1 1 0 1 0 1.364 1.462l2.926-2.727l2.728 2.926a1 1 0 1 0 1.462-1.363l-2.727-2.926z" />
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12m11 9a9 9 0 1 1 0-18a9 9 0 0 1 0 18"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{title && <span className="font-semibold">{title}</span>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
export function CalloutInfo({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl my-4 px-4 py-3 flex gap-3 border bg-blue-50 border-blue-200 text-blue-900 dark:bg-blue-900/15 dark:border-blue-900 dark:text-blue-100 [&>div>p]:m-0">
|
||||||
|
<div className="pt-1.5 text-blue-500 dark:text-blue-100">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={18}
|
||||||
|
height={18}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path d="M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8 8-8s8 3.59 8 8s-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{title && <span className="font-semibold">{title}</span>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
export function CalloutPositive({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl my-4 px-4 py-3 flex gap-3 border bg-green-50 border-green-200 text-green-900 dark:bg-green-900/15 dark:border-green-900 dark:text-green-100 [&>div>p]:m-0">
|
||||||
|
<div className="pt-1.5 text-green-500 dark:text-green-100">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<g fill="none" fillRule="evenodd">
|
||||||
|
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M21.546 5.111a1.5 1.5 0 0 1 0 2.121L10.303 18.475a1.6 1.6 0 0 1-2.263 0L2.454 12.89a1.5 1.5 0 1 1 2.121-2.121l4.596 4.596L19.424 5.111a1.5 1.5 0 0 1 2.122 0"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{title && <span className="font-semibold">{title}</span>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export { CalloutPositive } from "./CalloutPositive";
|
||||||
|
export { CalloutCaution } from "./CalloutCaution";
|
||||||
|
export { CalloutDanger } from "./CalloutDanger";
|
||||||
|
export { CalloutInfo } from "./CalloutInfo";
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { ThemeToggle } from "fumadocs-ui/components/layout/theme-toggle";
|
||||||
|
|
||||||
|
export function FooterIcons() {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-between items-center w-full px-2">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<a
|
||||||
|
href="https://github.com/bknd-io/bknd"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label="GitHub"
|
||||||
|
className="text-fd-muted-foreground hover:text-fd-accent-foreground"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="w-6 h-6"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://discord.gg/952SFk8Tb8"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label="Discord"
|
||||||
|
className="text-fd-muted-foreground hover:text-fd-accent-foreground"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="w-6.5 h-6.5"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M18.942 5.556a16.3 16.3 0 0 0-4.126-1.3a12 12 0 0 0-.529 1.1a15.2 15.2 0 0 0-4.573 0a12 12 0 0 0-.535-1.1a16.3 16.3 0 0 0-4.129 1.3a17.4 17.4 0 0 0-2.868 11.662a15.8 15.8 0 0 0 4.963 2.521q.616-.847 1.084-1.785a10.6 10.6 0 0 1-1.706-.83q.215-.16.418-.331a11.66 11.66 0 0 0 10.118 0q.206.172.418.331q-.817.492-1.71.832a12.6 12.6 0 0 0 1.084 1.785a16.5 16.5 0 0 0 5.064-2.595a17.3 17.3 0 0 0-2.973-11.59M8.678 14.813a1.94 1.94 0 0 1-1.8-2.045a1.93 1.93 0 0 1 1.8-2.047a1.92 1.92 0 0 1 1.8 2.047a1.93 1.93 0 0 1-1.8 2.045m6.644 0a1.94 1.94 0 0 1-1.8-2.045a1.93 1.93 0 0 1 1.8-2.047a1.92 1.92 0 0 1 1.8 2.047a1.93 1.93 0 0 1-1.8 2.045"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ThemeToggle className="p-0" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export function Logo() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Image
|
||||||
|
src="/logo/bknd_logo_white.svg"
|
||||||
|
alt="bknd logo"
|
||||||
|
width={110}
|
||||||
|
height={24}
|
||||||
|
className="hidden dark:block pl-1.5"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="/logo/bknd_logo_black.svg"
|
||||||
|
alt="bknd logo"
|
||||||
|
width={110}
|
||||||
|
height={24}
|
||||||
|
className="block dark:hidden pl-1.5"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { create } from "@orama/orama";
|
||||||
|
import { useDocsSearch } from "fumadocs-core/search/client";
|
||||||
|
import {
|
||||||
|
SearchDialog,
|
||||||
|
SearchDialogClose,
|
||||||
|
SearchDialogContent,
|
||||||
|
SearchDialogFooter,
|
||||||
|
SearchDialogHeader,
|
||||||
|
SearchDialogIcon,
|
||||||
|
SearchDialogInput,
|
||||||
|
SearchDialogList,
|
||||||
|
SearchDialogOverlay,
|
||||||
|
type SharedProps,
|
||||||
|
} from "fumadocs-ui/components/dialog/search";
|
||||||
|
import { useI18n } from "fumadocs-ui/contexts/i18n";
|
||||||
|
|
||||||
|
function initOrama() {
|
||||||
|
return create({
|
||||||
|
schema: { _: "string" },
|
||||||
|
// https://docs.orama.com/open-source/supported-languages
|
||||||
|
language: "english",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DefaultSearchDialog(props: SharedProps) {
|
||||||
|
const { locale } = useI18n(); // (optional) for i18n
|
||||||
|
const { search, setSearch, query } = useDocsSearch({
|
||||||
|
type: "static",
|
||||||
|
initOrama,
|
||||||
|
locale,
|
||||||
|
from: "/api/search",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SearchDialog
|
||||||
|
search={search}
|
||||||
|
onSearchChange={setSearch}
|
||||||
|
isLoading={query.isLoading}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SearchDialogOverlay />
|
||||||
|
<SearchDialogContent>
|
||||||
|
<SearchDialogHeader>
|
||||||
|
<SearchDialogIcon />
|
||||||
|
<SearchDialogInput />
|
||||||
|
<SearchDialogClose />
|
||||||
|
</SearchDialogHeader>
|
||||||
|
|
||||||
|
<SearchDialogList items={query.data !== "empty" ? query.data : null} />
|
||||||
|
|
||||||
|
<SearchDialogFooter>
|
||||||
|
<div className="flex w-full">
|
||||||
|
<a
|
||||||
|
href="https://orama.com"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
className="ml-auto text-xs text-nowrap text-fd-muted-foreground"
|
||||||
|
>
|
||||||
|
Powered by Orama
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</SearchDialogFooter>
|
||||||
|
</SearchDialogContent>
|
||||||
|
</SearchDialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { create } from "@orama/orama";
|
||||||
|
import { clsx } from "clsx";
|
||||||
|
import { useDocsSearch } from "fumadocs-core/search/client";
|
||||||
|
import {
|
||||||
|
SearchDialog,
|
||||||
|
SearchDialogClose,
|
||||||
|
SearchDialogContent,
|
||||||
|
SearchDialogFooter,
|
||||||
|
SearchDialogHeader,
|
||||||
|
SearchDialogIcon,
|
||||||
|
SearchDialogInput,
|
||||||
|
SearchDialogList,
|
||||||
|
SearchDialogOverlay,
|
||||||
|
type SharedProps,
|
||||||
|
} from "fumadocs-ui/components/dialog/search";
|
||||||
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "fumadocs-ui/components/ui/popover";
|
||||||
|
import { ChevronDown } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
function initOrama() {
|
||||||
|
return create({
|
||||||
|
schema: {
|
||||||
|
_: "string",
|
||||||
|
title: "string",
|
||||||
|
description: "string",
|
||||||
|
url: "string",
|
||||||
|
tags: "string[]",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagItems = [
|
||||||
|
{
|
||||||
|
name: "All",
|
||||||
|
value: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Documentation",
|
||||||
|
description: "Developer documentation",
|
||||||
|
value: "documentation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Guide",
|
||||||
|
description: "User Guide",
|
||||||
|
value: "guide",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OpenAPI",
|
||||||
|
description: "OpenAPI Reference",
|
||||||
|
value: "openapi",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function DefaultSearchDialog(props: SharedProps) {
|
||||||
|
const [tag, setTag] = useState<string>();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const { search, setSearch, query } = useDocsSearch({
|
||||||
|
type: "static",
|
||||||
|
initOrama,
|
||||||
|
tag,
|
||||||
|
from: "/api/search",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SearchDialog
|
||||||
|
search={search}
|
||||||
|
onSearchChange={setSearch}
|
||||||
|
isLoading={query.isLoading}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SearchDialogOverlay />
|
||||||
|
<SearchDialogContent>
|
||||||
|
<SearchDialogHeader>
|
||||||
|
<SearchDialogIcon />
|
||||||
|
<SearchDialogInput />
|
||||||
|
<SearchDialogClose />
|
||||||
|
</SearchDialogHeader>
|
||||||
|
|
||||||
|
<SearchDialogList items={query.data !== "empty" ? query.data : null} />
|
||||||
|
|
||||||
|
<SearchDialogFooter className="flex flex-row flex-wrap gap-2 items-center">
|
||||||
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
|
<PopoverTrigger
|
||||||
|
className={buttonVariants({
|
||||||
|
size: "sm",
|
||||||
|
color: "ghost",
|
||||||
|
className: "-m-1.5 me-auto",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<span className="text-fd-muted-foreground/80 me-2">Filter</span>
|
||||||
|
{tagItems.find((item) => item.value === tag)?.name ?? "All"}
|
||||||
|
<ChevronDown className="size-3.5 text-fd-muted-foreground" />
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="flex flex-col p-1 gap-1" align="start">
|
||||||
|
{tagItems.map((item, i) => {
|
||||||
|
const isSelected = item.value === tag;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => {
|
||||||
|
setTag(item.value);
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
className={clsx(
|
||||||
|
"rounded-lg text-start px-2 py-1.5",
|
||||||
|
isSelected
|
||||||
|
? "text-fd-primary bg-fd-primary/10"
|
||||||
|
: "hover:text-fd-accent-foreground hover:bg-fd-accent",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p className="font-medium mb-0.5">{item.name}</p>
|
||||||
|
<p className="text-xs opacity-70">{item.description}</p>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<a
|
||||||
|
href="https://orama.com"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
className="text-xs text-nowrap text-fd-muted-foreground"
|
||||||
|
>
|
||||||
|
Powered by Orama
|
||||||
|
</a>
|
||||||
|
</SearchDialogFooter>
|
||||||
|
</SearchDialogContent>
|
||||||
|
</SearchDialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export const examples = {
|
||||||
|
adminRich: {
|
||||||
|
path: "github/bknd-io/bknd-examples",
|
||||||
|
startScript: "example-admin-rich",
|
||||||
|
initialPath: "/data/schema"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StackBlitz = ({
|
||||||
|
path,
|
||||||
|
ratio = 9 / 16,
|
||||||
|
example,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
path?: string;
|
||||||
|
ratio?: number;
|
||||||
|
example?: keyof typeof examples;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}) => {
|
||||||
|
const selected = example ? examples[example] : undefined;
|
||||||
|
const finalPath = path || selected?.path || "github/bknd-io/bknd-examples";
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
ctl: "1",
|
||||||
|
hideExplorer: "1",
|
||||||
|
embed: "1",
|
||||||
|
view: "preview",
|
||||||
|
...(selected || {}),
|
||||||
|
...props
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = new URL(
|
||||||
|
`https://stackblitz.com/${finalPath}?${params.toString()}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
overflow: "hidden",
|
||||||
|
width: "100%",
|
||||||
|
paddingTop: `${ratio * 100}%`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
src={url.toString()}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
bottom: 0,
|
||||||
|
right: 0,
|
||||||
|
border: "none"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "80%",
|
||||||
|
opacity: 0.7,
|
||||||
|
marginTop: "0.2rem",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
textAlign: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
If you’re having issues viewing it inline,{" "}
|
||||||
|
<a href={url.toString()} target="_blank" rel="noreferrer">
|
||||||
|
try in a new tab
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { source } from "@/lib/source";
|
||||||
|
import { createFromSource } from "fumadocs-core/search/server";
|
||||||
|
|
||||||
|
export const revalidate = false;
|
||||||
|
export const { staticGET: GET } = createFromSource(source);
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
@import "fumadocs-ui/css/neutral.css";
|
||||||
|
@import "fumadocs-ui/css/preset.css";
|
||||||
|
@import "fumadocs-openapi/css/preset.css";
|
||||||
|
@import "fumadocs-twoslash/twoslash.css";
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--color-fd-primary: #008001;
|
||||||
|
--color-fd-primary-foreground: #000000;
|
||||||
|
--tw-prose-links: #008001;
|
||||||
|
--tw-prose-code: #008001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--color-fd-primary: #4ec9b0;
|
||||||
|
--color-fd-primary-foreground: #000000;
|
||||||
|
--tw-prose-links: #4ec9b0;
|
||||||
|
--tw-prose-code: #4ec9b0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
|
||||||
|
import { Logo } from "@/app/_components/Logo";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared layout configurations
|
||||||
|
*
|
||||||
|
* you can customise layouts individually from:
|
||||||
|
* Home Layout: app/(home)/layout.tsx
|
||||||
|
* Docs Layout: app/docs/layout.tsx
|
||||||
|
*/
|
||||||
|
export const baseOptions: BaseLayoutProps = {
|
||||||
|
nav: {
|
||||||
|
title: <Logo />,
|
||||||
|
},
|
||||||
|
// see https://fumadocs.dev/docs/ui/navigation/links
|
||||||
|
links: [],
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import "./global.css";
|
||||||
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||||
|
import { baseOptions } from "./layout.config";
|
||||||
|
import { source } from "@/lib/source";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import { Provider } from "./provider";
|
||||||
|
import { AnimatedGridPattern } from "./_components/AnimatedGridPattern";
|
||||||
|
import { FooterIcons } from "./_components/FooterIcons";
|
||||||
|
|
||||||
|
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<html lang="en" suppressHydrationWarning>
|
||||||
|
<body className="relative bg-background">
|
||||||
|
<div className="absolute top-0 inset-x-0 h-[300px] -z-10 pointer-events-none [mask-image:linear-gradient(to_bottom,black,transparent)]">
|
||||||
|
<AnimatedGridPattern className="h-full w-full opacity-15 dark:opacity-10 text-[var(--color-fd-primary)] dark:text-[var(--color-fd-primary)]" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Provider>
|
||||||
|
<DocsLayout
|
||||||
|
tree={source.pageTree}
|
||||||
|
nav={{ ...baseOptions.nav }}
|
||||||
|
themeSwitch={{
|
||||||
|
enabled: true,
|
||||||
|
component: <FooterIcons />,
|
||||||
|
mode: "light-dark",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DocsLayout>
|
||||||
|
</Provider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { source } from "@/lib/source";
|
||||||
|
import { getLLMText } from "@/lib/get-llm-text";
|
||||||
|
|
||||||
|
// cached forever
|
||||||
|
export const revalidate = false;
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const scan = source.getPages().map(getLLMText);
|
||||||
|
const scanned = await Promise.all(scan);
|
||||||
|
|
||||||
|
return new Response(scanned.join("\n\n"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { type NextRequest, NextResponse } from "next/server";
|
||||||
|
import { getLLMText } from "@/lib/get-llm-text";
|
||||||
|
import { source } from "@/lib/source";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
|
export const revalidate = false;
|
||||||
|
|
||||||
|
export async function GET(_req: NextRequest, { params }: { params: Promise<{ slug?: string[] }> }) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const page = source.getPage(slug);
|
||||||
|
if (!page) notFound();
|
||||||
|
|
||||||
|
return new NextResponse(await getLLMText(page));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateStaticParams() {
|
||||||
|
return source.generateParams();
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
"use client";
|
||||||
|
import { RootProvider } from "fumadocs-ui/provider";
|
||||||
|
import Search from "./_components/Search";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
export function Provider({ children }: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<RootProvider search={{ SearchDialog: Search }}>{children}</RootProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
"use client";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { Check, ChevronDown, Copy, ExternalLinkIcon } from "lucide-react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
|
||||||
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from "fumadocs-ui/components/ui/popover";
|
||||||
|
import { cva } from "class-variance-authority";
|
||||||
|
|
||||||
|
const cache = new Map<string, string>();
|
||||||
|
|
||||||
|
export function LLMCopyButton({
|
||||||
|
/**
|
||||||
|
* A URL to fetch the raw Markdown/MDX content of page
|
||||||
|
*/
|
||||||
|
markdownUrl,
|
||||||
|
}: {
|
||||||
|
markdownUrl: string;
|
||||||
|
}) {
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const [checked, onClick] = useCopyButton(async () => {
|
||||||
|
const cached = cache.get(markdownUrl);
|
||||||
|
if (cached) return navigator.clipboard.writeText(cached);
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.write([
|
||||||
|
new ClipboardItem({
|
||||||
|
"text/plain": fetch(markdownUrl).then(async (res) => {
|
||||||
|
const content = await res.text();
|
||||||
|
cache.set(markdownUrl, content);
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
disabled={isLoading}
|
||||||
|
className={cn(
|
||||||
|
buttonVariants({
|
||||||
|
color: "secondary",
|
||||||
|
size: "sm",
|
||||||
|
className: "gap-2 [&_svg]:size-3.5 [&_svg]:text-fd-muted-foreground",
|
||||||
|
}),
|
||||||
|
)}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{checked ? <Check /> : <Copy />}
|
||||||
|
Copy Markdown
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionVariants = cva(
|
||||||
|
"text-sm p-2 rounded-lg inline-flex items-center gap-2 hover:text-fd-accent-foreground hover:bg-fd-accent [&_svg]:size-4",
|
||||||
|
);
|
||||||
|
|
||||||
|
export function ViewOptions({
|
||||||
|
markdownUrl,
|
||||||
|
githubUrl,
|
||||||
|
}: {
|
||||||
|
/**
|
||||||
|
* A URL to the raw Markdown/MDX content of page
|
||||||
|
*/
|
||||||
|
markdownUrl: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source file URL on GitHub
|
||||||
|
*/
|
||||||
|
githubUrl: string;
|
||||||
|
}) {
|
||||||
|
const items = useMemo(() => {
|
||||||
|
const fullMarkdownUrl =
|
||||||
|
typeof window !== "undefined" ? new URL(markdownUrl, window.location.origin) : "loading";
|
||||||
|
const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`;
|
||||||
|
|
||||||
|
return [
|
||||||
|
/* {
|
||||||
|
title: "Open in GitHub",
|
||||||
|
href: githubUrl,
|
||||||
|
icon: (
|
||||||
|
<svg fill="currentColor" role="img" viewBox="0 0 24 24">
|
||||||
|
<title>GitHub</title>
|
||||||
|
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
}, */
|
||||||
|
{
|
||||||
|
title: "Open in ChatGPT",
|
||||||
|
href: `https://chatgpt.com/?${new URLSearchParams({
|
||||||
|
hints: "search",
|
||||||
|
q,
|
||||||
|
})}`,
|
||||||
|
icon: (
|
||||||
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<title>OpenAI</title>
|
||||||
|
<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Open in Claude",
|
||||||
|
href: `https://claude.ai/new?${new URLSearchParams({
|
||||||
|
q,
|
||||||
|
})}`,
|
||||||
|
icon: (
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<title>Anthropic</title>
|
||||||
|
<path d="M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [githubUrl, markdownUrl]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger
|
||||||
|
className={cn(
|
||||||
|
buttonVariants({
|
||||||
|
color: "secondary",
|
||||||
|
size: "sm",
|
||||||
|
className: "gap-2",
|
||||||
|
}),
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Open
|
||||||
|
<ChevronDown className="size-3.5 text-fd-muted-foreground" />
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="flex flex-col overflow-auto">
|
||||||
|
{items.map((item) => (
|
||||||
|
<a
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
className={cn(optionVariants())}
|
||||||
|
>
|
||||||
|
{item.icon}
|
||||||
|
{item.title}
|
||||||
|
<ExternalLinkIcon className="text-fd-muted-foreground size-3.5 ms-auto" />
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Concepts"
|
|
||||||
---
|
|
||||||
|
|
||||||
There are a few important concepts around **bknd** you should be aware of in order to understand
|
|
||||||
it better.
|
|
||||||
|
|
||||||
## Primitive
|
|
||||||
Instead of going to deep into specific use-cases, **bknd** is designed to implement the lower
|
|
||||||
level functionalities in order to provide a solid foundation for building more complex logic.
|
|
||||||
|
|
||||||
## Minimal database
|
|
||||||
Although we focus on SQL-databases, we follow the priciple of moving as much logic as possible to
|
|
||||||
the application layer. E.g. default values are computed application side instead
|
|
||||||
of instruction the database to do so. This enables us to support a wide range of databases in
|
|
||||||
the future.
|
|
||||||
|
|
||||||
## Lowest runtime first
|
|
||||||
The main development target is Cloudflare Workers, since it's the most limited JavaScript
|
|
||||||
runtime built on Web Standards. If it runs there, it will run (probably) anywhere.
|
|
||||||
|
|
||||||
## Web Standards
|
|
||||||
...
|
|
||||||
+59
-53
@@ -1,24 +1,25 @@
|
|||||||
---
|
---
|
||||||
title: bknd.config.ts
|
title: bknd.config.ts
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
The central configuration file to extend bknd should be placed in the root of your project, so that the [CLI](/usage/cli#using-configuration-file-bknd-config) can automatically pick it up. It allows to:
|
The central configuration file to extend bknd should be placed in the root of your project, so that the [CLI](/usage/cli#using-configuration-file-bknd-config) can automatically pick it up. It allows to:
|
||||||
* define your database connection centrally
|
|
||||||
* pass in initial configuration or data seeds when booting the first time
|
|
||||||
* add plugins to the app
|
|
||||||
* hook into system events
|
|
||||||
* define custom routes and endpoints
|
|
||||||
|
|
||||||
|
- define your database connection centrally
|
||||||
|
- pass in [initial configuration](/usage/database#initial-structure) or [data seeds](/usage/database#seeding-the-database) when booting the first time
|
||||||
|
- add plugins to the app
|
||||||
|
- hook into system events
|
||||||
|
- define custom routes and endpoints
|
||||||
|
|
||||||
A simple example of a `bknd.config.ts` file:
|
A simple example of a `bknd.config.ts` file:
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { BkndConfig } from "bknd/adapter";
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db",
|
url: "file:data.db",
|
||||||
}
|
},
|
||||||
} satisfies BkndConfig;
|
} satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -26,57 +27,62 @@ export default {
|
|||||||
|
|
||||||
The `BkndConfig` extends the [`CreateAppConfig`](/usage/introduction#configuration-createappconfig) type with the following properties:
|
The `BkndConfig` extends the [`CreateAppConfig`](/usage/introduction#configuration-createappconfig) type with the following properties:
|
||||||
|
|
||||||
|
{/* <AutoTypeTable path="../app/src/adapter/index.ts" name="BkndConfig" /> */}
|
||||||
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export type BkndConfig = CreateAppConfig & {
|
export type BkndConfig = CreateAppConfig & {
|
||||||
// return the app configuration as object or from a function
|
// return the app configuration as object or from a function
|
||||||
app?: CreateAppConfig | ((args: Args) => CreateAppConfig);
|
app?: CreateAppConfig | ((args: Args) => CreateAppConfig);
|
||||||
// called before the app is built
|
// called before the app is built
|
||||||
beforeBuild?: (app: App) => Promise<void>;
|
beforeBuild?: (app: App) => Promise<void>;
|
||||||
// called after the app has been built
|
// called after the app has been built
|
||||||
onBuilt?: (app: App) => Promise<void>;
|
onBuilt?: (app: App) => Promise<void>;
|
||||||
// passed as the first argument to the `App.build` method
|
// passed as the first argument to the `App.build` method
|
||||||
buildConfig?: Parameters<App["build"]>[0];
|
buildConfig?: Parameters<App["build"]>[0];
|
||||||
// force the app to be recreated
|
// force the app to be recreated
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
// the id of the app, defaults to `app`
|
// the id of the app, defaults to `app`
|
||||||
id?: string;
|
id?: string;
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
The supported configuration file extensions are `js`, `ts`, `mjs`, `cjs` and `json`. Throughout the documentation, we'll use `ts` for the file extension.
|
The supported configuration file extensions are `js`, `ts`, `mjs`, `cjs` and `json`. Throughout the documentation, we'll use `ts` for the file extension.
|
||||||
|
|
||||||
### `app` (CreateAppConfig)
|
### `app` (CreateAppConfig)
|
||||||
|
|
||||||
The `app` property is a function that returns a `CreateAppConfig` object. It allows to pass in the environment variables to the configuration object.
|
The `app` property is a function that returns a `CreateAppConfig` object. It allows to pass in the environment variables to the configuration object.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { BkndConfig } from "bknd/adapter";
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
app: ({ env }) => ({
|
app: ({ env }) => ({
|
||||||
connection: {
|
connection: {
|
||||||
url: env.DB_URL,
|
url: env.DB_URL,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
} satisfies BkndConfig;
|
} satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
See [Database](/usage/database) for more information on how to configure the database connection.
|
See [Database](/usage/database) for more information on how to configure the database connection.
|
||||||
|
|
||||||
### `beforeBuild`
|
### `beforeBuild`
|
||||||
|
|
||||||
The `beforeBuild` property is an async function that is called before the app is built. It allows to modify the app instance that may influence the build process.
|
The `beforeBuild` property is an async function that is called before the app is built. It allows to modify the app instance that may influence the build process.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { BkndConfig } from "bknd/adapter";
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
beforeBuild: async (app: App) => {
|
beforeBuild: async (app: App) => {
|
||||||
// do something that has to happen before the app is built
|
// do something that has to happen before the app is built
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### `onBuilt`
|
### `onBuilt`
|
||||||
|
|
||||||
The `onBuilt` property is an async function that is called after the app has been built. It allows to hook into the app after it has been built. This is useful for defining event listeners or register custom routes, as both the event manager and the server are recreated during the build process.
|
The `onBuilt` property is an async function that is called after the app has been built. It allows to hook into the app after it has been built. This is useful for defining event listeners or register custom routes, as both the event manager and the server are recreated during the build process.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@@ -84,21 +90,22 @@ import { type App, AppEvents } from "bknd";
|
|||||||
import type { BkndConfig } from "bknd/adapter";
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
onBuilt: async (app: App) => {
|
onBuilt: async (app: App) => {
|
||||||
console.log("App built", app.version());
|
console.log("App built", app.version());
|
||||||
|
|
||||||
// registering an event listener
|
// registering an event listener
|
||||||
app.emgr.onEvent(AppEvents.AppRequest, (event) => {
|
app.emgr.onEvent(AppEvents.AppRequest, (event) => {
|
||||||
console.log("Request received", event.request.url);
|
console.log("Request received", event.request.url);
|
||||||
})
|
});
|
||||||
|
|
||||||
// registering a custom route
|
// registering a custom route
|
||||||
app.server.get("/hello", (c) => c.text("Hello World"));
|
app.server.get("/hello", (c) => c.text("Hello World"));
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### `force` & `id`
|
### `force` & `id`
|
||||||
|
|
||||||
The `force` property is a boolean that forces the app to be recreated. This is mainly useful for serverless environments where the execution environment is re-used, and you may or may not want to recreate the app on every request.
|
The `force` property is a boolean that forces the app to be recreated. This is mainly useful for serverless environments where the execution environment is re-used, and you may or may not want to recreate the app on every request.
|
||||||
|
|
||||||
The `id` property is the reference in a cache map. You may create multiple instances of apps in the same process by using different ids (e.g. multi tenant applications).
|
The `id` property is the reference in a cache map. You may create multiple instances of apps in the same process by using different ids (e.g. multi tenant applications).
|
||||||
@@ -113,12 +120,12 @@ Depending on which framework or runtime you're using to run bknd, the configurat
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export type RuntimeBkndConfig<Args = any> = BkndConfig<Args> & {
|
export type RuntimeBkndConfig<Args = any> = BkndConfig<Args> & {
|
||||||
// the path to the dist folder to serve static assets for the admin UI
|
// the path to the dist folder to serve static assets for the admin UI
|
||||||
distPath?: string;
|
distPath?: string;
|
||||||
// custom middleware to serve static assets for the admin UI
|
// custom middleware to serve static assets for the admin UI
|
||||||
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
||||||
// options for the admin UI
|
// options for the admin UI
|
||||||
adminOptions?: AdminControllerOptions | false;
|
adminOptions?: AdminControllerOptions | false;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -129,13 +136,12 @@ export type RuntimeBkndConfig<Args = any> = BkndConfig<Args> & {
|
|||||||
```typescript
|
```typescript
|
||||||
type NextjsEnv = NextApiRequest["env"];
|
type NextjsEnv = NextApiRequest["env"];
|
||||||
export type NextjsBkndConfig<Env = NextjsEnv> = FrameworkBkndConfig<Env> & {
|
export type NextjsBkndConfig<Env = NextjsEnv> = FrameworkBkndConfig<Env> & {
|
||||||
cleanRequest?: { searchParams?: string[] };
|
cleanRequest?: { searchParams?: string[] };
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Next.js adds the mounted path to the request object, so that the `cleanRequest` property can be used to remove the mounted path from the request URL. See other frameworks for more information on how to configure them.
|
Next.js adds the mounted path to the request object, so that the `cleanRequest` property can be used to remove the mounted path from the request URL. See other frameworks for more information on how to configure them.
|
||||||
|
|
||||||
|
|
||||||
## Using the configuration file
|
## Using the configuration file
|
||||||
|
|
||||||
The configuration file is automatically picked up if you're using the [CLI](/usage/cli). This allows interacting with your application using the `bknd` command. For example, you can run the following command in the root of your project to start an instance:
|
The configuration file is automatically picked up if you're using the [CLI](/usage/cli). This allows interacting with your application using the `bknd` command. For example, you can run the following command in the root of your project to start an instance:
|
||||||
@@ -150,4 +156,4 @@ When serving your application, you need to make sure to import the contents of y
|
|||||||
2. create a `bknd.ts` file inside your app folder which exports helper functions to instantiate the bknd instance and retrieve the API.
|
2. create a `bknd.ts` file inside your app folder which exports helper functions to instantiate the bknd instance and retrieve the API.
|
||||||
3. create a catch-all route file at `src/api/[[...bknd]]/route.ts` which serves the bknd API.
|
3. create a catch-all route file at `src/api/[[...bknd]]/route.ts` which serves the bknd API.
|
||||||
|
|
||||||
This way, your application and the CLI are using the same configuration.
|
This way, your application and the CLI are using the same configuration.
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
---
|
||||||
|
title: Events & Hooks
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
bknd comes with a powerful built-in event system that allows you to hook into the app lifecycle and extend its functionality. You can hook into these events in two ways:
|
||||||
|
|
||||||
|
- `async`: Your listener is not blocking the main execution flow. E.g. on Cloudflare Workers, by default, the `ExecutionContext`'s `waitUntil` method is used so that the listeners runs after the response is sent.
|
||||||
|
- `sync`: Your listener is blocking the main execution flow. This allows to abort the request in your custom conditions. Some events also allow to return a modified event payload.
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
Don't mistake `async` with JavaScript's `async` keyword. The `async` keyword
|
||||||
|
is used to indicate that the listener is not blocking the main execution flow.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
### Listening to events
|
||||||
|
|
||||||
|
You can listen to events by using the `EventManager` exposed at `app.emgr`. To register a listener, you can use either of these methods:
|
||||||
|
|
||||||
|
- `onEvent`: Register a listener for a specific event with a typed event.
|
||||||
|
- `on`: Register a listener for an event by its slug.
|
||||||
|
- `onAny`: Register a listener for all events.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createApp, AppEvents } from "bknd";
|
||||||
|
const app = createApp();
|
||||||
|
|
||||||
|
app.emgr.onEvent(AppEvents.AppRequest, async (event) => {
|
||||||
|
// ^? AppRequest
|
||||||
|
console.log("Request received", event.request.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.emgr.on("app-request", async (event) => {
|
||||||
|
console.log("Request received", event.request.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.emgr.onAny(async (event) => {
|
||||||
|
console.log("Event received", event.slug);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You may want to register your listeners inside [`bknd.config.ts`](/extending/config) to make sure they are registered before the app is built:
|
||||||
|
|
||||||
|
```typescript title="bknd.config.ts"
|
||||||
|
import { AppEvents } from "bknd";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
onBuilt: (app) => {
|
||||||
|
app.emgr.onEvent(AppEvents.AppRequest, async (event) => {
|
||||||
|
console.log("Request received", event.request.url);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting a mode
|
||||||
|
|
||||||
|
By default, listeners are registered as `async` listeners, meaning that the listener is not blocking the main execution flow. You can change this by passing the mode as the third argument:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
app.emgr.onEvent(
|
||||||
|
AppEvents.AppRequest,
|
||||||
|
async (event) => {
|
||||||
|
console.log("Request received", event.request.url);
|
||||||
|
},
|
||||||
|
{ mode: "sync" },
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This works for all three methods.
|
||||||
|
|
||||||
|
## App Events
|
||||||
|
|
||||||
|
These events are emitted by the `App` class and are available on the `AppEvents` object.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { AppEvents } from "bknd";
|
||||||
|
```
|
||||||
|
|
||||||
|
Available events:
|
||||||
|
|
||||||
|
{/* <AutoTypeTable path="../app/src/App.ts" name="AppEvents" /> */}
|
||||||
|
| Event | Params | Description |
|
||||||
|
|:------|:--------|:------------|
|
||||||
|
| `AppConfigUpdatedEvent` | `{ app: App }` | Emitted when the app configuration is updated |
|
||||||
|
| `AppBuiltEvent` | `{ app: App }` | Emitted when the app is built |
|
||||||
|
| `AppFirstBoot` | `{ app: App }` | Emitted when the app is first booted |
|
||||||
|
| `AppRequest` | `{ app: App, request: Request }` | Emitted when a request is received |
|
||||||
|
| `AppBeforeResponse` | `{ app: App, request: Request, response: Response }` | Emitted before a response is sent |
|
||||||
|
|
||||||
|
## Database Events
|
||||||
|
|
||||||
|
These events are emitted by the `Database` class and are available on the `DatabaseEvents` object. These are divided by events triggered by the `Mutator` and `Repository` classes.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { DatabaseEvents } from "bknd";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mutator Events
|
||||||
|
|
||||||
|
These events are emitted during database mutations (insert, update, delete operations).
|
||||||
|
|
||||||
|
| Event | Params | Description |
|
||||||
|
| :-------------------- | :-------------------------------------------------------------------------------------- | :---------------------------------------------------------- |
|
||||||
|
| `MutatorInsertBefore` | `{ entity: Entity, data: EntityData }` | Emitted before inserting a new record. Can modify the data. |
|
||||||
|
| `MutatorInsertAfter` | `{ entity: Entity, data: EntityData, changed: EntityData }` | Emitted after inserting a new record. |
|
||||||
|
| `MutatorUpdateBefore` | `{ entity: Entity, entityId: PrimaryFieldType, data: EntityData }` | Emitted before updating a record. Can modify the data. |
|
||||||
|
| `MutatorUpdateAfter` | `{ entity: Entity, entityId: PrimaryFieldType, data: EntityData, changed: EntityData }` | Emitted after updating a record. |
|
||||||
|
| `MutatorDeleteBefore` | `{ entity: Entity, entityId: PrimaryFieldType }` | Emitted before deleting a record. |
|
||||||
|
| `MutatorDeleteAfter` | `{ entity: Entity, entityId: PrimaryFieldType, data: EntityData }` | Emitted after deleting a record. |
|
||||||
|
|
||||||
|
### Repository Events
|
||||||
|
|
||||||
|
These events are emitted during database queries (find operations).
|
||||||
|
|
||||||
|
| Event | Params | Description |
|
||||||
|
| :------------------------- | :--------------------------------------------------------- | :--------------------------------------- |
|
||||||
|
| `RepositoryFindOneBefore` | `{ entity: Entity, options: RepoQuery }` | Emitted before finding a single record. |
|
||||||
|
| `RepositoryFindOneAfter` | `{ entity: Entity, options: RepoQuery, data: EntityData }` | Emitted after finding a single record. |
|
||||||
|
| `RepositoryFindManyBefore` | `{ entity: Entity, options: RepoQuery }` | Emitted before finding multiple records. |
|
||||||
|
| `RepositoryFindManyAfter` | `{ entity: Entity, options: RepoQuery, data: EntityData }` | Emitted after finding multiple records. |
|
||||||
|
|
||||||
|
## Media Events
|
||||||
|
|
||||||
|
These events are emitted by the `Storage` class and are available on the `MediaEvents` object.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { MediaEvents } from "bknd";
|
||||||
|
```
|
||||||
|
|
||||||
|
| Event | Params | Description |
|
||||||
|
| :------------------ | :--------------------------------------- | :----------------------------------------------------------------------- |
|
||||||
|
| `FileUploadedEvent` | `{ file: FileBody } & FileUploadPayload` | Emitted when a file is successfully uploaded. Can modify the event data. |
|
||||||
|
| `FileDeletedEvent` | `{ name: string }` | Emitted when a file is deleted. |
|
||||||
|
| `FileAccessEvent` | `{ name: string }` | Emitted when a file is accessed. |
|
||||||
|
|
||||||
|
## Auth Events
|
||||||
|
|
||||||
|
Coming soon.
|
||||||
+96
-59
@@ -1,64 +1,95 @@
|
|||||||
---
|
---
|
||||||
title: 'Astro'
|
title: "Astro"
|
||||||
description: 'Run bknd inside Astro'
|
description: "Run bknd inside Astro"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get started with Astro and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
To get started with Astro and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
<Tabs>
|
### CLI Starter
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Astro CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
Create a new Astro CLI starter project by running the following command:
|
||||||
npx bknd create -i astro
|
|
||||||
```
|
|
||||||
</Tab>
|
|
||||||
<Tab title="Manual">
|
|
||||||
Create a new Astro project by following the [official guide](https://docs.astro.build/en/install-and-setup/), and then install bknd as a dependency:
|
|
||||||
|
|
||||||
<InstallBknd />
|
```sh
|
||||||
|
npx bknd create -i astro
|
||||||
|
```
|
||||||
|
|
||||||
<Note>The guide below assumes you're using Astro v4. We've experienced issues with Astro DB
|
### Manual
|
||||||
using v5, see [this issue](https://github.com/withastro/astro/issues/12474).</Note>
|
|
||||||
|
|
||||||
For the Astro integration to work, you also need to [add the react integration](https://docs.astro.build/en/guides/integrations-guide/react/):
|
Create a new Astro project by following the [official guide](https://docs.astro.build/en/install-and-setup/), and then install bknd as a dependency:
|
||||||
```bash
|
|
||||||
npx astro add react
|
|
||||||
```
|
|
||||||
|
|
||||||
You also need to make sure to set the output to `server` in your Astro config:
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
```js {6}
|
|
||||||
// astro.config.mjs
|
|
||||||
import { defineConfig } from "astro/config";
|
|
||||||
import react from "@astrojs/react";
|
|
||||||
|
|
||||||
export default defineConfig({
|
```bash tab="npm"
|
||||||
output: "server",
|
npm install bknd
|
||||||
integrations: [react()]
|
```
|
||||||
});
|
|
||||||
```
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<Note>
|
|
||||||
If you don't want to use React with Astro, there is also an option to serve the bknd Admin UI
|
|
||||||
statically using Astro's middleware. In case you're interested in this, feel free to reach
|
|
||||||
out in [Discord](https://discord.gg/952SFk8Tb8) or open an [issue on GitHub](https://github.com/bknd-io/bknd/issues/new).
|
|
||||||
</Note>
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
The guide below assumes you're using Astro v4. We've experienced issues with
|
||||||
|
Astro DB using v5, see [this
|
||||||
|
issue](https://github.com/withastro/astro/issues/12474).
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
For the Astro integration to work, you also need to [add the react integration](https://docs.astro.build/en/guides/integrations-guide/react/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx astro add react
|
||||||
|
```
|
||||||
|
|
||||||
|
You also need to make sure to set the output to `server` in your Astro config:
|
||||||
|
|
||||||
|
```js {6}
|
||||||
|
// astro.config.mjs
|
||||||
|
import { defineConfig } from "astro/config";
|
||||||
|
import react from "@astrojs/react";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
output: "server", // [!code highlight]
|
||||||
|
integrations: [react()],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
If you don't want to use React with Astro, there is also an option to serve
|
||||||
|
the bknd Admin UI statically using Astro's middleware. In case you're
|
||||||
|
interested in this, feel free to reach out in
|
||||||
|
[Discord](https://discord.gg/952SFk8Tb8) or open an [issue on
|
||||||
|
GitHub](https://github.com/bknd-io/bknd/issues/new).
|
||||||
|
</Callout>
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
<Callout type="warning">
|
||||||
|
When run with Node.js, a version of 22 (LTS) or higher is required. Please
|
||||||
|
verify your version by running `node -v`, and
|
||||||
|
[upgrade](https://nodejs.org/en/download/) if necessary.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you.
|
Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you.
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { AstroBkndConfig } from "bknd/adapter/astro";
|
import type { AstroBkndConfig } from "bknd/adapter/astro";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db"
|
url: "file:data.db",
|
||||||
},
|
},
|
||||||
} satisfies AstroBkndConfig;
|
} satisfies AstroBkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -70,9 +101,10 @@ export type AstroBkndConfig<Env = AstroEnv> = FrameworkBkndConfig<Env>;
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Serve the API
|
## Serve the API
|
||||||
|
|
||||||
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file:
|
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file:
|
||||||
|
|
||||||
```ts src/bknd.ts
|
```ts title="src/bknd.ts"
|
||||||
import type { AstroGlobal } from "astro";
|
import type { AstroGlobal } from "astro";
|
||||||
import { getApp as getBkndApp } from "bknd/adapter/astro";
|
import { getApp as getBkndApp } from "bknd/adapter/astro";
|
||||||
import config from "../bknd.config";
|
import config from "../bknd.config";
|
||||||
@@ -80,37 +112,37 @@ import config from "../bknd.config";
|
|||||||
export { config };
|
export { config };
|
||||||
|
|
||||||
export async function getApp() {
|
export async function getApp() {
|
||||||
return await getBkndApp(config);
|
return await getBkndApp(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getApi(
|
export async function getApi(
|
||||||
astro: AstroGlobal,
|
astro: AstroGlobal,
|
||||||
opts?: { mode: "static" } | { mode?: "dynamic"; verify?: boolean },
|
opts?: { mode: "static" } | { mode?: "dynamic"; verify?: boolean },
|
||||||
) {
|
) {
|
||||||
const app = await getApp();
|
const app = await getApp();
|
||||||
if (opts?.mode !== "static" && opts?.verify) {
|
if (opts?.mode !== "static" && opts?.verify) {
|
||||||
const api = app.getApi({ headers: astro.request.headers });
|
const api = app.getApi({ headers: astro.request.headers });
|
||||||
await api.verifyAuth();
|
await api.verifyAuth();
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
return app.getApi();
|
return app.getApi();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a new catch-all route at `src/pages/api/[...api].ts`.
|
Create a new catch-all route at `src/pages/api/[...api].ts`.
|
||||||
|
|
||||||
```ts src/pages/api/[...api].ts
|
```ts title="src/pages/api/[...api].ts"
|
||||||
import { serve } from "bknd/adapter/astro";
|
import { serve } from "bknd/adapter/astro";
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
export const ALL = serve({
|
export const ALL = serve({
|
||||||
connection: {
|
connection: {
|
||||||
// location of your local Astro DB
|
// location of your local Astro DB
|
||||||
// make sure to use a remote URL in production
|
// make sure to use a remote URL in production
|
||||||
url: "file:.astro/content.db"
|
url: "file:.astro/content.db",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -119,8 +151,10 @@ special case of astro, you may also use your Astro DB credentials since it's als
|
|||||||
under the hood. Refer to the [Astro DB documentation](https://docs.astro.build/en/guides/astro-db/) for more information.
|
under the hood. Refer to the [Astro DB documentation](https://docs.astro.build/en/guides/astro-db/) for more information.
|
||||||
|
|
||||||
## Enabling the Admin UI
|
## Enabling the Admin UI
|
||||||
|
|
||||||
Create a new catch-all route at `src/pages/admin/[...admin].astro`:
|
Create a new catch-all route at `src/pages/admin/[...admin].astro`:
|
||||||
```jsx src/pages/admin/[...admin].astro
|
|
||||||
|
```jsx title="src/pages/admin/[...admin].astro"
|
||||||
---
|
---
|
||||||
import { Admin } from "bknd/ui";
|
import { Admin } from "bknd/ui";
|
||||||
import "bknd/dist/styles.css";
|
import "bknd/dist/styles.css";
|
||||||
@@ -139,7 +173,7 @@ export const prerender = false;
|
|||||||
withProvider={{ user }}
|
withProvider={{ user }}
|
||||||
config={{
|
config={{
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
color_scheme: "dark",
|
theme: "dark",
|
||||||
logo_return_path: "/../"
|
logo_return_path: "/../"
|
||||||
}}
|
}}
|
||||||
client:only
|
client:only
|
||||||
@@ -149,10 +183,12 @@ export const prerender = false;
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Example usage of the API
|
## Example usage of the API
|
||||||
|
|
||||||
You use the API in both static and SSR pages. Just note that on static pages, authentication
|
You use the API in both static and SSR pages. Just note that on static pages, authentication
|
||||||
might not work as expected, because Cookies are not available in the static context.
|
might not work as expected, because Cookies are not available in the static context.
|
||||||
|
|
||||||
Here is an example of using the API in static context:
|
Here is an example of using the API in static context:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
---
|
---
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
@@ -168,6 +204,7 @@ const { data } = await api.data.readMany("todos");
|
|||||||
```
|
```
|
||||||
|
|
||||||
On SSR pages, you can also access the authenticated user:
|
On SSR pages, you can also access the authenticated user:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
---
|
---
|
||||||
import { getApi } from "bknd/adapter/astro";
|
import { getApi } from "bknd/adapter/astro";
|
||||||
@@ -189,4 +226,4 @@ export const prerender = false;
|
|||||||
```
|
```
|
||||||
|
|
||||||
Check the [astro repository example](https://github.com/bknd-io/bknd/tree/main/examples/astro)
|
Check the [astro repository example](https://github.com/bknd-io/bknd/tree/main/examples/astro)
|
||||||
for more implementation details or a [fully working example using Astro DB](https://github.com/dswbx/bknd-astro-example).
|
for more implementation details or a [fully working example using Astro DB](https://github.com/dswbx/bknd-astro-example).
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"pages": ["nextjs", "react-router", "astro", "vite"]
|
||||||
|
}
|
||||||
+93
-59
@@ -1,39 +1,62 @@
|
|||||||
---
|
---
|
||||||
title: 'Next.js'
|
title: "Next.js"
|
||||||
description: 'Run bknd inside Next.js'
|
description: "Run bknd inside Next.js"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
To get started with Next.js and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
|
||||||
|
|
||||||
<Tabs>
|
To get started with Next.js and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter.
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Next.js CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
### CLI Starter
|
||||||
npx bknd create -i nextjs
|
|
||||||
```
|
Create a new Next.js CLI starter project by running the following command:
|
||||||
</Tab>
|
|
||||||
<Tab title="Manual">
|
```sh
|
||||||
Create a new Next.js project by following the [official guide](https://nextjs.org/docs/pages/api-reference/cli/create-next-app), and then install bknd as a dependency:
|
npx bknd create -i nextjs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new Next.js project by following the [official guide](https://nextjs.org/docs/pages/api-reference/cli/create-next-app), and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<InstallBknd />
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
<Callout type="warning">
|
||||||
|
When run with Node.js, a version of 22 (LTS) or higher is required. Please
|
||||||
|
verify your version by running `node -v`, and
|
||||||
|
[upgrade](https://nodejs.org/en/download/) if necessary.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you.
|
Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you.
|
||||||
|
|
||||||
|
```typescript title="bknd.config.ts"
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
|
||||||
import type { NextjsBkndConfig } from "bknd/adapter/nextjs";
|
import type { NextjsBkndConfig } from "bknd/adapter/nextjs";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db"
|
url: "file:data.db",
|
||||||
},
|
},
|
||||||
} satisfies NextjsBkndConfig;
|
} satisfies NextjsBkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -42,39 +65,45 @@ See [bknd.config.ts](/extending/config) for more information on how to configure
|
|||||||
```typescript
|
```typescript
|
||||||
type NextjsEnv = NextApiRequest["env"];
|
type NextjsEnv = NextApiRequest["env"];
|
||||||
export type NextjsBkndConfig<Env = NextjsEnv> = FrameworkBkndConfig<Env> & {
|
export type NextjsBkndConfig<Env = NextjsEnv> = FrameworkBkndConfig<Env> & {
|
||||||
cleanRequest?: { searchParams?: string[] };
|
cleanRequest?: { searchParams?: string[] };
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Serve the API
|
## Serve the API
|
||||||
|
|
||||||
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file:
|
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file:
|
||||||
|
|
||||||
```ts src/bknd.ts
|
```ts title="src/bknd.ts"
|
||||||
import { type NextjsBkndConfig, getApp as getBkndApp } from "bknd/adapter/nextjs";
|
import {
|
||||||
|
type NextjsBkndConfig,
|
||||||
|
getApp as getBkndApp,
|
||||||
|
} from "bknd/adapter/nextjs";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import config from "../bknd.config";
|
import config from "../bknd.config";
|
||||||
|
|
||||||
export { config };
|
export { config };
|
||||||
|
|
||||||
export async function getApp() {
|
export async function getApp() {
|
||||||
return await getBkndApp(config, process.env);
|
return await getBkndApp(config, process.env);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getApi(opts?: { verify?: boolean }) {
|
export async function getApi(opts?: { verify?: boolean }) {
|
||||||
const app = await getApp();
|
const app = await getApp();
|
||||||
if (opts?.verify) {
|
if (opts?.verify) {
|
||||||
const api = app.getApi({ headers: await headers() });
|
const api = app.getApi({ headers: await headers() });
|
||||||
await api.verifyAuth();
|
await api.verifyAuth();
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
return app.getApi();
|
return app.getApi();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
Now to expose the API, create a catch-all route file at `src/api/[[...bknd]]/route.ts`:
|
Now to expose the API, create a catch-all route file at `src/api/[[...bknd]]/route.ts`:
|
||||||
```ts src/api/[[...bknd]]/route.ts
|
|
||||||
|
```ts title="src/api/[[...bknd]]/route.ts"
|
||||||
import { config } from "@/bknd";
|
import { config } from "@/bknd";
|
||||||
import { serve } from "bknd/adapter/nextjs";
|
import { serve } from "bknd/adapter/nextjs";
|
||||||
|
|
||||||
@@ -82,12 +111,12 @@ import { serve } from "bknd/adapter/nextjs";
|
|||||||
export const runtime = "edge";
|
export const runtime = "edge";
|
||||||
|
|
||||||
const handler = serve({
|
const handler = serve({
|
||||||
...config,
|
...config,
|
||||||
cleanRequest: {
|
cleanRequest: {
|
||||||
// depending on what name you used for the catch-all route,
|
// depending on what name you used for the catch-all route,
|
||||||
// you need to change this to clean it from the request.
|
// you need to change this to clean it from the request.
|
||||||
searchParams: ["bknd"],
|
searchParams: ["bknd"],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const GET = handler;
|
export const GET = handler;
|
||||||
@@ -98,43 +127,48 @@ export const DELETE = handler;
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Enabling the Admin UI
|
## Enabling the Admin UI
|
||||||
|
|
||||||
Create a page at `admin/[[...admin]]/page.tsx`:
|
Create a page at `admin/[[...admin]]/page.tsx`:
|
||||||
```tsx admin/[[...admin]]/page.tsx
|
|
||||||
|
```tsx title="admin/[[...admin]]/page.tsx"
|
||||||
import { Admin } from "bknd/ui";
|
import { Admin } from "bknd/ui";
|
||||||
import { getApi } from "@/bknd";
|
import { getApi } from "@/bknd";
|
||||||
import "bknd/dist/styles.css";
|
import "bknd/dist/styles.css";
|
||||||
|
|
||||||
export default async function AdminPage() {
|
export default async function AdminPage() {
|
||||||
// make sure to verify auth using headers
|
// make sure to verify auth using headers
|
||||||
const api = await getApi({ verify: true });
|
const api = await getApi({ verify: true });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Admin
|
<Admin
|
||||||
withProvider={{ user: api.getUser() }}
|
withProvider={{ user: api.getUser() }}
|
||||||
config={{
|
config={{
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/../",
|
logo_return_path: "/../",
|
||||||
color_scheme: "system",
|
theme: "system",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example usage of the API
|
## Example usage of the API
|
||||||
|
|
||||||
You can use the `getApi` helper function we've already set up to fetch and mutate in static pages and server components:
|
You can use the `getApi` helper function we've already set up to fetch and mutate in static pages and server components:
|
||||||
|
|
||||||
```tsx app/page.tsx
|
```tsx title="app/page.tsx"
|
||||||
import { getApi } from "@/bknd";
|
import { getApi } from "@/bknd";
|
||||||
|
|
||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
const api = await getApi();
|
const api = await getApi();
|
||||||
const { data: todos } = await api.data.readMany("todos", { limit: 5 });
|
const { data: todos } = await api.data.readMany("todos", { limit: 5 });
|
||||||
|
|
||||||
return <ul>
|
return (
|
||||||
|
<ul>
|
||||||
{todos.map((todo) => (
|
{todos.map((todo) => (
|
||||||
<li key={String(todo.id)}>{todo.title}</li>
|
<li key={String(todo.id)}>{todo.title}</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
---
|
||||||
|
title: "React Router"
|
||||||
|
description: "Run bknd inside React Router"
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
To get started with React Router and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
|
### CLI Starter
|
||||||
|
|
||||||
|
Create a new React Router CLI starter project by running the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx bknd create -i react-router
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new React Router project by following the [official guide](https://reactrouter.com/start/framework/installation), and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
<Callout type="warning">
|
||||||
|
When run with Node.js, a version of 22 (LTS) or higher is required. Please
|
||||||
|
verify your version by running `node -v`, and
|
||||||
|
[upgrade](https://nodejs.org/en/download/) if necessary.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you.
|
||||||
|
|
||||||
|
```typescript title="bknd.config.ts"
|
||||||
|
import type { ReactRouterBkndConfig } from "bknd/adapter/react-router";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
connection: {
|
||||||
|
url: "file:data.db",
|
||||||
|
},
|
||||||
|
} satisfies ReactRouterBkndConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
See [bknd.config.ts](/extending/config) for more information on how to configure bknd. The `ReactRouterBkndConfig` type extends the `BkndConfig` type with the following additional properties:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type ReactRouterEnv = NodeJS.ProcessEnv;
|
||||||
|
type ReactRouterFunctionArgs = {
|
||||||
|
request: Request;
|
||||||
|
};
|
||||||
|
export type ReactRouterBkndConfig<Env = ReactRouterEnv> =
|
||||||
|
FrameworkBkndConfig<Env>;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Serve the API
|
||||||
|
|
||||||
|
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file:
|
||||||
|
|
||||||
|
```ts title="app/bknd.ts"
|
||||||
|
import {
|
||||||
|
type ReactRouterBkndConfig,
|
||||||
|
getApp as getBkndApp,
|
||||||
|
} from "bknd/adapter/react-router";
|
||||||
|
import config from "../bknd.config";
|
||||||
|
|
||||||
|
export { config };
|
||||||
|
|
||||||
|
// you may adjust this function depending on your runtime environment.
|
||||||
|
// e.g. when deploying to cloudflare workers, you'd want the FunctionArgs to be passed in
|
||||||
|
// to resolve environment variables
|
||||||
|
export async function getApp() {
|
||||||
|
return await getBkndApp(config, process.env as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getApi(
|
||||||
|
args?: { request: Request },
|
||||||
|
opts?: { verify?: boolean },
|
||||||
|
) {
|
||||||
|
const app = await getApp();
|
||||||
|
if (opts?.verify) {
|
||||||
|
const api = app.getApi({ headers: args?.request.headers });
|
||||||
|
await api.verifyAuth();
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.getApi();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
|
Create a new api splat route file at `app/routes/api.$.ts`:
|
||||||
|
|
||||||
|
```ts title="app/routes/api.$.ts"
|
||||||
|
import { getApp } from "~/bknd";
|
||||||
|
|
||||||
|
const handler = async (args: { request: Request }) => {
|
||||||
|
const app = await getApp();
|
||||||
|
return app.fetch(args.request);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loader = handler;
|
||||||
|
export const action = handler;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Enabling the Admin UI
|
||||||
|
|
||||||
|
Create a new splat route file at `app/routes/admin.$.tsx`:
|
||||||
|
|
||||||
|
```tsx title="app/routes/admin.$.tsx"
|
||||||
|
import { lazy, Suspense, useSyncExternalStore } from "react";
|
||||||
|
import { type LoaderFunctionArgs, useLoaderData } from "react-router";
|
||||||
|
import { getApi } from "~/bknd";
|
||||||
|
|
||||||
|
const Admin = lazy(() =>
|
||||||
|
import("bknd/ui").then((mod) => ({ default: mod.Admin })),
|
||||||
|
);
|
||||||
|
import "bknd/dist/styles.css";
|
||||||
|
|
||||||
|
export const loader = async (args: LoaderFunctionArgs) => {
|
||||||
|
const api = await getApi(args, { verify: true });
|
||||||
|
return {
|
||||||
|
user: api.getUser(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdminPage() {
|
||||||
|
const { user } = useLoaderData<typeof loader>();
|
||||||
|
// derived from https://github.com/sergiodxa/remix-utils
|
||||||
|
// @ts-ignore
|
||||||
|
const hydrated = useSyncExternalStore(
|
||||||
|
() => {},
|
||||||
|
() => true,
|
||||||
|
() => false,
|
||||||
|
);
|
||||||
|
if (!hydrated) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Suspense>
|
||||||
|
<Admin
|
||||||
|
withProvider={{ user }}
|
||||||
|
config={{ basepath: "/admin", logo_return_path: "/../" }}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example usage of the API
|
||||||
|
|
||||||
|
You can use the `getApi` helper function we've already set up to fetch and mutate:
|
||||||
|
|
||||||
|
```tsx title="app/routes/_index.tsx"
|
||||||
|
import { useLoaderData, type LoaderFunctionArgs } from "react-router";
|
||||||
|
import { getApi } from "~/bknd";
|
||||||
|
|
||||||
|
export const loader = async (args: LoaderFunctionArgs) => {
|
||||||
|
// use authentication from request
|
||||||
|
const api = await getApi(args, { verify: true });
|
||||||
|
const { data } = await api.data.readMany("todos");
|
||||||
|
return { data, user: api.getUser() };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
const { data, user } = useLoaderData<typeof loader>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Data</h1>
|
||||||
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||||
|
<h1>User</h1>
|
||||||
|
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
+73
-38
@@ -1,31 +1,59 @@
|
|||||||
---
|
---
|
||||||
title: 'Vite'
|
title: "Vite"
|
||||||
description: 'Run bknd inside Vite'
|
description: "Run bknd inside Vite"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
Vite is a powerful toolkit to accelerate your local development.
|
Vite is a powerful toolkit to accelerate your local development.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Create a new vite project by following the [official guide](https://vite.dev/guide/#scaffolding-your-first-vite-project)
|
Create a new vite project by following the [official guide](https://vite.dev/guide/#scaffolding-your-first-vite-project)
|
||||||
and then install bknd as a dependency:
|
and then install bknd as a dependency:
|
||||||
<InstallBknd />
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
Additionally, install required dependencies:
|
Additionally, install required dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @hono/vite-dev-server
|
npm install @hono/vite-dev-server
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
<Callout type="warning">
|
||||||
|
When run with Node.js, a version of 22 (LTS) or higher is required. Please
|
||||||
|
verify your version by running `node -v`, and
|
||||||
|
[upgrade](https://nodejs.org/en/download/) if necessary.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
Now create a `bknd.config.ts` file in the root of your project.
|
Now create a `bknd.config.ts` file in the root of your project.
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { ViteBkndConfig } from "bknd/adapter/vite";
|
import type { ViteBkndConfig } from "bknd/adapter/vite";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db"
|
url: "file:data.db",
|
||||||
}
|
},
|
||||||
} satisfies ViteBkndConfig;
|
} satisfies ViteBkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -38,22 +66,25 @@ export type ViteBkndConfig<Env = ViteEnv> = RuntimeBkndConfig<Env> & {};
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Serve the API
|
## Serve the API
|
||||||
|
|
||||||
To serve the **bknd** API, you first have to create a local server file for you vite environment.
|
To serve the **bknd** API, you first have to create a local server file for you vite environment.
|
||||||
Create a `server.ts` file:
|
Create a `server.ts` file:
|
||||||
|
|
||||||
```typescript
|
```typescript title="server.ts"
|
||||||
import { serve } from "bknd/adapter/vite";
|
import { serve } from "bknd/adapter/vite";
|
||||||
import config from "./bknd.config";
|
import config from "./bknd.config";
|
||||||
|
|
||||||
export default serve(config)
|
export default serve(config);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also run your vite server in `mode: "fresh"`, this will re-create the app on every fetch.
|
You can also run your vite server in `mode: "fresh"`, this will re-create the app on every fetch.
|
||||||
This is only useful for when working on the `bknd` repository directly.
|
This is only useful for when working on the `bknd` repository directly.
|
||||||
|
|
||||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
Next, adjust your `vite.config.ts` to look like the following:
|
Next, adjust your `vite.config.ts` to look like the following:
|
||||||
```ts
|
|
||||||
|
```ts title="vite.config.ts"
|
||||||
import { devServer } from "bknd/adapter/vite";
|
import { devServer } from "bknd/adapter/vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
@@ -62,13 +93,13 @@ import tsconfigPaths from "vite-tsconfig-paths";
|
|||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
tsconfigPaths(),
|
tsconfigPaths(),
|
||||||
devServer({
|
devServer({
|
||||||
// point to your previously created server file
|
// point to your previously created server file
|
||||||
entry: "./server.ts"
|
entry: "./server.ts",
|
||||||
})
|
}),
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -77,64 +108,68 @@ looks like an empty project. That's because we only registered the API, head ove
|
|||||||
http://localhost:5174/api/system/config to see **bknd** respond.
|
http://localhost:5174/api/system/config to see **bknd** respond.
|
||||||
|
|
||||||
## Serve the Admin UI
|
## Serve the Admin UI
|
||||||
|
|
||||||
After adding the API, you can easily add the Admin UI by simply returning it in your `App.tsx`.
|
After adding the API, you can easily add the Admin UI by simply returning it in your `App.tsx`.
|
||||||
Replace all of its content with the following:
|
Replace all of its content with the following:
|
||||||
|
|
||||||
```tsx
|
```tsx title="App.tsx"
|
||||||
import { Admin } from "bknd/ui";
|
import { Admin } from "bknd/ui";
|
||||||
import "bknd/dist/styles.css";
|
import "bknd/dist/styles.css";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return <Admin withProvider />
|
return <Admin withProvider />;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now http://localhost:5174/ should give you the Admin UI.
|
Now http://localhost:5174/ should give you the Admin UI.
|
||||||
|
|
||||||
## Customizations
|
## Customizations
|
||||||
|
|
||||||
This is just the bare minimum and may not always fulfill your requirements. There are a few
|
This is just the bare minimum and may not always fulfill your requirements. There are a few
|
||||||
options you can make use of to adjust it according to your setup.
|
options you can make use of to adjust it according to your setup.
|
||||||
|
|
||||||
### Use custom HTML to serve the Admin UI
|
### Use custom HTML to serve the Admin UI
|
||||||
|
|
||||||
There might be cases you want to be sure to be in control over the HTML that is being used.
|
There might be cases you want to be sure to be in control over the HTML that is being used.
|
||||||
`bknd` generates it automatically, but you use your own one as follows:
|
`bknd` generates it automatically, but you use your own one as follows:
|
||||||
|
|
||||||
```typescript server.ts
|
```typescript title="server.ts"
|
||||||
import { serve, addViteScript } from "bknd/adapter/vite";
|
import { serve, addViteScript } from "bknd/adapter/vite";
|
||||||
import { readFile } from "node:fs/promises"
|
import { readFile } from "node:fs/promises";
|
||||||
import config from "./bknd.config";
|
import config from "./bknd.config";
|
||||||
|
|
||||||
let html = await readFile("./index.html", "utf-8");
|
let html = await readFile("./index.html", "utf-8");
|
||||||
|
|
||||||
// then add it as an option
|
// then add it as an option
|
||||||
export default serve({
|
export default serve({
|
||||||
...config,
|
...config,
|
||||||
adminOptions: {
|
adminOptions: {
|
||||||
html: addViteScript(html),
|
html: addViteScript(html),
|
||||||
// optionally, you can change the base path for the admin UI
|
// optionally, you can change the base path for the admin UI
|
||||||
adminBasePath: "/admin"
|
adminBasePath: "/admin",
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
The vite scripts has to be added manually currently, as adding them automatically with
|
The vite scripts has to be added manually currently, as adding them automatically with
|
||||||
`@hono/vite-dev-server` is buggy. This may change in the future.
|
`@hono/vite-dev-server` is buggy. This may change in the future.
|
||||||
|
|
||||||
### Use a custom entry point
|
### Use a custom entry point
|
||||||
|
|
||||||
By default, the entry point `/src/main.tsx` is used and should fit most cases. If that's not you,
|
By default, the entry point `/src/main.tsx` is used and should fit most cases. If that's not you,
|
||||||
you can supply a different one like so:
|
you can supply a different one like so:
|
||||||
|
|
||||||
```typescript server.ts
|
```typescript title="server.ts"
|
||||||
import { serve } from "bknd/adapter/vite";
|
import { serve } from "bknd/adapter/vite";
|
||||||
import config from "./bknd.config";
|
import config from "./bknd.config";
|
||||||
|
|
||||||
// the configuration given is optional
|
// the configuration given is optional
|
||||||
export default serve({
|
export default serve({
|
||||||
...config,
|
...config,
|
||||||
adminOptions: {
|
adminOptions: {
|
||||||
forceDev: {
|
forceDev: {
|
||||||
mainPath: "/src/special.tsx"
|
mainPath: "/src/special.tsx",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
+55
-33
@@ -1,44 +1,65 @@
|
|||||||
---
|
---
|
||||||
title: 'AWS Lambda'
|
title: "AWS Lambda"
|
||||||
description: 'Run bknd inside AWS Lambda'
|
description: "Run bknd inside AWS Lambda"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get started with AWS Lambda and bknd you can either install the package manually and follow the descriptions below, or use the CLI starter:
|
To get started with AWS Lambda and bknd you can either install the package manually and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
<Tabs>
|
### CLI Starter
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Bun CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
Create a new Bun CLI starter project by running the following command:
|
||||||
npx bknd create -i aws
|
|
||||||
```
|
```sh
|
||||||
</Tab>
|
npx bknd create -i aws
|
||||||
<Tab title="Manual">
|
```
|
||||||
Create a new AWS Lambda project and then install bknd as a dependency:
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new AWS Lambda project and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<InstallBknd />
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Serve the API
|
## Serve the API
|
||||||
|
|
||||||
To serve the API, you can use the `serveLambda` function of the AWS Lambda adapter.
|
To serve the API, you can use the `serveLambda` function of the AWS Lambda adapter.
|
||||||
|
|
||||||
```tsx index.mjs
|
```tsx title="index.mjs"
|
||||||
import { serveLambda } from "bknd/adapter/aws";
|
import { serveLambda } from "bknd/adapter/aws";
|
||||||
import { libsql } from "bknd/data";
|
import { libsql } from "bknd";
|
||||||
|
|
||||||
export const handler = serveLambda({
|
export const handler = serveLambda({
|
||||||
connection: libsql({
|
connection: libsql({
|
||||||
url: "libsql://your-database-url.turso.io",
|
url: "libsql://your-database-url.turso.io",
|
||||||
authToken: "your-auth-token",
|
authToken: "your-auth-token",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Although the runtime would support database as a file, we don't recommend it. You'd need to also bundle the native dependencies which increases the deployment size and cold start time. Instead, we recommend you to use [LibSQL on Turso](/usage/database#sqlite-using-libsql-on-turso).
|
Although the runtime would support database as a file, we don't recommend it. You'd need to also bundle the native dependencies which increases the deployment size and cold start time. Instead, we recommend you to use [LibSQL on Turso](/usage/database#sqlite-using-libsql-on-turso).
|
||||||
|
|
||||||
## Serve the Admin UI
|
## Serve the Admin UI
|
||||||
|
|
||||||
Lambda functions should be as small as possible. Therefore, the static files for the admin panel should not be served from node_modules like with the Node adapter.
|
Lambda functions should be as small as possible. Therefore, the static files for the admin panel should not be served from node_modules like with the Node adapter.
|
||||||
|
|
||||||
Instead, we recommend to copy the static files and bundle them with the lambda function. To copy the static files, you can use the `copy-assets` command:
|
Instead, we recommend to copy the static files and bundle them with the lambda function. To copy the static files, you can use the `copy-assets` command:
|
||||||
@@ -49,35 +70,37 @@ npx bknd copy-assets --out static
|
|||||||
|
|
||||||
This will copy the static files to the `static` directory and then serve them from there:
|
This will copy the static files to the `static` directory and then serve them from there:
|
||||||
|
|
||||||
```tsx index.mjs {8-11}
|
```tsx title="index.mjs"
|
||||||
import { serveLambda } from "bknd/adapter/aws";
|
import { serveLambda } from "bknd/adapter/aws";
|
||||||
|
|
||||||
export const handler = serveLambda({
|
export const handler = serveLambda({
|
||||||
connection: {
|
connection: {
|
||||||
url: process.env.DB_URL!,
|
url: process.env.DB_URL!,
|
||||||
authToken: process.env.DB_AUTH_TOKEN!
|
authToken: process.env.DB_AUTH_TOKEN!,
|
||||||
},
|
},
|
||||||
assets: {
|
assets: {
|
||||||
mode: "local",
|
// [!code highlight]
|
||||||
root: "./static"
|
mode: "local", // [!code highlight]
|
||||||
}
|
root: "./static", // [!code highlight]
|
||||||
|
}, // [!code highlight]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
To deploy a lambda function, you could follow these steps:
|
To deploy a lambda function, you could follow these steps:
|
||||||
|
|
||||||
1. Create an IAM role with a trust policy that allows lambda to assume the role.
|
1. Create an IAM role with a trust policy that allows lambda to assume the role.
|
||||||
2. Attach the `AWSLambdaBasicExecutionRole` policy to the role.
|
2. Attach the `AWSLambdaBasicExecutionRole` policy to the role.
|
||||||
3. Bundle the lambda function with the static files (e.g. using esbuild)
|
3. Bundle the lambda function with the static files (e.g. using esbuild)
|
||||||
4. Create a zip file with the bundled lambda function
|
4. Create a zip file with the bundled lambda function
|
||||||
5. Create a lambda function
|
5. Create a lambda function
|
||||||
6. Create a function URL for the lambda function & make it publicly accessible (optional)
|
6. Create a function URL for the lambda function & make it publicly accessible (optional)
|
||||||
|
|
||||||
Depending on your use case, you may want to skip step 6 and use the AWS API Gateway to serve the lambda function. Here is an [example deployment script](https://github.com/bknd-io/bknd/blob/main/examples/aws-lambda/deploy.sh) which creates the AWS resources described above, bundles the lambda function and uploads it.
|
Depending on your use case, you may want to skip step 6 and use the AWS API Gateway to serve the lambda function. Here is an [example deployment script](https://github.com/bknd-io/bknd/blob/main/examples/aws-lambda/deploy.sh) which creates the AWS resources described above, bundles the lambda function and uploads it.
|
||||||
|
|
||||||
|
|
||||||
### Using the CLI starter
|
### Using the CLI starter
|
||||||
|
|
||||||
The CLI starter example includes a basic build script that creates the required AWS resources, copies the static files, bundles the lambda function and uploads it. To deploy the lambda function, you can run:
|
The CLI starter example includes a basic build script that creates the required AWS resources, copies the static files, bundles the lambda function and uploads it. To deploy the lambda function, you can run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -86,7 +109,7 @@ npm run deploy
|
|||||||
|
|
||||||
To make adjustments to the lambda function created (e.g. architecture, memory, timeout, etc.) you can edit the head section of the `deploy.sh` script.
|
To make adjustments to the lambda function created (e.g. architecture, memory, timeout, etc.) you can edit the head section of the `deploy.sh` script.
|
||||||
|
|
||||||
```sh deploy.sh
|
```sh title="deploy.sh"
|
||||||
# cat deploy.sh | head -12
|
# cat deploy.sh | head -12
|
||||||
FUNCTION_NAME="bknd-lambda"
|
FUNCTION_NAME="bknd-lambda"
|
||||||
ROLE_NAME="bknd-lambda-execution-role"
|
ROLE_NAME="bknd-lambda-execution-role"
|
||||||
@@ -105,4 +128,3 @@ To clean up AWS resources created by the deployment script, you can run:
|
|||||||
```bash
|
```bash
|
||||||
npm run clean
|
npm run clean
|
||||||
```
|
```
|
||||||
|
|
||||||
+40
-21
@@ -1,46 +1,65 @@
|
|||||||
---
|
---
|
||||||
title: 'Bun'
|
title: "Bun"
|
||||||
description: 'Run bknd inside Bun'
|
description: "Run bknd inside Bun"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get started with Bun and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
To get started with Bun and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
<Tabs>
|
## CLI Starter
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Bun CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
Create a new Bun CLI starter project by running the following command:
|
||||||
npx bknd create -i bun
|
|
||||||
```
|
```sh
|
||||||
</Tab>
|
npx bknd create -i bun
|
||||||
<Tab title="Manual">
|
```
|
||||||
Create a new Bun project and then install bknd as a dependency:
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new Bun project and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<InstallBknd />
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
## Serve the API & static files
|
## Serve the API & static files
|
||||||
|
|
||||||
The `serve` function of the Bun adapter makes sure to also serve the static files required for
|
The `serve` function of the Bun adapter makes sure to also serve the static files required for
|
||||||
the admin panel.
|
the admin panel.
|
||||||
|
|
||||||
``` tsx
|
```tsx title="index.ts"
|
||||||
// index.ts
|
|
||||||
import { serve } from "bknd/adapter/bun";
|
import { serve } from "bknd/adapter/bun";
|
||||||
|
|
||||||
// if the configuration is omitted, it uses an in-memory database
|
// if the configuration is omitted, it uses an in-memory database
|
||||||
serve({
|
serve({
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db"
|
url: "file:data.db",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
Run the application using Bun by executing:
|
Run the application using Bun by executing:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts
|
bun run index.ts
|
||||||
```
|
```
|
||||||
+117
-81
@@ -1,33 +1,51 @@
|
|||||||
---
|
---
|
||||||
title: 'Cloudflare'
|
title: "Cloudflare"
|
||||||
description: 'Run bknd inside Cloudflare Worker'
|
description: "Run bknd inside Cloudflare Worker"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get started with Cloudflare Workers and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
To get started with Cloudflare Workers and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
<Tabs>
|
### CLI Starter
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Cloudflare CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
Create a new Cloudflare CLI starter project by running the following command:
|
||||||
npx bknd create -i cloudflare
|
|
||||||
```
|
```sh
|
||||||
</Tab>
|
npx bknd create -i cloudflare
|
||||||
<Tab title="Manual">
|
```
|
||||||
Create a new cloudflare worker project by following the [official guide](https://developers.cloudflare.com/workers/get-started/guide/), and then install bknd as a dependency:
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new cloudflare worker project by following the [official guide](https://developers.cloudflare.com/workers/get-started/guide/), and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<InstallBknd />
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
## Serve the API
|
## Serve the API
|
||||||
|
|
||||||
If you don't choose anything specific, the following code will use the `warm` mode and uses the first D1 binding it finds. See the
|
If you don't choose anything specific, the following code will use the `warm` mode and uses the first D1 binding it finds. See the
|
||||||
chapter [Using a different mode](#using-a-different-mode) for available modes.
|
chapter [Using a different mode](#using-a-different-mode) for available modes.
|
||||||
|
|
||||||
```ts src/index.ts
|
```ts title="src/index.ts"
|
||||||
import { serve, d1 } from "bknd/adapter/cloudflare";
|
import { serve, d1 } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
// scans your environment for the first D1 binding it finds
|
// scans your environment for the first D1 binding it finds
|
||||||
@@ -35,23 +53,24 @@ export default serve();
|
|||||||
|
|
||||||
// manually specifying a D1 binding:
|
// manually specifying a D1 binding:
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
app: ({ env }) => d1({ binding: env.D1_BINDING })
|
app: ({ env }) => d1({ binding: env.D1_BINDING }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// or specify binding using `bindings`
|
// or specify binding using `bindings`
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
bindings: ({ env }) => ({ db: env.D1_BINDING })
|
bindings: ({ env }) => ({ db: env.D1_BINDING }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// or use LibSQL
|
// or use LibSQL
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
app: ({ env }) => ({ url: env.DB_URL })
|
app: ({ env }) => ({ url: env.DB_URL }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information about the connection object when using LibSQL, refer to the [Database](/usage/database) guide.
|
For more information about the connection object when using LibSQL, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
Now run the worker:
|
Now run the worker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wrangler dev
|
wrangler dev
|
||||||
```
|
```
|
||||||
@@ -60,76 +79,86 @@ And confirm it works by opening [http://localhost:8787](http://localhost:8787) i
|
|||||||
your browser.
|
your browser.
|
||||||
|
|
||||||
## Serve the Admin UI
|
## Serve the Admin UI
|
||||||
|
|
||||||
Now in order to also server the static admin files, you have to modify the `wrangler.toml` to include the static assets. You can do so by either serving the static using the new [Assets feature](https://developers.cloudflare.com/workers/static-assets/), or the deprecated [Workers Site](https://developers.cloudflare.com/workers/configuration/sites/configuration/).
|
Now in order to also server the static admin files, you have to modify the `wrangler.toml` to include the static assets. You can do so by either serving the static using the new [Assets feature](https://developers.cloudflare.com/workers/static-assets/), or the deprecated [Workers Site](https://developers.cloudflare.com/workers/configuration/sites/configuration/).
|
||||||
|
|
||||||
<Tabs>
|
### Assets
|
||||||
<Tab title="Assets">
|
|
||||||
Make sure your assets point to the static assets included in the bknd package:
|
|
||||||
|
|
||||||
```toml wrangler.toml
|
Make sure your assets point to the static assets included in the bknd package:
|
||||||
assets = { directory = "node_modules/bknd/dist/static" }
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
```toml title="wrangler.toml"
|
||||||
<Tab title="Workers Sites">
|
assets = { directory = "node_modules/bknd/dist/static" }
|
||||||
Make sure your site points to the static assets included in the bknd package:
|
```
|
||||||
|
|
||||||
```toml wrangler.toml
|
### Workers Sites
|
||||||
[site]
|
|
||||||
bucket = "node_modules/bknd/dist/static"
|
|
||||||
```
|
|
||||||
|
|
||||||
And then modify the worker entry as follows:
|
Make sure your site points to the static assets included in the bknd package:
|
||||||
```ts {2, 6} src/index.ts
|
|
||||||
import { serve } from "bknd/adapter/cloudflare";
|
|
||||||
import manifest from "__STATIC_CONTENT_MANIFEST";
|
|
||||||
|
|
||||||
export default serve<Env>({
|
```toml title="wrangler.toml"
|
||||||
app: () => ({/* ... */}),
|
[site]
|
||||||
manifest
|
bucket = "node_modules/bknd/dist/static"
|
||||||
});
|
```
|
||||||
```
|
|
||||||
</Tab>
|
And then modify the worker entry as follows:
|
||||||
</Tabs>
|
|
||||||
|
```ts title="src/index.ts"
|
||||||
|
import { serve } from "bknd/adapter/cloudflare";
|
||||||
|
import manifest from "__STATIC_CONTENT_MANIFEST"; // [!code highlight]
|
||||||
|
|
||||||
|
export default serve<Env>({
|
||||||
|
app: () => ({
|
||||||
|
/* ... */
|
||||||
|
}),
|
||||||
|
manifest, // [!code highlight]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Adding custom routes
|
## Adding custom routes
|
||||||
|
|
||||||
You can also add custom routes by defining them after the app has been built, like so:
|
You can also add custom routes by defining them after the app has been built, like so:
|
||||||
```ts {5-7}
|
|
||||||
|
```ts
|
||||||
import { serve } from "bknd/adapter/cloudflare";
|
import { serve } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
// ...
|
// ...
|
||||||
onBuilt: async (app) => {
|
onBuilt: async (app) => {
|
||||||
app.server.get("/hello", (c) => c.json({ hello: "world" }));
|
// [!code highlight]
|
||||||
}
|
app.server.get("/hello", (c) => c.json({ hello: "world" })); // [!code highlight]
|
||||||
|
}, // [!code highlight]
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
The property `app.server` is a [Hono](https://hono.dev/) instance, you can literally anything you can do with Hono.
|
The property `app.server` is a [Hono](https://hono.dev/) instance, you can literally anything you can do with Hono.
|
||||||
|
|
||||||
## Using a different mode
|
## Using a different mode
|
||||||
|
|
||||||
With the Cloudflare Workers adapter, you're being offered to 4 modes to choose from (default:
|
With the Cloudflare Workers adapter, you're being offered to 4 modes to choose from (default:
|
||||||
`warm`):
|
`warm`):
|
||||||
|
|
||||||
| Mode | Description | Use Case |
|
| Mode | Description | Use Case |
|
||||||
|:----------|:-------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------|
|
| :-------- | :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `fresh` | On every request, the configuration gets refetched, app built and then served. | Ideal if you don't want to deal with eviction, KV or Durable Objects. |
|
| `fresh` | On every request, the configuration gets refetched, app built and then served. | Ideal if you don't want to deal with eviction, KV or Durable Objects. |
|
||||||
| `warm` | It tries to keep the built app in memory for as long as possible, and rebuilds if evicted. | Better response times, should be the default choice. |
|
| `warm` | It tries to keep the built app in memory for as long as possible, and rebuilds if evicted. | Better response times, should be the default choice. |
|
||||||
| `cache` | The configuration is fetched from KV to reduce the initial roundtrip to the database. | Generally faster response times with irregular access patterns. |
|
| `cache` | The configuration is fetched from KV to reduce the initial roundtrip to the database. | Generally faster response times with irregular access patterns. |
|
||||||
| `durable` | The bknd app is ran inside a Durable Object and can be configured to stay alive. | Slowest boot time, but fastest responses. Can be kept alive for as long as you want, giving similar response times as server instances. |
|
| `durable` | The bknd app is ran inside a Durable Object and can be configured to stay alive. | Slowest boot time, but fastest responses. Can be kept alive for as long as you want, giving similar response times as server instances. |
|
||||||
|
|
||||||
### Modes: `fresh` and `warm`
|
### Modes: `fresh` and `warm`
|
||||||
|
|
||||||
To use either `fresh` or `warm`, all you have to do is adding the desired mode to `cloudflare.
|
To use either `fresh` or `warm`, all you have to do is adding the desired mode to `cloudflare.
|
||||||
mode`, like so:
|
mode`, like so:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { serve } from "bknd/adapter/cloudflare";
|
import { serve } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve({
|
export default serve({
|
||||||
// ...
|
// ...
|
||||||
mode: "fresh" // mode: "fresh" | "warm" | "cache" | "durable"
|
mode: "fresh", // mode: "fresh" | "warm" | "cache" | "durable"
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mode: `cache`
|
### Mode: `cache`
|
||||||
|
|
||||||
For the cache mode to work, you also need to specify the KV to be used. For this, use the
|
For the cache mode to work, you also need to specify the KV to be used. For this, use the
|
||||||
`bindings` property:
|
`bindings` property:
|
||||||
|
|
||||||
@@ -137,29 +166,32 @@ For the cache mode to work, you also need to specify the KV to be used. For this
|
|||||||
import { serve } from "bknd/adapter/cloudflare";
|
import { serve } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
// ...
|
// ...
|
||||||
mode: "cache",
|
mode: "cache",
|
||||||
bindings: ({ env }) => ({ kv: env.KV })
|
bindings: ({ env }) => ({ kv: env.KV }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mode: `durable` (advanced)
|
### Mode: `durable` (advanced)
|
||||||
|
|
||||||
To use the `durable` mode, you have to specify the Durable Object to extract from your
|
To use the `durable` mode, you have to specify the Durable Object to extract from your
|
||||||
environment, and additionally export the `DurableBkndApp` class:
|
environment, and additionally export the `DurableBkndApp` class:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { serve, DurableBkndApp } from "bknd/adapter/cloudflare";
|
import { serve, DurableBkndApp } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export { DurableBkndApp };
|
export { DurableBkndApp };
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
// ...
|
// ...
|
||||||
mode: "durable",
|
mode: "durable",
|
||||||
bindings: ({ env }) => ({ dobj: env.DOBJ }),
|
bindings: ({ env }) => ({ dobj: env.DOBJ }),
|
||||||
keepAliveSeconds: 60 // optional
|
keepAliveSeconds: 60, // optional
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, you need to define the Durable Object in your `wrangler.toml` file (refer to the [Durable
|
Next, you need to define the Durable Object in your `wrangler.toml` file (refer to the [Durable
|
||||||
Objects](https://developers.cloudflare.com/durable-objects/) documentation):
|
Objects](https://developers.cloudflare.com/durable-objects/) documentation):
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[[durable_objects.bindings]]
|
[[durable_objects.bindings]]
|
||||||
name = "DOBJ"
|
name = "DOBJ"
|
||||||
@@ -173,25 +205,28 @@ new_classes = ["DurableBkndApp"]
|
|||||||
Since the communication between the Worker and Durable Object is serialized, the `onBuilt`
|
Since the communication between the Worker and Durable Object is serialized, the `onBuilt`
|
||||||
property won't work. To use it (e.g. to specify special routes), you need to extend from the
|
property won't work. To use it (e.g. to specify special routes), you need to extend from the
|
||||||
`DurableBkndApp`:
|
`DurableBkndApp`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { App } from "bknd";
|
import type { App } from "bknd";
|
||||||
import { serve, DurableBkndApp } from "bknd/adapter/cloudflare";
|
import { serve, DurableBkndApp } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve({
|
export default serve({
|
||||||
// ...
|
// ...
|
||||||
mode: "durable",
|
mode: "durable",
|
||||||
bindings: ({ env }) => ({ dobj: env.DOBJ }),
|
bindings: ({ env }) => ({ dobj: env.DOBJ }),
|
||||||
keepAliveSeconds: 60 // optional
|
keepAliveSeconds: 60, // optional
|
||||||
});
|
});
|
||||||
|
|
||||||
export class CustomDurableBkndApp extends DurableBkndApp {
|
export class CustomDurableBkndApp extends DurableBkndApp {
|
||||||
async onBuilt(app: App) {
|
async onBuilt(app: App) {
|
||||||
app.modules.server.get("/custom/endpoint", (c) => c.text("Custom"));
|
app.modules.server.get("/custom/endpoint", (c) => c.text("Custom"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In case you've already deployed your Worker, the deploy command may complain about a new class
|
In case you've already deployed your Worker, the deploy command may complain about a new class
|
||||||
being used. To fix this issue, you need to add a "rename migration":
|
being used. To fix this issue, you need to add a "rename migration":
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[[durable_objects.bindings]]
|
[[durable_objects.bindings]]
|
||||||
name = "DOBJ"
|
name = "DOBJ"
|
||||||
@@ -208,26 +243,27 @@ deleted_classes = ["DurableBkndApp"]
|
|||||||
```
|
```
|
||||||
|
|
||||||
## D1 Sessions (experimental)
|
## D1 Sessions (experimental)
|
||||||
|
|
||||||
D1 now supports to enable [global read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/). This allows to reduce latency by reading from the closest region. In order for this to work, D1 has to be started from a bookmark. You can enable this behavior on bknd by setting the `d1.session` property:
|
D1 now supports to enable [global read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/). This allows to reduce latency by reading from the closest region. In order for this to work, D1 has to be started from a bookmark. You can enable this behavior on bknd by setting the `d1.session` property:
|
||||||
|
|
||||||
```typescript src/index.ts
|
```typescript title="src/index.ts"
|
||||||
import { serve } from "bknd/adapter/cloudflare";
|
import { serve } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve({
|
export default serve({
|
||||||
// currently recommended to use "fresh" mode
|
// currently recommended to use "fresh" mode
|
||||||
// otherwise consecutive requests will use the same bookmark
|
// otherwise consecutive requests will use the same bookmark
|
||||||
mode: "fresh",
|
mode: "fresh",
|
||||||
// ...
|
// ...
|
||||||
d1: {
|
d1: {
|
||||||
// enables D1 sessions
|
// enables D1 sessions
|
||||||
session: true,
|
session: true,
|
||||||
// (optional) restrict the transport, options: "header" | "cookie"
|
// (optional) restrict the transport, options: "header" | "cookie"
|
||||||
// if not specified, it supports both
|
// if not specified, it supports both
|
||||||
transport: "cookie",
|
transport: "cookie",
|
||||||
// (optional) choose session constraint if not bookmark present
|
// (optional) choose session constraint if not bookmark present
|
||||||
// options: "first-primary" | "first-unconstrained"
|
// options: "first-primary" | "first-unconstrained"
|
||||||
first: "first-primary"
|
first: "first-primary",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -235,4 +271,4 @@ If bknd is used in a stateful user context (like in a browser), it'll automatica
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -H "x-cf-d1-session: <bookmark>" ...
|
curl -H "x-cf-d1-session: <bookmark>" ...
|
||||||
```
|
```
|
||||||
+10
-5
@@ -1,14 +1,17 @@
|
|||||||
---
|
---
|
||||||
title: 'Docker'
|
title: "Docker"
|
||||||
description: 'Official docker image for bknd'
|
description: "Official docker image for bknd"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
# Official `bknd` Docker image
|
# Official `bknd` Docker image
|
||||||
|
|
||||||
The docker image intentially doesn't copy any data into the image for now, so you can copy the Dockerfile and build the image anywhere.
|
The docker image intentially doesn't copy any data into the image for now, so you can copy the Dockerfile and build the image anywhere.
|
||||||
|
|
||||||
Locate the Dockerfile either by pulling the [repository](https://github.com/bknd-io/bknd) and navigating to the `docker` directory, or download from [here](https://github.com/bknd-io/bknd/blob/main/docker/Dockerfile).
|
Locate the Dockerfile either by pulling the [repository](https://github.com/bknd-io/bknd) and navigating to the `docker` directory, or download from [here](https://github.com/bknd-io/bknd/blob/main/docker/Dockerfile).
|
||||||
|
|
||||||
## Building the Docker image
|
## Building the Docker image
|
||||||
|
|
||||||
To build the Docker image, run the following command:
|
To build the Docker image, run the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -16,11 +19,13 @@ docker build -t bknd .
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you want to override the bknd version used, you can pass a `VERSION` build argument:
|
If you want to override the bknd version used, you can pass a `VERSION` build argument:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build --build-arg VERSION=<version> -t bknd .
|
docker build --build-arg VERSION=<version> -t bknd .
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running the Docker container
|
## Running the Docker container
|
||||||
|
|
||||||
To run the Docker container, run the following command:
|
To run the Docker container, run the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -34,6 +39,7 @@ docker run -p 1337:1337 -e ARGS="--db-url file:/data/data.db" bknd
|
|||||||
```
|
```
|
||||||
|
|
||||||
To mount the data directory to the host, you can use the `-v` flag:
|
To mount the data directory to the host, you can use the `-v` flag:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -p 1337:1337 -v /path/to/data:/data bknd
|
docker run -p 1337:1337 -v /path/to/data:/data bknd
|
||||||
```
|
```
|
||||||
@@ -42,7 +48,7 @@ docker run -p 1337:1337 -v /path/to/data:/data bknd
|
|||||||
|
|
||||||
If you want to use docker compose and build the image directly from the git repository.
|
If you want to use docker compose and build the image directly from the git repository.
|
||||||
|
|
||||||
```yaml compose.yml
|
```yaml title="compose.yml"
|
||||||
services:
|
services:
|
||||||
bknd:
|
bknd:
|
||||||
pull_policy: build
|
pull_policy: build
|
||||||
@@ -55,12 +61,11 @@ services:
|
|||||||
- ${DATA_DIR:-.}/data:/data
|
- ${DATA_DIR:-.}/data:/data
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
The docker compose file can be extended to build a specific version of bknd.
|
The docker compose file can be extended to build a specific version of bknd.
|
||||||
Extend the `build` section with `args` and `labels`.
|
Extend the `build` section with `args` and `labels`.
|
||||||
Inside `args`, you can pass a `VERSION` build argument, and use `labels` so the built image receives a unique identifier.
|
Inside `args`, you can pass a `VERSION` build argument, and use `labels` so the built image receives a unique identifier.
|
||||||
|
|
||||||
```yaml compose.yml
|
```yaml title="compose.yml"
|
||||||
services:
|
services:
|
||||||
bknd:
|
bknd:
|
||||||
pull_policy: build
|
pull_policy: build
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"pages": ["node", "bun", "cloudflare", "aws", "docker"]
|
||||||
|
}
|
||||||
+41
-22
@@ -1,49 +1,68 @@
|
|||||||
---
|
---
|
||||||
title: 'Node'
|
title: "Node"
|
||||||
description: 'Run bknd inside Node'
|
description: "Run bknd inside Node"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
import InstallBknd from '/snippets/install-bknd.mdx';
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To get started with Node and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
To get started with Node and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||||
|
|
||||||
<Tabs>
|
### CLI Starter
|
||||||
<Tab title="CLI Starter">
|
|
||||||
Create a new Node CLI starter project by running the following command:
|
|
||||||
|
|
||||||
```sh
|
Create a new Node CLI starter project by running the following command:
|
||||||
npx bknd create -i node
|
|
||||||
```
|
```sh
|
||||||
</Tab>
|
npx bknd create -i node
|
||||||
<Tab title="Manual">
|
```
|
||||||
Create a new Node project and then install bknd as a dependency:
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Create a new Node project and then install bknd as a dependency:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="pnpm"
|
||||||
|
pnpm install bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="yarn"
|
||||||
|
yarn add bknd
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bun add bknd
|
||||||
|
```
|
||||||
|
|
||||||
<InstallBknd />
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Serve the API & static files
|
## Serve the API & static files
|
||||||
|
|
||||||
The `serve` function of the Node adapter makes sure to also serve the static files required for
|
The `serve` function of the Node adapter makes sure to also serve the static files required for
|
||||||
the admin panel.
|
the admin panel.
|
||||||
|
|
||||||
``` tsx
|
```tsx title="server.ts"
|
||||||
// index.js
|
|
||||||
import { serve } from "bknd/adapter/node";
|
import { serve } from "bknd/adapter/node";
|
||||||
|
|
||||||
// if the configuration is omitted, it uses an in-memory database
|
// if the configuration is omitted, it uses an in-memory database
|
||||||
/** @type {import("bknd/adapter/node").NodeAdapterOptions} */
|
/** @type {import("bknd/adapter/node").NodeAdapterOptions} */
|
||||||
const config = {
|
const config = {
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db"
|
url: "file:data.db",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
serve(config);
|
serve(config);
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||||
|
|
||||||
Run the application using node by executing:
|
Run the application using node by executing:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node index.js
|
node server.js
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
title: "Introduction"
|
||||||
|
description: "Integrate bknd into your runtime/framework of choice"
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
|
||||||
|
## Start with a Framework
|
||||||
|
|
||||||
|
bknd seamlessly integrates with popular frameworks, allowing you to use what you're already familar with. The following guides will help you get started with your framework of choice.
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
<Card icon={<Icon icon="tabler:brand-nextjs" className="text-fd-primary !size-6" />} title="NextJS" href="/integration/nextjs" />
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon icon="simple-icons:reactrouter" className="text-fd-primary !size-6" />
|
||||||
|
}
|
||||||
|
title="React Router"
|
||||||
|
href="/integration/react-router"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:astro" className="text-fd-primary !size-6" />}
|
||||||
|
title="Astro"
|
||||||
|
href="/integration/astro"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
|
Create a new issue to request a guide for your framework.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
|
|
||||||
|
## Start with a Runtime
|
||||||
|
|
||||||
|
If you prefer to use a runtime instead of a framework, you can choose from the following options. These runtimes allow you to serve the API and UI in the runtime's native server and serve the UI assets statically from `node_modules`.
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="tabler:brand-nodejs" className="text-fd-primary !size-6" />}
|
||||||
|
title="NodeJS"
|
||||||
|
href="/integration/node"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:bun" className="text-fd-primary !size-6" />}
|
||||||
|
title="Bun"
|
||||||
|
href="/integration/bun"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="devicon-plain:cloudflareworkers"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Cloudflare"
|
||||||
|
href="/integration/cloudflare"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
||||||
|
title="AWS Lambda"
|
||||||
|
href="/integration/aws"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:vitest" className="text-fd-primary !size-6" />}
|
||||||
|
title="Vite"
|
||||||
|
href="/integration/vite"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="streamline-logos:docker-logo-solid"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Docker"
|
||||||
|
href="/integration/docker"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
|
Create a new issue to request a guide for your runtime.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
### Serving the backend (API)
|
||||||
|
|
||||||
|
Serve the backend as an API for any JS runtime or framework. The latter is especially handy, as it allows you to deploy your frontend and backend bundled together. Furthermore it allows adding additional logic in a way you're already familar with. Just add another route and you're good to go.
|
||||||
|
|
||||||
|
Here is an example of serving the API using node:
|
||||||
|
|
||||||
|
```js title="index.js"
|
||||||
|
import { serve } from "bknd/adapter/node";
|
||||||
|
serve();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Serving the Admin UI
|
||||||
|
|
||||||
|
The admin UI allows to manage your data including full configuration of your backend using a graphical user interface. Using `vite`, your admin route looks like this:
|
||||||
|
|
||||||
|
```tsx title="admin.tsx"
|
||||||
|
import { Admin } from "bknd/ui";
|
||||||
|
import "bknd/dist/styles.css";
|
||||||
|
|
||||||
|
export default function AdminPage() {
|
||||||
|
return <Admin withProvider />;
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"title": "Documentation",
|
||||||
|
"root": true,
|
||||||
|
"description": "Technical reference and integration",
|
||||||
|
"icon": "Book",
|
||||||
|
"slug": "",
|
||||||
|
"pages": [
|
||||||
|
"---Getting Started---",
|
||||||
|
"start",
|
||||||
|
"motivation",
|
||||||
|
"---Usage---",
|
||||||
|
"./usage/introduction",
|
||||||
|
"./usage/database",
|
||||||
|
"./usage/cli",
|
||||||
|
"./usage/sdk",
|
||||||
|
"./usage/react",
|
||||||
|
"./usage/elements",
|
||||||
|
"---Extending---",
|
||||||
|
"./extending/config",
|
||||||
|
"./extending/events",
|
||||||
|
"---Integration---",
|
||||||
|
"./integration/introduction",
|
||||||
|
"./integration/(frameworks)/",
|
||||||
|
"./integration/(runtimes)/",
|
||||||
|
"---Modules---",
|
||||||
|
"./modules/overview",
|
||||||
|
"./modules/server",
|
||||||
|
"./modules/data",
|
||||||
|
"./modules/auth",
|
||||||
|
"./modules/media",
|
||||||
|
"./modules/flows"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
---
|
---
|
||||||
title: 'Auth'
|
title: "Auth"
|
||||||
description: 'Easily implement reliable authentication strategies.'
|
description: "Easily implement reliable authentication strategies."
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Authentication is essential for securing applications, and **bknd** provides a straightforward approach to implementing robust strategies.
|
Authentication is essential for securing applications, and **bknd** provides a straightforward approach to implementing robust strategies.
|
||||||
|
|
||||||
### **Core Features**
|
### **Core Features**
|
||||||
|
|
||||||
- Automatically creates a `user` entity, with support for customizable fields.
|
- Automatically creates a `user` entity, with support for customizable fields.
|
||||||
- Authenticates users based on configurable strategies.
|
- Authenticates users based on configurable strategies.
|
||||||
- Generates JWTs according to specified configurations.
|
- Generates JWTs according to specified configurations.
|
||||||
- Provides session management for maintaining user authentication state.
|
- Provides session management for maintaining user authentication state.
|
||||||
|
|
||||||
### **Supported Authentication Strategies**
|
### **Supported Authentication Strategies**
|
||||||
|
|
||||||
- **Email/Password**: Supports plain and SHA-256 password hashing (bcrypt planned for future
|
- **Email/Password**: Supports plain and SHA-256 password hashing (bcrypt planned for future
|
||||||
releases).
|
releases).
|
||||||
- **OAuth/OIDC**: Works with providers like Google and GitHub.
|
- **OAuth/OIDC**: Works with providers like Google and GitHub.
|
||||||
- Compatible with any specification-compliant provider.
|
- Compatible with any specification-compliant provider.
|
||||||
|
|
||||||
@@ -1,37 +1,47 @@
|
|||||||
---
|
---
|
||||||
title: 'Data'
|
title: "Data"
|
||||||
description: 'Define, query, and control your data with ease.'
|
description: "Define, query, and control your data with ease."
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Data is the lifeblood of any application, and **bknd** provides the tools to handle it effortlessly. From defining entities to executing complex queries, bknd offers a developer-friendly, intuitive, and powerful data management experience.
|
Data is the lifeblood of any application, and **bknd** provides the tools to handle it effortlessly. From defining entities to executing complex queries, bknd offers a developer-friendly, intuitive, and powerful data management experience.
|
||||||
|
|
||||||
### **Define Your Data**
|
### **Define Your Data**
|
||||||
|
|
||||||
Model entities with **fields** and **relationships**, automatically synced to your database.
|
Model entities with **fields** and **relationships**, automatically synced to your database.
|
||||||
|
|
||||||
- Supported field types: `primary`, `text`, `number`, `date`, `boolean`, `enum`, `json`, and `jsonschema`.
|
- Supported field types: `primary`, `text`, `number`, `date`, `boolean`, `enum`, `json`, and `jsonschema`.
|
||||||
- Relationship types: `many-to-one`, `one-to-one`, `many-to-many`, and `polymorphic`.
|
- Relationship types: `many-to-one`, `one-to-one`, `many-to-many`, and `polymorphic`.
|
||||||
- Add **indices** to enhance database performance: single, compound, and unique indices.
|
- Add **indices** to enhance database performance: single, compound, and unique indices.
|
||||||
|
|
||||||
### **Entity Management**
|
### **Entity Management**
|
||||||
|
|
||||||
Use the **EntityManager** to simplify handling your entities. Access data efficiently with the **Repository**:
|
Use the **EntityManager** to simplify handling your entities. Access data efficiently with the **Repository**:
|
||||||
|
|
||||||
- Select specific properties to return.
|
- Select specific properties to return.
|
||||||
- Define sort directions, limits, and offsets.
|
- Define sort directions, limits, and offsets.
|
||||||
- Include or join relational data seamlessly within a single query using `with` and joins.
|
- Include or join relational data seamlessly within a single query using `with` and joins.
|
||||||
- Apply robust filtering with an extensive `where` object: `$eq`, `$ne`, `$isnull`, `$notnull`, `$in`, `$notin`, `$gt`, `$gte`, `$lt`, `$lte`, `$between`.
|
- Apply robust filtering with an extensive `where` object: `$eq`, `$ne`, `$isnull`, `$notnull`, `$in`, `$notin`, `$gt`, `$gte`, `$lt`, `$lte`, `$between`.
|
||||||
|
|
||||||
### **Seamless Data Manipulation with Mutators**
|
### **Seamless Data Manipulation with Mutators**
|
||||||
|
|
||||||
Create, update, and delete entity data with confidence.
|
Create, update, and delete entity data with confidence.
|
||||||
|
|
||||||
- Validates data against the entity schema.
|
- Validates data against the entity schema.
|
||||||
- (coming soon) Supports relational data with flexible syntax: `$create`, `$set`, `$attach`,
|
- (coming soon) Supports relational data with flexible syntax: `$create`, `$set`, `$attach`,
|
||||||
`$detach`.
|
`$detach`.
|
||||||
|
|
||||||
### **Powerful Event System**
|
### **Powerful Event System**
|
||||||
|
|
||||||
Hook into critical lifecycle events for fine-grained control:
|
Hook into critical lifecycle events for fine-grained control:
|
||||||
|
|
||||||
- Repository events: `find-one-before`, `find-one-after`, `find-many-before`, `find-many-after`.
|
- Repository events: `find-one-before`, `find-one-after`, `find-many-before`, `find-many-after`.
|
||||||
- Mutator events: `insert-before`, `insert-after`, `update-before`, `update-after`, `delete-before`, `delete-after`.
|
- Mutator events: `insert-before`, `insert-after`, `update-before`, `update-after`, `delete-before`, `delete-after`.
|
||||||
|
|
||||||
### **Enhanced Database Communication**
|
### **Enhanced Database Communication**
|
||||||
|
|
||||||
The **Connection** class communicates with the database. It's based on kysely, so that it
|
The **Connection** class communicates with the database. It's based on kysely, so that it
|
||||||
generally supports multiple database dialects (but currently only SQLite/LibSQL is supported).
|
generally supports multiple database dialects (but currently only SQLite/LibSQL is supported).
|
||||||
|
|
||||||
Whether you're modeling simple data structures or managing complex relationships, bknd's data tools empower you to build applications with confidence and scalability.
|
Whether you're modeling simple data structures or managing complex relationships, bknd's data tools empower you to build applications with confidence and scalability.
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: "Flows"
|
||||||
|
description: "Design and run workflows with seamless automation."
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
Flows is the youngest module and its UI is still in development. For the sake
|
||||||
|
of tech preview, we decided to exclude it from the Admin UI for now. It will
|
||||||
|
be available very soon.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
**bknd** enables you to automate tasks and processes through flexible and powerful workflows.
|
||||||
|
|
||||||
|
## **Core Features**
|
||||||
|
|
||||||
|
### Trigger-Based Executions
|
||||||
|
|
||||||
|
- **Manual**: Trigger workflows manually.
|
||||||
|
- **System Events**: Automate workflows based on system events, such as:
|
||||||
|
- **Data Events**: Entity create, update, or delete.
|
||||||
|
- **Auth Events**: User sign-in, sign-up, sign-out, or deletion.
|
||||||
|
- **Media Events**: File uploads or downloads.
|
||||||
|
- **Server Events**: Before and after request/response handling.
|
||||||
|
- **HTTP Trigger**: Map workflows to any URL path for external triggers.
|
||||||
|
|
||||||
|
- **Custom Event Hooks**: Define and trigger custom events within workflows for tailored automation.
|
||||||
|
|
||||||
|
### Task Management
|
||||||
|
|
||||||
|
- Define tasks to run in sequence, parallel, or loops.
|
||||||
|
- Enable conditional task execution based on output results.
|
||||||
|
|
||||||
|
### Execution Modes
|
||||||
|
|
||||||
|
- **Asynchronous**: Run workflows in the background.
|
||||||
|
- **Synchronous**: Block further execution until the workflow completes, similar to traditional code execution.
|
||||||
|
|
||||||
|
- **Reusable Components**: Create reusable task sequences (sub-workflows) for better organization and efficiency.
|
||||||
|
- **OpenAPI Specification (OAS) Tasks**: Upload an OpenAPI spec to execute API requests as part of a workflow.
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
title: "Media"
|
||||||
|
description: "Effortlessly manage and serve all your media files."
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
**bknd** provides a flexible and efficient way to handle media files, making it easy to upload, manage, and deliver content across various platforms.
|
||||||
|
|
||||||
|
### **Core Features**
|
||||||
|
|
||||||
|
- **File Uploads**: Supports direct (chunked coming soon) uploads of files up to 5GB (depending
|
||||||
|
on your environment).
|
||||||
|
- **Adapter-Based Design**:
|
||||||
|
- Pre-built support for S3, S3-compatible services (e.g., R2, Tigris), and Cloudinary.
|
||||||
|
- Extend functionality by implementing custom adapters.
|
||||||
|
- **Entity Integration**: Attach media files directly to entities for seamless data association.
|
||||||
|
- **Content Delivery**: Serve media over an API endpoint or directly from your provider.
|
||||||
|
|
||||||
|
The media tools are designed to integrate effortlessly into your workflows, offering scalability
|
||||||
|
and control without added complexity.
|
||||||
|
|
||||||
|
### Pre-built support for S3
|
||||||
|
|
||||||
|
There are two ways to enable S3 or S3 compatible storage in bknd.
|
||||||
|
|
||||||
|
1. Enable via the admin UI.
|
||||||
|
|
||||||
|
Simply navigate to the **Media** tab of the bknd admin UI and enable the S3 media support.
|
||||||
|
Enter your AWS S3-compatible storage Access Key, Secret Access Key, and URL.
|
||||||
|
This will automatically configure the S3 adapter for you.
|
||||||
|
|
||||||
|
**URL Format Examples:**
|
||||||
|
|
||||||
|
- **S3**: `https://{bucket}.s3.{region}.amazonaws.com`
|
||||||
|
- **R2 (Cloudflare)**: `https://{account_id}.r2.cloudflarestorage.com/{bucket}`
|
||||||
|
|
||||||
|
2. Enable programmatically.
|
||||||
|
|
||||||
|
To enable using a code-first approach, create an [Initial Structure](/usage/database#initial-structure) using the `initialConfig` option in your `bknd.config.ts` file.
|
||||||
|
|
||||||
|
```typescript title="bknd.config.ts"
|
||||||
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
initialConfig: {
|
||||||
|
media: {
|
||||||
|
enabled: true,
|
||||||
|
adapter: {
|
||||||
|
type: "s3",
|
||||||
|
config: {
|
||||||
|
access_key: "<key>",
|
||||||
|
secret_access_key: "<secret key>",
|
||||||
|
url: "<bucket url>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies BkndConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local adapter for development
|
||||||
|
|
||||||
|
For local development and testing, you can use the local file system adapter. This is particularly useful when working with Node.js environments.
|
||||||
|
|
||||||
|
```typescript title="bknd.config.ts"
|
||||||
|
import { registerLocalMediaAdapter } from "bknd/adapter/node";
|
||||||
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
|
// Register the local media adapter
|
||||||
|
const local = registerLocalMediaAdapter();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
initialConfig: {
|
||||||
|
media: {
|
||||||
|
enabled: true,
|
||||||
|
adapter: local({
|
||||||
|
path: "./public/uploads", // Files will be stored in this directory
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies BkndConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration will store uploaded files in the specified directory,
|
||||||
|
making them accessible through your application's public path (in this case)
|
||||||
|
or at `/api/media/file/{filename}`.
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
title: "Overview"
|
||||||
|
description: "General overview of the system"
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
|
||||||
|
This backend system focuses on 4 essential building blocks which can be tightly connected:
|
||||||
|
Data, Auth, Media and Flows.
|
||||||
|
The main idea is to supply all baseline functionality required in order to accomplish complex
|
||||||
|
logic and behaviors – instead of hard coding it into the system code. This way, almost any part
|
||||||
|
of the application is customizable and additionally won't limit you to what it can do.
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
<Card icon={<Icon icon="majesticons:data-line" className="text-fd-primary !size-6" />} title="Data" href="/modules/data">
|
||||||
|
Define, query, and control your data with ease.
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon icon="meteor-icons:fingerprint" className="text-fd-primary !size-6" />
|
||||||
|
}
|
||||||
|
title="Auth"
|
||||||
|
href="/modules/auth"
|
||||||
|
>
|
||||||
|
Easily implement reliable authentication strategies.
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon icon="flowbite:image-outline" className="text-fd-primary !size-6" />
|
||||||
|
}
|
||||||
|
title="Media"
|
||||||
|
href="/modules/media"
|
||||||
|
>
|
||||||
|
Effortlessly manage and serve all your media files.
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="hugeicons:workflow-square-03"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Flows"
|
||||||
|
href="/modules/flows"
|
||||||
|
>
|
||||||
|
Design and run workflows with seamless automation.
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
</Cards>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: "Server"
|
||||||
|
description: "Effortlessly manage and serve all your files."
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
<Callout type="info" title="The documentation is currently a work in progress">
|
||||||
|
Check back soon — or stay updated on our progress on
|
||||||
|
[GitHub](https://github.com/bknd-io/bknd) and join the conversation in
|
||||||
|
[Discord](https://discord.gg/952SFk8Tb8).
|
||||||
|
</Callout>
|
||||||
@@ -1,23 +1,27 @@
|
|||||||
---
|
---
|
||||||
title: "Motivation"
|
title: "Motivation"
|
||||||
description: "Why another backend system?"
|
description: "Why another backend system?"
|
||||||
|
icon: Rocket
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Creating digital products always requires developing both the backend (the logic) and the frontend (the appearance). Building a backend from scratch demands deep knowledge in areas such as authentication and database management. Using a backend framework can speed up initial development, but it still requires ongoing effort to work within its constraints (e.g., *"how to do X with Y?"*), which can quickly slow you down. Choosing a backend system is a tough decision, as you might not be aware of its limitations until you encounter them.
|
Creating digital products always requires developing both the backend (the logic) and the frontend (the appearance). Building a backend from scratch demands deep knowledge in areas such as authentication and database management. Using a backend framework can speed up initial development, but it still requires ongoing effort to work within its constraints (e.g., _"how to do X with Y?"_), which can quickly slow you down. Choosing a backend system is a tough decision, as you might not be aware of its limitations until you encounter them.
|
||||||
|
|
||||||
<Check>
|
<CalloutPositive title="The solution">
|
||||||
**The solution:** A backend system that only assumes and implements primitive details, integrates into multiple environments, and adheres to industry standards.
|
A backend system that only assumes and implements primitive details,
|
||||||
</Check>
|
integrates into multiple environments, and adheres to industry standards.
|
||||||
|
</CalloutPositive>
|
||||||
|
|
||||||
For the sake of brevity, let's assume you are looking for a "backend system" rather than dealing with custom implementations yourself. Let's identify the most common challenges:
|
For the sake of brevity, let's assume you are looking for a "backend system" rather than dealing with custom implementations yourself. Let's identify the most common challenges:
|
||||||
|
|
||||||
1. Database lock-in
|
1. Database lock-in
|
||||||
2. Environment and framework lock-in
|
2. Environment and framework lock-in
|
||||||
3. Deviation from standards (such as `X-Auth` headers for authentication)
|
3. Deviation from standards (such as `X-Auth` headers for authentication)
|
||||||
4. *Wrong-for-your-use-case* implementations
|
4. _Wrong-for-your-use-case_ implementations
|
||||||
5. Complex self-hosting
|
5. Complex self-hosting
|
||||||
|
|
||||||
## Database lock-in
|
## Database lock-in
|
||||||
|
|
||||||
As the developer of a backend system, you must make tough decisions, one of which is choosing which database(s) to support. To simplify development, many systems lock you into a single database, leveraging its advanced features.
|
As the developer of a backend system, you must make tough decisions, one of which is choosing which database(s) to support. To simplify development, many systems lock you into a single database, leveraging its advanced features.
|
||||||
|
|
||||||
But isn't the database known to be the hardest part to scale? Isn't more logic moving to the application layer? Haven't NoSQL databases proven this? If you're like me, you may have dipped your toes into the NoSQL world only to quickly return to SQL. SQL is known, predictable, and safe. But what if we could have both? NoSQL offers flexibility and scalability, yet querying it is tedious due to vendor-specific implementations.
|
But isn't the database known to be the hardest part to scale? Isn't more logic moving to the application layer? Haven't NoSQL databases proven this? If you're like me, you may have dipped your toes into the NoSQL world only to quickly return to SQL. SQL is known, predictable, and safe. But what if we could have both? NoSQL offers flexibility and scalability, yet querying it is tedious due to vendor-specific implementations.
|
||||||
@@ -25,21 +29,23 @@ But isn't the database known to be the hardest part to scale? Isn't more logic m
|
|||||||
To get the best of both worlds, bknd focuses on the weakest SQL database (SQLite), treating it as a data store and query interface. Schema details and enforcement are moved to the application layer, making it easy to adjust a default value or property length. The added benefit is that any SQL database could theoretically work the same way, and since it's all TypeScript, the same validation logic can be used on both the client and server sides–you can validate your data before it even reaches your server. It even works without database-enforced referential integrity, as the integrity checks occur on the application layer. This opens the door to NewSQL systems like PlanetScale.
|
To get the best of both worlds, bknd focuses on the weakest SQL database (SQLite), treating it as a data store and query interface. Schema details and enforcement are moved to the application layer, making it easy to adjust a default value or property length. The added benefit is that any SQL database could theoretically work the same way, and since it's all TypeScript, the same validation logic can be used on both the client and server sides–you can validate your data before it even reaches your server. It even works without database-enforced referential integrity, as the integrity checks occur on the application layer. This opens the door to NewSQL systems like PlanetScale.
|
||||||
|
|
||||||
## Environment and framework lock-in
|
## Environment and framework lock-in
|
||||||
|
|
||||||
There are backend systems that embed themselves into a specific React framework. This works well until you realize it doesn't support your preferred framework or the new hyped one you're considering switching to. Just like database choices, decisions must be made. The easiest path is to select a single option and let people live with it.
|
There are backend systems that embed themselves into a specific React framework. This works well until you realize it doesn't support your preferred framework or the new hyped one you're considering switching to. Just like database choices, decisions must be made. The easiest path is to select a single option and let people live with it.
|
||||||
|
|
||||||
Alternatively, you could develop for the weakest environment (workerd) by strictly using Web APIs, avoiding shortcuts, and implementing certain logic manually because the go-to package is using Node APIs. This isn't always fun, but it's essential. The benefit? It works anywhere JavaScript does.
|
Alternatively, you could develop for the weakest environment (workerd) by strictly using Web APIs, avoiding shortcuts, and implementing certain logic manually because the go-to package is using Node APIs. This isn't always fun, but it's essential. The benefit? It works anywhere JavaScript does.
|
||||||
|
|
||||||
bknd is the only backend system that not only works with any JavaScript framework but also integrates directly into it. It runs within the framework, enabling a single deployment for your entire app.
|
bknd is the only backend system that not only works with any JavaScript framework but also integrates directly into it. It runs within the framework, enabling a single deployment for your entire app.
|
||||||
|
|
||||||
*"But isn't it ironic that it forces a JavaScript environment?"* you might ask. And you're right, but it also allows running standalone via CLI or Docker.
|
_"But isn't it ironic that it forces a JavaScript environment?"_ you might ask. And you're right, but it also allows running standalone via CLI or Docker.
|
||||||
|
|
||||||
|
|
||||||
## Deviation from standards
|
## Deviation from standards
|
||||||
|
|
||||||
One of the biggest frustrations I've encountered is when software vendors choose custom headers for authentication or implement query parameters in a format they find more suitable—such as unencoded JSON for simplicity. When you are in full control, it's tempting to use a more suitable format, or just use an auth-ish name for the header property–after all, it's just a header, right?
|
One of the biggest frustrations I've encountered is when software vendors choose custom headers for authentication or implement query parameters in a format they find more suitable—such as unencoded JSON for simplicity. When you are in full control, it's tempting to use a more suitable format, or just use an auth-ish name for the header property–after all, it's just a header, right?
|
||||||
|
|
||||||
The issue is that users may rely on HTTP clients that offer built-in authentication methods, which won't include your custom solution. Custom `SearchParams` implementations might be convenient, but translating them across different environments and languages can be challenging without trial and error.
|
The issue is that users may rely on HTTP clients that offer built-in authentication methods, which won't include your custom solution. Custom `SearchParams` implementations might be convenient, but translating them across different environments and languages can be challenging without trial and error.
|
||||||
|
|
||||||
bknd strives to adhere to web standards as much as possible while offering handy alternatives. Here's an example of the `select` search parameter for retrieving a list of entities:
|
bknd strives to adhere to web standards as much as possible while offering handy alternatives. Here's an example of the `select` search parameter for retrieving a list of entities:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/api/data/todos?select=id&select=name # web standard
|
/api/data/todos?select=id&select=name # web standard
|
||||||
/api/data/todos?select=id,name # handy alternative
|
/api/data/todos?select=id,name # handy alternative
|
||||||
@@ -47,13 +53,14 @@ bknd strives to adhere to web standards as much as possible while offering handy
|
|||||||
|
|
||||||
If you ever find an instance where bknd isn't adhering to standards or could be improved, please feel free to [file an issue](https://github.com/bknd-io/bknd/issues/new). Your feedback is greatly appreciated!
|
If you ever find an instance where bknd isn't adhering to standards or could be improved, please feel free to [file an issue](https://github.com/bknd-io/bknd/issues/new). Your feedback is greatly appreciated!
|
||||||
|
|
||||||
|
|
||||||
## Wrong-for-your-use-case implementations
|
## Wrong-for-your-use-case implementations
|
||||||
|
|
||||||
If you've ever developed a social chat application, you likely discovered the extensive feature depth required—features we often take for granted. Things like socket connections for single and group chats, partial loading, asset attachments, and emoji reactions. Even more frustrating, these features make the app being considered incomplete until delivered.
|
If you've ever developed a social chat application, you likely discovered the extensive feature depth required—features we often take for granted. Things like socket connections for single and group chats, partial loading, asset attachments, and emoji reactions. Even more frustrating, these features make the app being considered incomplete until delivered.
|
||||||
|
|
||||||
The same applies to backend systems. Features such as email sending, password resets, and image transformations are expected. Worse still, you'll receive feedback requesting different email verification methods—PIN codes instead of links, 4-digit codes versus 6-digit ones, or UUIDs like Axiom uses.
|
The same applies to backend systems. Features such as email sending, password resets, and image transformations are expected. Worse still, you'll receive feedback requesting different email verification methods—PIN codes instead of links, 4-digit codes versus 6-digit ones, or UUIDs like Axiom uses.
|
||||||
|
|
||||||
Since it's impossible to satisfy all requirements, why implement them at all? *"Because people expect it."* That's fair. But technically, email verification is not a core backend feature—it's business logic. Setting it up involves:
|
Since it's impossible to satisfy all requirements, why implement them at all? _"Because people expect it."_ That's fair. But technically, email verification is not a core backend feature—it's business logic. Setting it up involves:
|
||||||
|
|
||||||
1. Adding a `code` and `verified` field to the users' entity and generating a random code on creation.
|
1. Adding a `code` and `verified` field to the users' entity and generating a random code on creation.
|
||||||
2. Creating an endpoint to accept the code, retrieve the authenticated user, check the code, clear it, and mark the user as verified.
|
2. Creating an endpoint to accept the code, retrieve the authenticated user, check the code, clear it, and mark the user as verified.
|
||||||
|
|
||||||
@@ -62,10 +69,7 @@ Additional security measures, such as short-lived tokens, can be added, but the
|
|||||||
Instead of hardcoding such features, bknd offers a powerful event system that supports asynchronous (like webhooks) and synchronous execution, blocking further actions if needed. With integrated workflows (UI coming soon), you can listen to and react to system events, and even map them to endpoints. Since workflows, like everything else in bknd, are JSON-serializable, they're easy to export and import.
|
Instead of hardcoding such features, bknd offers a powerful event system that supports asynchronous (like webhooks) and synchronous execution, blocking further actions if needed. With integrated workflows (UI coming soon), you can listen to and react to system events, and even map them to endpoints. Since workflows, like everything else in bknd, are JSON-serializable, they're easy to export and import.
|
||||||
|
|
||||||
## Complex self-hosting
|
## Complex self-hosting
|
||||||
|
|
||||||
Finally, hosting. It's a business advantage if your system is highly sought after but difficult to self-host, forcing users to opt for your cloud service. The truth is, if it's hard for users, it's also hard for the vendor, which drives up costs.
|
Finally, hosting. It's a business advantage if your system is highly sought after but difficult to self-host, forcing users to opt for your cloud service. The truth is, if it's hard for users, it's also hard for the vendor, which drives up costs.
|
||||||
|
|
||||||
If you know how to deploy your Next.js, Remix, or Astro application, you can deploy bknd. It's straightforward to deploy using Cloudflare Workers/Pages or with just 28 lines of a Dockerfile. No PhD required.
|
If you know how to deploy your Next.js, Remix, or Astro application, you can deploy bknd. It's straightforward to deploy using Cloudflare Workers/Pages or with just 28 lines of a Dockerfile. No PhD required.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
---
|
||||||
|
title: Introduction
|
||||||
|
icon: Album
|
||||||
|
tags: ["documentation"]
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
import { examples } from "@/app/_components/StackBlitz";
|
||||||
|
|
||||||
|
Glad you're here! **bknd** is a lightweight, infrastructure agnostic and feature-rich backend that runs in any JavaScript environment.
|
||||||
|
|
||||||
|
- Instant backend with full REST API
|
||||||
|
- Built on Web Standards for maximum compatibility
|
||||||
|
- Multiple run modes (standalone, runtime, framework)
|
||||||
|
- Official API and React SDK with type-safety
|
||||||
|
- React elements for auto-configured authentication and media components
|
||||||
|
|
||||||
|
## Preview
|
||||||
|
|
||||||
|
Here is a preview of **bknd** in StackBlitz:
|
||||||
|
|
||||||
|
<StackBlitz {...examples.adminRich} />
|
||||||
|
|
||||||
|
<Accordions>
|
||||||
|
<Accordion title="What's going on?">
|
||||||
|
The example shown is starting a [node server](/integration/node) using an [in-memory database](/usage/database#sqlite-in-memory). To ensure there are a few entities defined, it is using an [initial structure](/usage/database#initial-structure) using the prototype methods. Furthermore it uses the [seed option](/usage/database#seeding-the-database) to seed some data in the structure created.
|
||||||
|
|
||||||
|
To ensure there are users defined on first boot, it hooks into the `App.Events.AppFirstBoot` event to create them (documentation pending).
|
||||||
|
|
||||||
|
</Accordion>
|
||||||
|
</Accordions>
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
Enter the following command to spin up an instance:
|
||||||
|
|
||||||
|
<Tabs groupId='package-manager' persist items={[ 'npm','bun' ]}>
|
||||||
|
|
||||||
|
```bash tab="npm"
|
||||||
|
npx bknd run
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="bun"
|
||||||
|
bunx bknd run
|
||||||
|
```
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
To learn more about the CLI, check out the [Using the CLI](/usage/cli) guide.
|
||||||
|
|
||||||
|
## Start with a Framework/Runtime
|
||||||
|
|
||||||
|
Start by using the integration guide for these popular frameworks/runtimes. There will be more in the future, so stay tuned!
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
<Card icon={<Icon icon="tabler:brand-nextjs" className="text-fd-primary !size-6" />} title="NextJS" href="/integration/nextjs" />
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon icon="simple-icons:reactrouter" className="text-fd-primary !size-6" />
|
||||||
|
}
|
||||||
|
title="React Router"
|
||||||
|
href="/integration/react-router"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:astro" className="text-fd-primary !size-6" />}
|
||||||
|
title="Astro"
|
||||||
|
href="/integration/astro"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="tabler:brand-nodejs" className="text-fd-primary !size-6" />}
|
||||||
|
title="NodeJS"
|
||||||
|
href="/integration/node"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="devicon-plain:cloudflareworkers"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Cloudflare"
|
||||||
|
href="/integration/cloudflare"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:bun" className="text-fd-primary !size-6" />}
|
||||||
|
title="Bun"
|
||||||
|
href="/integration/bun"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
||||||
|
title="AWS Lambda"
|
||||||
|
href="/integration/aws"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:vitest" className="text-fd-primary !size-6" />}
|
||||||
|
title="Vite"
|
||||||
|
href="/integration/vite"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="streamline-logos:docker-logo-solid"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Docker"
|
||||||
|
href="/integration/docker"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
|
Create a new issue to request a guide for your runtime or framework.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
|
|
||||||
|
## Use your favorite SQL Database
|
||||||
|
|
||||||
|
The following databases are currently supported. Request a new integration if your favorite is missing.
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
<Card icon={<Icon icon="simple-icons:sqlite" className="text-fd-primary !size-6" />} title="SQLite" href="/usage/database#database" />
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:turso" className="text-fd-primary !size-6" />}
|
||||||
|
title="Turso/LibSQL"
|
||||||
|
href="/usage/database#sqlite-using-libsql-on-turso"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon icon="lineicons:postgresql" className="text-fd-primary !size-6" />
|
||||||
|
}
|
||||||
|
title="PostgreSQL"
|
||||||
|
href="/usage/database#postgresql"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
icon="streamline-plump:database"
|
||||||
|
className="text-fd-primary !size-6"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Cloudflare D1"
|
||||||
|
href="/usage/database#cloudflare-d1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
|
Create a new issue to request a new database integration.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: 'Using the CLI'
|
title: "Using the CLI"
|
||||||
description: 'How to start a bknd instance using the CLI.'
|
description: "How to start a bknd instance using the CLI."
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
The bknd package includes a command-line interface (CLI) that allows you to run a bknd instance and perform various tasks.
|
The bknd package includes a command-line interface (CLI) that allows you to run a bknd instance and perform various tasks.
|
||||||
@@ -10,11 +11,12 @@ npx bknd
|
|||||||
```
|
```
|
||||||
|
|
||||||
Here is the output:
|
Here is the output:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ npx bknd
|
$ npx bknd
|
||||||
Usage: bknd [options] [command]
|
Usage: bknd [options] [command]
|
||||||
|
|
||||||
⚡ bknd cli v0.13.0
|
⚡ bknd cli v0.16.0
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-V, --version output the version number
|
-V, --version output the version number
|
||||||
@@ -33,6 +35,7 @@ Commands:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Starting an instance (`run`)
|
## Starting an instance (`run`)
|
||||||
|
|
||||||
To see all available `run` options, execute `npx bknd run --help`.
|
To see all available `run` options, execute `npx bknd run --help`.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -51,6 +54,7 @@ Options:
|
|||||||
```
|
```
|
||||||
|
|
||||||
To order in which the connection is determined is as follows:
|
To order in which the connection is determined is as follows:
|
||||||
|
|
||||||
1. `--db-url`
|
1. `--db-url`
|
||||||
2. `--config` or reading the filesystem looking for `bknd.config.[js|ts|mjs|cjs|json]`
|
2. `--config` or reading the filesystem looking for `bknd.config.[js|ts|mjs|cjs|json]`
|
||||||
3. `--memory`
|
3. `--memory`
|
||||||
@@ -58,6 +62,7 @@ To order in which the connection is determined is as follows:
|
|||||||
5. Fallback to file-based database `data.db`
|
5. Fallback to file-based database `data.db`
|
||||||
|
|
||||||
### File-based database
|
### File-based database
|
||||||
|
|
||||||
By default, a file-based database `data.db` is used when running without any arguments. You can specify a different file name or path using the `--db-url` option. The database file will be created in the current working directory if it does not exist.
|
By default, a file-based database `data.db` is used when running without any arguments. You can specify a different file name or path using the `--db-url` option. The database file will be created in the current working directory if it does not exist.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -65,6 +70,7 @@ npx bknd run --db-url file:data.db
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Using configuration file (`bknd.config.*`)
|
### Using configuration file (`bknd.config.*`)
|
||||||
|
|
||||||
You can create a configuration file on the working directory that automatically gets picked up: `bknd.config.[js|ts|mjs|cjs|json]`
|
You can create a configuration file on the working directory that automatically gets picked up: `bknd.config.[js|ts|mjs|cjs|json]`
|
||||||
|
|
||||||
Here is an example of a `bknd.config.ts` file:
|
Here is an example of a `bknd.config.ts` file:
|
||||||
@@ -73,20 +79,20 @@ Here is an example of a `bknd.config.ts` file:
|
|||||||
import type { BkndConfig } from "bknd/adapter";
|
import type { BkndConfig } from "bknd/adapter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// you can either specify the connection directly
|
// you can either specify the connection directly
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:data.db",
|
url: "file:data.db",
|
||||||
},
|
},
|
||||||
// or use the `app` function which passes the environment variables
|
// or use the `app` function which passes the environment variables
|
||||||
app: ({ env }) => ({
|
app: ({ env }) => ({
|
||||||
connection: {
|
connection: {
|
||||||
url: env.DB_URL,
|
url: env.DB_URL,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
} satisfies BkndConfig;
|
} satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
The `app` function is useful if you need a cross-platform way to access the environment variables. For example, on Cloudflare Workers, you can only access environment variables inside a request handler. If you're exclusively using a node-like environment, it's safe to access the environment variables directly from `process.env`.
|
|
||||||
|
|
||||||
|
The `app` function is useful if you need a cross-platform way to access the environment variables. For example, on Cloudflare Workers, you can only access environment variables inside a request handler. If you're exclusively using a node-like environment, it's safe to access the environment variables directly from `process.env`.
|
||||||
|
|
||||||
If you're using `npx bknd run`, make sure to create a file in a file format that `node` can load, otherwise you may run into an error that the file couldn't be found:
|
If you're using `npx bknd run`, make sure to create a file in a file format that `node` can load, otherwise you may run into an error that the file couldn't be found:
|
||||||
|
|
||||||
@@ -112,21 +118,27 @@ npx tsx node_modules/.bin/bknd run
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Turso/LibSQL database
|
### Turso/LibSQL database
|
||||||
|
|
||||||
To start an instance with a Turso/LibSQL database, run the following:
|
To start an instance with a Turso/LibSQL database, run the following:
|
||||||
|
|
||||||
```
|
```
|
||||||
npx bknd run --db-url libsql://your-db.turso.io --db-token <your-token>
|
npx bknd run --db-url libsql://your-db.turso.io --db-token <your-token>
|
||||||
```
|
```
|
||||||
|
|
||||||
The `--db-token` option is optional and only required if the database is protected.
|
The `--db-token` option is optional and only required if the database is protected.
|
||||||
|
|
||||||
|
|
||||||
### In-memory database
|
### In-memory database
|
||||||
|
|
||||||
To start an instance with an ephemeral in-memory database, run the following:
|
To start an instance with an ephemeral in-memory database, run the following:
|
||||||
|
|
||||||
```
|
```
|
||||||
npx bknd run --memory
|
npx bknd run --memory
|
||||||
```
|
```
|
||||||
|
|
||||||
Keep in mind that the database is not persisted and will be lost when the process is terminated.
|
Keep in mind that the database is not persisted and will be lost when the process is terminated.
|
||||||
|
|
||||||
## Generating types (`types`)
|
## Generating types (`types`)
|
||||||
|
|
||||||
To see all available `types` options, execute `npx bknd types --help`.
|
To see all available `types` options, execute `npx bknd types --help`.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -142,6 +154,7 @@ Options:
|
|||||||
```
|
```
|
||||||
|
|
||||||
To generate types for the database, run the following:
|
To generate types for the database, run the following:
|
||||||
|
|
||||||
```
|
```
|
||||||
npx bknd types
|
npx bknd types
|
||||||
```
|
```
|
||||||
@@ -149,7 +162,7 @@ npx bknd types
|
|||||||
This will generate types for your database schema in `bknd-types.d.ts`. The generated file could look like this:
|
This will generate types for your database schema in `bknd-types.d.ts`. The generated file could look like this:
|
||||||
|
|
||||||
```typescript bknd-types.d.ts
|
```typescript bknd-types.d.ts
|
||||||
import type { DB } from "bknd/core";
|
import type { DB } from "bknd";
|
||||||
import type { Insertable, Selectable, Updateable, Generated } from "kysely";
|
import type { Insertable, Selectable, Updateable, Generated } from "kysely";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -168,7 +181,7 @@ interface Database {
|
|||||||
todos: Todos;
|
todos: Todos;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "bknd/core" {
|
declare module "bknd" {
|
||||||
interface DB extends Database {}
|
interface DB extends Database {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -177,18 +190,17 @@ Make sure to add the generated file in your `tsconfig.json` file:
|
|||||||
|
|
||||||
```json tsconfig.json
|
```json tsconfig.json
|
||||||
{
|
{
|
||||||
"include": [
|
"include": ["bknd-types.d.ts"]
|
||||||
"bknd-types.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then use the types by importing them from `bknd/core`:
|
You can then use the types by importing them from `bknd`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { DB } from "bknd/core";
|
import type { DB } from "bknd";
|
||||||
|
|
||||||
type Todo = DB["todos"];
|
type Todo = DB["todos"];
|
||||||
```
|
```
|
||||||
|
|
||||||
All bknd methods that involve your database schema will be automatically typed.
|
All bknd methods that involve your database schema will be automatically typed.
|
||||||
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
---
|
---
|
||||||
title: 'Database'
|
title: "Database"
|
||||||
description: 'Choosing the right database configuration'
|
description: "Choosing the right database configuration"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
In order to use **bknd**, you need to prepare access information to your database and potentially install additional dependencies. Connections to the database are managed using Kysely. Therefore, all [its dialects](https://kysely.dev/docs/dialects) are theoretically supported.
|
In order to use **bknd**, you need to prepare access information to your database and potentially install additional dependencies. Connections to the database are managed using Kysely. Therefore, all [its dialects](https://kysely.dev/docs/dialects) are theoretically supported.
|
||||||
|
|
||||||
Currently supported and tested databases are:
|
Currently supported and tested databases are:
|
||||||
|
|
||||||
- SQLite (embedded): Node.js SQLite, Bun SQLite, LibSQL, SQLocal
|
- SQLite (embedded): Node.js SQLite, Bun SQLite, LibSQL, SQLocal
|
||||||
- SQLite (remote): Turso, Cloudflare D1
|
- SQLite (remote): Turso, Cloudflare D1
|
||||||
- Postgres: Vanilla Postgres, Supabase, Neon, Xata
|
- Postgres: Vanilla Postgres, Supabase, Neon, Xata
|
||||||
@@ -13,73 +15,80 @@ Currently supported and tested databases are:
|
|||||||
By default, bknd will try to use a SQLite database in-memory. Depending on your runtime, a different SQLite implementation will be used.
|
By default, bknd will try to use a SQLite database in-memory. Depending on your runtime, a different SQLite implementation will be used.
|
||||||
|
|
||||||
## Defining the connection
|
## Defining the connection
|
||||||
|
|
||||||
There are mainly 3 ways to define the connection to your database, when
|
There are mainly 3 ways to define the connection to your database, when
|
||||||
|
|
||||||
1. creating an app using `App.create()` or `createApp()`
|
1. creating an app using `App.create()` or `createApp()`
|
||||||
2. creating an app using a [Framework or Runtime adapter](/integration/introduction)
|
2. creating an app using a [Framework or Runtime adapter](/integration/introduction)
|
||||||
3. starting a quick instance using the [CLI](/usage/cli#using-configuration-file-bknd-config)
|
3. starting a quick instance using the [CLI](/usage/cli#using-configuration-file-bknd-config)
|
||||||
|
|
||||||
When creating an app using `App.create()` or `createApp()`, you can pass a connection object in the configuration object.
|
When creating an app using `App.create()` or `createApp()`, you can pass a connection object in the configuration object.
|
||||||
|
|
||||||
```typescript app.ts
|
```typescript title="app.ts"
|
||||||
import { createApp } from "bknd";
|
import { createApp } from "bknd";
|
||||||
import { sqlite } from "bknd/adapter/sqlite";
|
import { sqlite } from "bknd/adapter/sqlite";
|
||||||
|
|
||||||
// a connection is required when creating an app like this
|
// a connection is required when creating an app like this
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
connection: sqlite({ url: ":memory:" }),
|
connection: sqlite({ url: ":memory:" }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
When using an adapter, or using the CLI, bknd will automatically try to use a SQLite implementation depending on the runtime:
|
When using an adapter, or using the CLI, bknd will automatically try to use a SQLite implementation depending on the runtime:
|
||||||
|
|
||||||
|
```javascript title="app.js"
|
||||||
```javascript app.js
|
|
||||||
import { serve } from "bknd/adapter/node";
|
import { serve } from "bknd/adapter/node";
|
||||||
|
|
||||||
serve({
|
serve({
|
||||||
// connection is optional, but recommended
|
// connection is optional, but recommended
|
||||||
connection: { url: "file:data.db" },
|
connection: { url: "file:data.db" },
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also pass a connection instance to the `connection` property to explictly use a specific connection.
|
You can also pass a connection instance to the `connection` property to explictly use a specific connection.
|
||||||
|
|
||||||
```javascript app.js
|
```javascript title="app.js"
|
||||||
import { serve } from "bknd/adapter/node";
|
import { serve } from "bknd/adapter/node";
|
||||||
import { sqlite } from "bknd/adapter/sqlite";
|
import { sqlite } from "bknd/adapter/sqlite";
|
||||||
|
|
||||||
serve({
|
serve({
|
||||||
connection: sqlite({ url: "file:data.db" }),
|
connection: sqlite({ url: "file:data.db" }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
If you're using [`bknd.config.*`](/extending/config), you can specify the connection on the exported object.
|
If you're using [`bknd.config.*`](/extending/config), you can specify the connection on the exported object.
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { BkndConfig } from "bknd";
|
import type { BkndConfig } from "bknd";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: { url: "file:data.db" },
|
connection: { url: "file:data.db" },
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
Throughout the documentation, it is assumed you use `bknd.config.ts` to define your connection.
|
Throughout the documentation, it is assumed you use `bknd.config.ts` to define your connection.
|
||||||
|
|
||||||
## SQLite
|
## SQLite
|
||||||
|
|
||||||
### Using config object
|
### Using config object
|
||||||
|
|
||||||
The `sqlite` adapter is automatically resolved based on the runtime.
|
<Callout type="warn">
|
||||||
|
When run with Node.js, a version of 22 (LTS) or higher is required. Please
|
||||||
|
verify your version by running `node -v`, and
|
||||||
|
[upgrade](https://nodejs.org/en/download/) if necessary.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
| Runtime | Adapter | In-Memory | File | Remote |
|
The `sqlite` adapter is automatically resolved based on the runtime.
|
||||||
| ------- | ------- | --------- | ---- | ------ |
|
|
||||||
| Node.js | `node:sqlite` | ✅ | ✅ | ❌ |
|
| Runtime | Adapter | In-Memory | File | Remote |
|
||||||
| Bun | `bun:sqlite` | ✅ | ✅ | ❌ |
|
| ------------------------------ | ------------- | --------- | ---- | ------ |
|
||||||
| Cloudflare Worker/Browser/Edge | `libsql` | 🟠 | 🟠 | ✅ |
|
| Node.js | `node:sqlite` | ✅ | ✅ | ❌ |
|
||||||
|
| Bun | `bun:sqlite` | ✅ | ✅ | ❌ |
|
||||||
|
| Cloudflare Worker/Browser/Edge | `libsql` | 🟠 | 🟠 | ✅ |
|
||||||
|
|
||||||
The bundled version of the `libsql` connection only works with remote databases. However, you can pass in a `Client` from `@libsql/client`, see [LibSQL](#libsql) for more details.
|
The bundled version of the `libsql` connection only works with remote databases. However, you can pass in a `Client` from `@libsql/client`, see [LibSQL](#libsql) for more details.
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { BkndConfig } from "bknd";
|
import type { BkndConfig } from "bknd";
|
||||||
|
|
||||||
// no connection is required, bknd will use a SQLite database in-memory
|
// no connection is required, bknd will use a SQLite database in-memory
|
||||||
@@ -88,51 +97,49 @@ export default {} as const satisfies BkndConfig;
|
|||||||
|
|
||||||
// or explicitly in-memory
|
// or explicitly in-memory
|
||||||
export default {
|
export default {
|
||||||
connection: { url: ":memory:" },
|
connection: { url: ":memory:" },
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies BkndConfig;
|
||||||
|
|
||||||
// or explicitly as a file
|
// or explicitly as a file
|
||||||
export default {
|
export default {
|
||||||
connection: { url: "file:<path/to/your/database.db>" },
|
connection: { url: "file:<path/to/your/database.db>" },
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### LibSQL
|
### LibSQL
|
||||||
|
|
||||||
Turso offers a SQLite-fork called LibSQL that runs a server around your SQLite database. The edge-version of the adapter is included in the bundle (remote only):
|
Turso offers a SQLite-fork called LibSQL that runs a server around your SQLite database. The edge-version of the adapter is included in the bundle (remote only):
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { BkndConfig } from "bknd";
|
import { libsql, type BkndConfig } from "bknd";
|
||||||
import { libsql } from "bknd/data";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: libsql({
|
connection: libsql({
|
||||||
url: "libsql://<database>.turso.io",
|
url: "libsql://<database>.turso.io",
|
||||||
authToken: "<auth-token>",
|
authToken: "<auth-token>",
|
||||||
}),
|
}),
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
If you wish to use LibSQL as file, in-memory or make use of [Embedded Replicas](https://docs.turso.tech/features/embedded-replicas/introduction), you have to pass in the `Client` from `@libsql/client`:
|
If you wish to use LibSQL as file, in-memory or make use of [Embedded Replicas](https://docs.turso.tech/features/embedded-replicas/introduction), you have to pass in the `Client` from `@libsql/client`:
|
||||||
|
|
||||||
```typescript bknd.config.ts
|
```typescript title="bknd.config.ts"
|
||||||
import type { BkndConfig } from "bknd";
|
import { libsql, type BkndConfig } from "bknd";
|
||||||
import { libsql } from "bknd/data";
|
|
||||||
import { createClient } from "@libsql/client";
|
import { createClient } from "@libsql/client";
|
||||||
|
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
url: "libsql://<database>.turso.io",
|
url: "libsql://<database>.turso.io",
|
||||||
authToken: "<auth-token>",
|
authToken: "<auth-token>",
|
||||||
})
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
connection: libsql(client),
|
connection: libsql(client),
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies BkndConfig;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Cloudflare D1
|
### Cloudflare D1
|
||||||
Using the [Cloudflare Adapter](/integration/cloudflare), you can choose to use a D1 database binding. To do so, you only need to add a D1 database to your `wrangler.toml` and it'll pick up automatically.
|
|
||||||
|
Using the [Cloudflare Adapter](/integration/cloudflare), you can choose to use a D1 database binding. To do so, you only need to add a D1 database to your `wrangler.toml` and it'll pick up automatically.
|
||||||
|
|
||||||
To manually specify which D1 database to take, you can specify it explicitly:
|
To manually specify which D1 database to take, you can specify it explicitly:
|
||||||
|
|
||||||
@@ -140,12 +147,12 @@ To manually specify which D1 database to take, you can specify it explicitly:
|
|||||||
import { serve, d1 } from "bknd/adapter/cloudflare";
|
import { serve, d1 } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
export default serve<Env>({
|
export default serve<Env>({
|
||||||
app: ({ env }) => d1({ binding: env.D1_BINDING })
|
app: ({ env }) => d1({ binding: env.D1_BINDING }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### SQLocal
|
### SQLocal
|
||||||
|
|
||||||
To use bknd with `sqlocal` for a offline expierence, you need to install the `@bknd/sqlocal` package. You can do so by running the following command:
|
To use bknd with `sqlocal` for a offline expierence, you need to install the `@bknd/sqlocal` package. You can do so by running the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -159,14 +166,15 @@ import { createApp } from "bknd";
|
|||||||
import { SQLocalConnection } from "@bknd/sqlocal";
|
import { SQLocalConnection } from "@bknd/sqlocal";
|
||||||
|
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
connection: new SQLocalConnection({
|
connection: new SQLocalConnection({
|
||||||
databasePath: ":localStorage:",
|
databasePath: ":localStorage:",
|
||||||
verbose: true,
|
verbose: true,
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## PostgreSQL
|
## PostgreSQL
|
||||||
|
|
||||||
To use bknd with Postgres, you need to install the `@bknd/postgres` package. You can do so by running the following command:
|
To use bknd with Postgres, you need to install the `@bknd/postgres` package. You can do so by running the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -177,7 +185,7 @@ You can connect to your Postgres database using `pg` or `postgres` dialects. Add
|
|||||||
|
|
||||||
### Using `pg`
|
### Using `pg`
|
||||||
|
|
||||||
To establish a connection to your database, you can use any connection options available on the [`pg`](https://node-postgres.com/apis/client) package.
|
To establish a connection to your database, you can use any connection options available on the [`pg`](https://node-postgres.com/apis/client) package.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { serve } from "bknd/adapter/node";
|
import { serve } from "bknd/adapter/node";
|
||||||
@@ -185,10 +193,9 @@ import { pg } from "@bknd/postgres";
|
|||||||
|
|
||||||
/** @type {import("bknd/adapter/node").NodeBkndConfig} */
|
/** @type {import("bknd/adapter/node").NodeBkndConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
connection: pg({
|
connection: pg({
|
||||||
connectionString:
|
connectionString: "postgresql://user:password@localhost:5432/database",
|
||||||
"postgresql://user:password@localhost:5432/database",
|
}),
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
serve(config);
|
serve(config);
|
||||||
@@ -196,14 +203,14 @@ serve(config);
|
|||||||
|
|
||||||
### Using `postgres`
|
### Using `postgres`
|
||||||
|
|
||||||
To establish a connection to your database, you can use any connection options available on the [`postgres`](https://github.com/porsager/postgres) package.
|
To establish a connection to your database, you can use any connection options available on the [`postgres`](https://github.com/porsager/postgres) package.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { serve } from "bknd/adapter/node";
|
import { serve } from "bknd/adapter/node";
|
||||||
import { postgresJs } from "@bknd/postgres";
|
import { postgresJs } from "@bknd/postgres";
|
||||||
|
|
||||||
serve({
|
serve({
|
||||||
connection: postgresJs("postgresql://user:password@localhost:5432/database"),
|
connection: postgresJs("postgresql://user:password@localhost:5432/database"),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -220,9 +227,9 @@ import { NeonDialect } from "kysely-neon";
|
|||||||
const neon = createCustomPostgresConnection(NeonDialect);
|
const neon = createCustomPostgresConnection(NeonDialect);
|
||||||
|
|
||||||
serve({
|
serve({
|
||||||
connection: neon({
|
connection: neon({
|
||||||
connectionString: process.env.NEON,
|
connectionString: process.env.NEON,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -235,73 +242,78 @@ import { buildClient } from "@xata.io/client";
|
|||||||
|
|
||||||
const client = buildClient();
|
const client = buildClient();
|
||||||
const xata = new client({
|
const xata = new client({
|
||||||
databaseURL: process.env.XATA_URL,
|
databaseURL: process.env.XATA_URL,
|
||||||
apiKey: process.env.XATA_API_KEY,
|
apiKey: process.env.XATA_API_KEY,
|
||||||
branch: process.env.XATA_BRANCH,
|
branch: process.env.XATA_BRANCH,
|
||||||
});
|
});
|
||||||
|
|
||||||
const xataConnection = createCustomPostgresConnection(XataDialect, {
|
const xataConnection = createCustomPostgresConnection(XataDialect, {
|
||||||
supports: {
|
supports: {
|
||||||
batching: false,
|
batching: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
serve({
|
serve({
|
||||||
connection: xataConnection({ xata }),
|
connection: xataConnection({ xata }),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Custom Connection
|
## Custom Connection
|
||||||
|
|
||||||
Creating a custom connection is as easy as extending the `Connection` class and passing constructing a Kysely instance.
|
Creating a custom connection is as easy as extending the `Connection` class and passing constructing a Kysely instance.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { createApp } from "bknd";
|
import { createApp, Connection } from "bknd";
|
||||||
import { Connection } from "bknd/data";
|
|
||||||
import { Kysely } from "kysely";
|
import { Kysely } from "kysely";
|
||||||
|
|
||||||
class CustomConnection extends Connection {
|
class CustomConnection extends Connection {
|
||||||
constructor() {
|
constructor() {
|
||||||
const kysely = new Kysely(/* ... */);
|
const kysely = new Kysely(/* ... */);
|
||||||
super(kysely);
|
super(kysely);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const connection = new CustomConnection();
|
const connection = new CustomConnection();
|
||||||
|
|
||||||
// e.g. and then, create an instance
|
// e.g. and then, create an instance
|
||||||
const app = createApp({ connection })
|
const app = createApp({ connection });
|
||||||
```
|
```
|
||||||
|
|
||||||
## Initial Structure
|
## Initial Structure
|
||||||
|
|
||||||
To provide an initial database structure, you can pass `initialConfig` to the creation of an app. This will only be used if there isn't an existing configuration found in the database given. Here is a quick example:
|
To provide an initial database structure, you can pass `initialConfig` to the creation of an app. This will only be used if there isn't an existing configuration found in the database given. Here is a quick example:
|
||||||
|
|
||||||
<Note>
|
<Callout type="info">
|
||||||
The initial structure is only respected if the database is empty! If you made updates, ensure to delete the database first, or perform updates through the Admin UI.
|
The initial structure is only respected if the database is empty! If you made
|
||||||
</Note>
|
updates, ensure to delete the database first, or perform updates through the
|
||||||
|
Admin UI.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createApp } from "bknd";
|
import { createApp, em, entity, text, number } from "bknd";
|
||||||
import { em, entity, text, number } from "bknd/data";
|
|
||||||
|
|
||||||
const schema = em({
|
const schema = em(
|
||||||
posts: entity("posts", {
|
{
|
||||||
|
posts: entity("posts", {
|
||||||
// "id" is automatically added
|
// "id" is automatically added
|
||||||
title: text().required(),
|
title: text().required(),
|
||||||
slug: text().required(),
|
slug: text().required(),
|
||||||
content: text(),
|
content: text(),
|
||||||
views: number()
|
views: number(),
|
||||||
}),
|
}),
|
||||||
comments: entity("comments", {
|
comments: entity("comments", {
|
||||||
content: text()
|
content: text(),
|
||||||
})
|
}),
|
||||||
|
|
||||||
// relations and indices are defined separately.
|
// relations and indices are defined separately.
|
||||||
// the first argument are the helper functions, the second the entities.
|
// the first argument are the helper functions, the second the entities.
|
||||||
}, ({ relation, index }, { posts, comments }) => {
|
},
|
||||||
relation(comments).manyToOne(posts);
|
({ relation, index }, { posts, comments }) => {
|
||||||
// relation as well as index can be chained!
|
relation(comments).manyToOne(posts);
|
||||||
index(posts).on(["title"]).on(["slug"], true);
|
// relation as well as index can be chained!
|
||||||
});
|
index(posts).on(["title"]).on(["slug"], true);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// to get a type from your schema, use:
|
// to get a type from your schema, use:
|
||||||
type Database = (typeof schema)["DB"];
|
type Database = (typeof schema)["DB"];
|
||||||
@@ -320,66 +332,81 @@ type Database = (typeof schema)["DB"];
|
|||||||
|
|
||||||
// pass the schema to the app
|
// pass the schema to the app
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
connection: { /* ... */ },
|
connection: {
|
||||||
initialConfig: {
|
/* ... */
|
||||||
data: schema.toJSON()
|
},
|
||||||
}
|
initialConfig: {
|
||||||
|
data: schema.toJSON(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that we didn't add relational fields directly to the entity, but instead defined them afterwards. That is because the relations are managed outside the entity scope to have an unified expierence for all kinds of relations (e.g. many-to-many).
|
Note that we didn't add relational fields directly to the entity, but instead defined them afterwards. That is because the relations are managed outside the entity scope to have an unified expierence for all kinds of relations (e.g. many-to-many).
|
||||||
|
|
||||||
<Note>
|
<Callout type="info">
|
||||||
Defined relations are currently not part of the produced types for the structure. We're working on that, but in the meantime, you can define them manually.
|
Defined relations are currently not part of the produced types for the
|
||||||
</Note>
|
structure. We're working on that, but in the meantime, you can define them
|
||||||
|
manually.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
### Type completion
|
### Type completion
|
||||||
|
|
||||||
To get type completion, there are two options:
|
To get type completion, there are two options:
|
||||||
|
|
||||||
1. Use the CLI to [generate the types](/usage/cli#generating-types-types)
|
1. Use the CLI to [generate the types](/usage/cli#generating-types-types)
|
||||||
2. If you have an initial structure created with the prototype functions, you can extend the `DB` interface with your own schema.
|
2. If you have an initial structure created with the prototype functions, you can extend the `DB` interface with your own schema.
|
||||||
|
|
||||||
All entity related functions use the types defined in `DB` from `bknd/core`. To get type completion, you can extend that interface with your own schema:
|
All entity related functions use the types defined in `DB` from `bknd`. To get type completion, you can extend that interface with your own schema:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { em } from "bknd/data";
|
import { em } from "bknd";
|
||||||
import { Api } from "bknd/client";
|
import { Api } from "bknd/client";
|
||||||
|
|
||||||
const schema = em({ /* ... */ });
|
const schema = em({
|
||||||
|
/* ... */
|
||||||
|
});
|
||||||
|
|
||||||
type Database = (typeof schema)["DB"];
|
type Database = (typeof schema)["DB"];
|
||||||
declare module "bknd/core" {
|
declare module "bknd" {
|
||||||
interface DB extends Database {}
|
interface DB extends Database {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = new Api({ /* ... */ });
|
const api = new Api({
|
||||||
const { data: posts } = await api.data.readMany("posts", {})
|
/* ... */
|
||||||
|
});
|
||||||
|
const { data: posts } = await api.data.readMany("posts", {});
|
||||||
// `posts` is now typed as Database["posts"]
|
// `posts` is now typed as Database["posts"]
|
||||||
```
|
```
|
||||||
|
|
||||||
The type completion is available for the API as well as all provided [React hooks](/usage/react).
|
The type completion is available for the API as well as all provided [React hooks](/usage/react).
|
||||||
|
|
||||||
### Seeding the database
|
### Seeding the database
|
||||||
|
|
||||||
To seed your database with initial data, you can pass a `seed` function to the configuration. It
|
To seed your database with initial data, you can pass a `seed` function to the configuration. It
|
||||||
provides the `ModuleBuildContext` as the first argument.
|
provides the `ModuleBuildContext` as the first argument.
|
||||||
|
|
||||||
<Note>
|
<Callout type="info">
|
||||||
Note that the seed function will only be executed on app's first boot. If a configuration
|
Note that the seed function will only be executed on app's first boot. If a
|
||||||
already exists in the database, it will not be executed.
|
configuration already exists in the database, it will not be executed.
|
||||||
</Note>
|
</Callout>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createApp, type ModuleBuildContext } from "bknd";
|
import { createApp, type ModuleBuildContext } from "bknd";
|
||||||
|
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
connection: { /* ... */ },
|
connection: {
|
||||||
initialConfig: { /* ... */ },
|
/* ... */
|
||||||
options: {
|
},
|
||||||
seed: async (ctx: ModuleBuildContext) => {
|
initialConfig: {
|
||||||
await ctx.em.mutator("posts").insertMany([
|
/* ... */
|
||||||
{ title: "First post", slug: "first-post", content: "..." },
|
},
|
||||||
{ title: "Second post", slug: "second-post" }
|
options: {
|
||||||
]);
|
seed: async (ctx: ModuleBuildContext) => {
|
||||||
}
|
await ctx.em.mutator("posts").insertMany([
|
||||||
}
|
{ title: "First post", slug: "first-post", content: "..." },
|
||||||
|
{ title: "Second post", slug: "second-post" },
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -1,24 +1,28 @@
|
|||||||
---
|
---
|
||||||
title: "React Elements"
|
title: "React Elements"
|
||||||
description: "Speed up your frontend development"
|
description: "Speed up your frontend development"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Not only creating and maintaing a backend is time-consuming, but also integrating it into your frontend can be a hassle. With `bknd/elements`, you can easily add media uploads and authentication forms to your app without having to figure out API details.
|
Not only creating and maintaing a backend is time-consuming, but also integrating it into your frontend can be a hassle. With `bknd/elements`, you can easily add media uploads and authentication forms to your app without having to figure out API details.
|
||||||
|
|
||||||
<Note>
|
<Callout type="info">
|
||||||
In order to use these exported elements, make sure to wrap your app inside `ClientProvider`. See the [React Setup](/usage/react#setup) for more information.
|
In order to use these exported elements, make sure to wrap your app inside
|
||||||
</Note>
|
`ClientProvider`. See the [React Setup](/usage/react#setup) for more
|
||||||
|
information.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
# Media
|
## Media
|
||||||
|
|
||||||
|
### Media.Dropzone
|
||||||
|
|
||||||
## Media.Dropzone
|
|
||||||
The `Media.Dropzone` element allows retrieving from and uploading media items to your bknd instance. Without any properties specified, it will behave similar to your media library inside the bknd Admin UI. Here is how to get the last 10 items:
|
The `Media.Dropzone` element allows retrieving from and uploading media items to your bknd instance. Without any properties specified, it will behave similar to your media library inside the bknd Admin UI. Here is how to get the last 10 items:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Media } from "bknd/elements"
|
import { Media } from "bknd/elements";
|
||||||
|
|
||||||
export default function MediaGallery() {
|
export default function MediaGallery() {
|
||||||
return <Media.Dropzone query={{ limit: 10, sort: "-id" }} />
|
return <Media.Dropzone query={{ limit: 10, sort: "-id" }} />;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -28,15 +32,18 @@ Since you can also upload media to a specific entity, you can also point that `D
|
|||||||
import { Media } from "bknd/elements";
|
import { Media } from "bknd/elements";
|
||||||
|
|
||||||
export default function UserAvatar() {
|
export default function UserAvatar() {
|
||||||
return <Media.Dropzone
|
return (
|
||||||
|
<Media.Dropzone
|
||||||
entity={{ name: "users", id: 1, field: "avatar" }}
|
entity={{ name: "users", id: 1, field: "avatar" }}
|
||||||
maxItems={1}
|
maxItems={1}
|
||||||
overwrite
|
overwrite
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Props
|
#### Props
|
||||||
|
|
||||||
- `initialItems?: xMediaFieldSchema[]`: Initial items to display, must be an array of media objects.
|
- `initialItems?: xMediaFieldSchema[]`: Initial items to display, must be an array of media objects.
|
||||||
- `entity?: { name: string; id: number; field: string }`: If given, the initial media items fetched will be from this entity.
|
- `entity?: { name: string; id: number; field: string }`: If given, the initial media items fetched will be from this entity.
|
||||||
- `query?: RepoQueryIn`: Query to filter the media items.
|
- `query?: RepoQueryIn`: Query to filter the media items.
|
||||||
@@ -48,88 +55,97 @@ export default function UserAvatar() {
|
|||||||
- `onUploaded?: (file: FileState) => void`: Callback when a file is uploaded.
|
- `onUploaded?: (file: FileState) => void`: Callback when a file is uploaded.
|
||||||
- `placeholder?: { show?: boolean; text?: string }`: Placeholder text to show when no media items are present.
|
- `placeholder?: { show?: boolean; text?: string }`: Placeholder text to show when no media items are present.
|
||||||
|
|
||||||
### Customize Rendering
|
#### Customize Rendering
|
||||||
|
|
||||||
You can also customize the rendering of the media items and its uploading by passing a react element as a child. Here is an example of a custom `Media.Dropzone` that renders an user avatar (styled using tailwind):
|
You can also customize the rendering of the media items and its uploading by passing a react element as a child. Here is an example of a custom `Media.Dropzone` that renders an user avatar (styled using tailwind):
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Media, useMediaDropzone, useMediaDropzoneState } from "bknd/elements";
|
import { Media, useMediaDropzone, useMediaDropzoneState } from "bknd/elements";
|
||||||
|
|
||||||
export default function CustomUserAvatar() {
|
export default function CustomUserAvatar() {
|
||||||
return <Media.Dropzone
|
return (
|
||||||
|
<Media.Dropzone
|
||||||
entity={{ name: "users", id: 1, field: "avatar" }}
|
entity={{ name: "users", id: 1, field: "avatar" }}
|
||||||
maxItems={1}
|
maxItems={1}
|
||||||
overwrite
|
overwrite
|
||||||
>
|
>
|
||||||
<CustomUserAvatar />
|
<CustomUserAvatar />
|
||||||
</Media.Dropzone>
|
</Media.Dropzone>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CustomUserAvatar() {
|
function CustomUserAvatar() {
|
||||||
const {
|
const {
|
||||||
wrapperRef,
|
wrapperRef,
|
||||||
inputProps,
|
inputProps,
|
||||||
showPlaceholder,
|
showPlaceholder,
|
||||||
actions: { openFileInput }
|
actions: { openFileInput },
|
||||||
} = useMediaDropzone();
|
} = useMediaDropzone();
|
||||||
const { files: [ file ], isOver, isOverAccepted } = useMediaDropzoneState();
|
const {
|
||||||
|
files: [file],
|
||||||
|
isOver,
|
||||||
|
isOverAccepted,
|
||||||
|
} = useMediaDropzoneState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
className="size-32 rounded-full border border-gray-200 flex justify-center items-center leading-none overflow-hidden"
|
className="size-32 rounded-full border border-gray-200 flex justify-center items-center leading-none overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="hidden">
|
<div className="hidden">
|
||||||
<input {...inputProps} />
|
<input {...inputProps} />
|
||||||
</div>
|
|
||||||
{showPlaceholder && <>{isOver && isOverAccepted ? "let it drop" : "drop here"}</>}
|
|
||||||
{file && (
|
|
||||||
<Media.Preview
|
|
||||||
file={file}
|
|
||||||
className="object-cover w-full h-full"
|
|
||||||
onClick={openFileInput}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
{showPlaceholder && (
|
||||||
|
<>{isOver && isOverAccepted ? "let it drop" : "drop here"}</>
|
||||||
|
)}
|
||||||
|
{file && (
|
||||||
|
<Media.Preview
|
||||||
|
file={file}
|
||||||
|
className="object-cover w-full h-full"
|
||||||
|
onClick={openFileInput}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Auth
|
## Auth
|
||||||
|
|
||||||
Adding authentication to your app with bknd is as easy as adding a `<form method="POST" />` with an action pointing to the action (`login` or `register`) to the strategy you want to use, e.g. for the password strategy, use `/api/auth/password/login`. But to make it even easier, you can use the `Auth.*` elements.
|
Adding authentication to your app with bknd is as easy as adding a `<form method="POST" />` with an action pointing to the action (`login` or `register`) to the strategy you want to use, e.g. for the password strategy, use `/api/auth/password/login`. But to make it even easier, you can use the `Auth.*` elements.
|
||||||
|
|
||||||
## `Auth.Screen`
|
### `Auth.Screen`
|
||||||
|
|
||||||
The `Auth.Screen` element is a wrapper around the `Auth.Form` element that provides a full page screen. The current layout is admittedly very basic, but there will be more customization options in the future.
|
The `Auth.Screen` element is a wrapper around the `Auth.Form` element that provides a full page screen. The current layout is admittedly very basic, but there will be more customization options in the future.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Auth } from "bknd/elements"
|
import { Auth } from "bknd/elements";
|
||||||
|
|
||||||
export default function LoginScreen() {
|
export default function LoginScreen() {
|
||||||
return <Auth.Screen action="login" />
|
return <Auth.Screen action="login" />;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Props
|
#### Props
|
||||||
Note that this component doesn't require any strategy-specific information, as it gathers it itself.
|
|
||||||
|
Note that this component doesn't require any strategy-specific information, as it gathers it itself.
|
||||||
|
|
||||||
- `action: "login" | "register"`: The action to perform.
|
- `action: "login" | "register"`: The action to perform.
|
||||||
- `method?: "POST" | "GET"`: The method to use for the form.
|
- `method?: "POST" | "GET"`: The method to use for the form.
|
||||||
|
|
||||||
|
### `Auth.Form`
|
||||||
|
|
||||||
|
|
||||||
## `Auth.Form`
|
|
||||||
If you only wish to render the form itself without the screen, you can use the `Auth.Form` element. Unlike the `Auth.Screen`, this element requires the `strategy` prop to be set to the strategy you want to use. You can either specify it manually, use use the exported hook `useAuthStrategies()` for fetch them from your bknd instance.
|
If you only wish to render the form itself without the screen, you can use the `Auth.Form` element. Unlike the `Auth.Screen`, this element requires the `strategy` prop to be set to the strategy you want to use. You can either specify it manually, use use the exported hook `useAuthStrategies()` for fetch them from your bknd instance.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Auth, useAuthStrategies } from "bknd/elements"
|
import { Auth, useAuthStrategies } from "bknd/elements";
|
||||||
|
|
||||||
export default function LoginForm() {
|
export default function LoginForm() {
|
||||||
const { strategies, basepath, loading } = useAuthStrategies();
|
const { strategies, basepath, loading } = useAuthStrategies();
|
||||||
if (loading) return null;
|
if (loading) return null;
|
||||||
|
|
||||||
return <Auth.Form
|
return (
|
||||||
action="login"
|
<Auth.Form action="login" strategies={strategies} basepath={basepath} />
|
||||||
strategies={strategies}
|
);
|
||||||
basepath={basepath}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
+58
-39
@@ -1,20 +1,23 @@
|
|||||||
---
|
---
|
||||||
title: 'Introduction'
|
title: "Introduction"
|
||||||
description: 'Setting up bknd'
|
description: "Setting up bknd"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
There are several methods to get **bknd** up and running. You can choose between these options:
|
There are several methods to get **bknd** up and running. You can choose between these options:
|
||||||
|
|
||||||
1. [Run it using the CLI](/usage/cli): That's the easiest and fastest way to get started.
|
1. [Run it using the CLI](/usage/cli): That's the easiest and fastest way to get started.
|
||||||
2. Use a runtime like [Node](/integration/node), [Bun](/integration/bun) or
|
2. Use a runtime like [Node](/integration/node), [Bun](/integration/bun) or
|
||||||
[Cloudflare](/integration/cloudflare) (workerd). This will run the API and UI in the runtime's
|
[Cloudflare](/integration/cloudflare) (workerd). This will run the API and UI in the runtime's
|
||||||
native server and serves the UI assets statically from `node_modules`.
|
native server and serves the UI assets statically from `node_modules`.
|
||||||
3. Run it inside your React framework of choice like [Next.js](/integration/nextjs),
|
3. Run it inside your React framework of choice like [Next.js](/integration/nextjs),
|
||||||
[Astro](/integration/astro) or [Remix](/integration/remix).
|
[Astro](/integration/astro) or [Remix](/integration/remix).
|
||||||
|
|
||||||
There is also a fourth option, which is running it inside a
|
There is also a fourth option, which is running it inside a
|
||||||
[Docker container](/integration/docker). This is essentially a wrapper around the CLI.
|
[Docker container](/integration/docker). This is essentially a wrapper around the CLI.
|
||||||
|
|
||||||
## Basic setup
|
## Basic setup
|
||||||
|
|
||||||
Regardless of the method you choose, at the end all adapters come down to the actual
|
Regardless of the method you choose, at the end all adapters come down to the actual
|
||||||
instantiation of the `App`, which in raw looks like this:
|
instantiation of the `App`, which in raw looks like this:
|
||||||
|
|
||||||
@@ -22,7 +25,9 @@ instantiation of the `App`, which in raw looks like this:
|
|||||||
import { createApp, type CreateAppConfig } from "bknd";
|
import { createApp, type CreateAppConfig } from "bknd";
|
||||||
|
|
||||||
// create the app
|
// create the app
|
||||||
const config = { /* ... */ } satisfies CreateAppConfig;
|
const config = {
|
||||||
|
/* ... */
|
||||||
|
} satisfies CreateAppConfig;
|
||||||
const app = createApp(config);
|
const app = createApp(config);
|
||||||
|
|
||||||
// build the app
|
// build the app
|
||||||
@@ -36,40 +41,41 @@ In Web API compliant environments, all you have to do is to default exporting th
|
|||||||
implements the `Fetch` API.
|
implements the `Fetch` API.
|
||||||
|
|
||||||
## Configuration (`CreateAppConfig`)
|
## Configuration (`CreateAppConfig`)
|
||||||
|
|
||||||
The `CreateAppConfig` type is the main configuration object for the `createApp` function. It has
|
The `CreateAppConfig` type is the main configuration object for the `createApp` function. It has
|
||||||
the following properties:
|
the following properties:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { App, InitialModuleConfigs, ModuleBuildContext } from "bknd";
|
import type { App, InitialModuleConfigs, ModuleBuildContext, Connection } from "bknd";
|
||||||
import type { Connection } from "bknd/data";
|
|
||||||
import type { Config } from "@libsql/client";
|
import type { Config } from "@libsql/client";
|
||||||
|
|
||||||
type AppPlugin = (app: App) => Promise<void> | void;
|
type AppPlugin = (app: App) => Promise<void> | void;
|
||||||
type ManagerOptions = {
|
type ManagerOptions = {
|
||||||
basePath?: string;
|
basePath?: string;
|
||||||
trustFetched?: boolean;
|
trustFetched?: boolean;
|
||||||
onFirstBoot?: () => Promise<void>;
|
onFirstBoot?: () => Promise<void>;
|
||||||
seed?: (ctx: ModuleBuildContext) => Promise<void>;
|
seed?: (ctx: ModuleBuildContext) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CreateAppConfig = {
|
type CreateAppConfig = {
|
||||||
connection?:
|
connection?: Connection | Config;
|
||||||
| Connection
|
initialConfig?: InitialModuleConfigs;
|
||||||
| Config;
|
options?: {
|
||||||
initialConfig?: InitialModuleConfigs;
|
plugins?: AppPlugin[];
|
||||||
options?: {
|
manager?: ManagerOptions;
|
||||||
plugins?: AppPlugin[];
|
};
|
||||||
manager?: ManagerOptions
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### `connection`
|
### `connection`
|
||||||
|
|
||||||
The `connection` property is the main connection object to the database. It can be either an object with libsql config or the actual `Connection` class.
|
The `connection` property is the main connection object to the database. It can be either an object with libsql config or the actual `Connection` class.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const connection = {
|
const connection = {
|
||||||
url: "<url>",
|
url: "<url>",
|
||||||
authToken: "<token>"
|
authToken: "<token>",
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can pass an instance of a `Connection` class directly,
|
Alternatively, you can pass an instance of a `Connection` class directly,
|
||||||
@@ -78,7 +84,8 @@ see [Custom Connection](/usage/database#custom-connection) as a reference.
|
|||||||
If the connection object is omitted, the app will try to use an in-memory database.
|
If the connection object is omitted, the app will try to use an in-memory database.
|
||||||
|
|
||||||
### `initialConfig`
|
### `initialConfig`
|
||||||
As initial configuration, you can either pass a partial configuration object or a complete one
|
|
||||||
|
As [initial configuration](/usage/database#initial-structure), you can either pass a partial configuration object or a complete one
|
||||||
with a version number. The version number is used to automatically migrate the configuration up
|
with a version number. The version number is used to automatically migrate the configuration up
|
||||||
to the latest version upon boot. The default configuration looks like this:
|
to the latest version upon boot. The default configuration looks like this:
|
||||||
|
|
||||||
@@ -92,8 +99,13 @@ to the latest version upon boot. The default configuration looks like this:
|
|||||||
},
|
},
|
||||||
"cors": {
|
"cors": {
|
||||||
"origin": "*",
|
"origin": "*",
|
||||||
"allow_methods": ["GET", "POST", "PATCH", "PUT", "DELETE" ],
|
"allow_methods": ["GET", "POST", "PATCH", "PUT", "DELETE"],
|
||||||
"allow_headers": ["Content-Type", "Content-Length", "Authorization", "Accept"]
|
"allow_headers": [
|
||||||
|
"Content-Type",
|
||||||
|
"Content-Length",
|
||||||
|
"Authorization",
|
||||||
|
"Accept"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
@@ -146,11 +158,13 @@ to the latest version upon boot. The default configuration looks like this:
|
|||||||
```
|
```
|
||||||
|
|
||||||
You can use the CLI to get the default configuration:
|
You can use the CLI to get the default configuration:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx bknd config --pretty
|
npx bknd config --pretty
|
||||||
```
|
```
|
||||||
|
|
||||||
To validate your configuration against a JSON schema, you can also dump the schema using the CLI:
|
To validate your configuration against a JSON schema, you can also dump the schema using the CLI:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx bknd schema
|
npx bknd schema
|
||||||
```
|
```
|
||||||
@@ -158,6 +172,7 @@ npx bknd schema
|
|||||||
To create an initial data structure, you can use helpers [described here](/usage/database#initial-structure).
|
To create an initial data structure, you can use helpers [described here](/usage/database#initial-structure).
|
||||||
|
|
||||||
### `options.plugins`
|
### `options.plugins`
|
||||||
|
|
||||||
The `plugins` property is an array of functions that are called after the app has been built,
|
The `plugins` property is an array of functions that are called after the app has been built,
|
||||||
but before its event is emitted. This is useful for adding custom routes or other functionality.
|
but before its event is emitted. This is useful for adding custom routes or other functionality.
|
||||||
A simple plugin that adds a custom route looks like this:
|
A simple plugin that adds a custom route looks like this:
|
||||||
@@ -166,7 +181,7 @@ A simple plugin that adds a custom route looks like this:
|
|||||||
import type { AppPlugin } from "bknd";
|
import type { AppPlugin } from "bknd";
|
||||||
|
|
||||||
export const myPlugin: AppPlugin = (app) => {
|
export const myPlugin: AppPlugin = (app) => {
|
||||||
app.server.get("/hello", (c) => c.json({ hello: "world" }));
|
app.server.get("/hello", (c) => c.json({ hello: "world" }));
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -175,35 +190,39 @@ structure, add custom middlewares, respond to or add events, etc. Plugins are ve
|
|||||||
make sure to only run trusted ones.
|
make sure to only run trusted ones.
|
||||||
|
|
||||||
### `options.seed`
|
### `options.seed`
|
||||||
|
|
||||||
The `seed` property is a function that is called when the app is booted for the first time. It is used to seed the database with initial data. The function is passed a `ModuleBuildContext` object:
|
The `seed` property is a function that is called when the app is booted for the first time. It is used to seed the database with initial data. The function is passed a `ModuleBuildContext` object:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
type ModuleBuildContext = {
|
type ModuleBuildContext = {
|
||||||
connection: Connection;
|
connection: Connection;
|
||||||
server: Hono;
|
server: Hono;
|
||||||
em: EntityManager;
|
em: EntityManager;
|
||||||
emgr: EventManager;
|
emgr: EventManager;
|
||||||
guard: Guard;
|
guard: Guard;
|
||||||
};
|
};
|
||||||
|
|
||||||
const seed = async (ctx: ModuleBuildContext) => {
|
const seed = async (ctx: ModuleBuildContext) => {
|
||||||
// seed the database
|
// seed the database
|
||||||
await ctx.em.mutator("todos").insertMany([
|
await ctx.em.mutator("todos").insertMany([
|
||||||
{ title: "Learn bknd", done: true },
|
{ title: "Learn bknd", done: true },
|
||||||
{ title: "Build something cool", done: false }
|
{ title: "Build something cool", done: false },
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### `options.manager`
|
### `options.manager`
|
||||||
|
|
||||||
This object is passed to the `ModuleManager` which is responsible for:
|
This object is passed to the `ModuleManager` which is responsible for:
|
||||||
|
|
||||||
- validating and maintaining configuration of all modules
|
- validating and maintaining configuration of all modules
|
||||||
- building all modules (data, auth, media, flows)
|
- building all modules (data, auth, media, flows)
|
||||||
- maintaining the `ModuleBuildContext` used by the modules
|
- maintaining the `ModuleBuildContext` used by the modules
|
||||||
|
|
||||||
The `options.manager` object has the following properties:
|
The `options.manager` object has the following properties:
|
||||||
|
|
||||||
- `basePath` (`string`): The base path for the Hono instance. This is used to prefix all routes.
|
- `basePath` (`string`): The base path for the Hono instance. This is used to prefix all routes.
|
||||||
- `trustFetched` (`boolean`): If set to `true`, the app will not perform any validity checks for
|
- `trustFetched` (`boolean`): If set to `true`, the app will not perform any validity checks for
|
||||||
the given or fetched configuration.
|
the given or fetched configuration.
|
||||||
- `onFirstBoot` (`() => Promise<void>`): A function that is called when the app is booted for
|
- `onFirstBoot` (`() => Promise<void>`): A function that is called when the app is booted for
|
||||||
the first time.
|
the first time.
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
---
|
---
|
||||||
title: 'SDK (React)'
|
title: "SDK (React)"
|
||||||
description: 'Use the bknd SDK for React'
|
description: "Use the bknd SDK for React"
|
||||||
|
tags: ["documentation"]
|
||||||
---
|
---
|
||||||
|
|
||||||
There are 4 useful hooks to work with your backend:
|
There are 4 useful hooks to work with your backend:
|
||||||
|
|
||||||
1. simple hooks which are solely based on the [API](/usage/sdk):
|
1. simple hooks which are solely based on the [API](/usage/sdk):
|
||||||
- [`useApi`](#useapi)
|
- [`useApi`](#useapi)
|
||||||
- [`useEntity`](#useentity)
|
- [`useEntity`](#useentity)
|
||||||
@@ -11,69 +13,74 @@ There are 4 useful hooks to work with your backend:
|
|||||||
- [`useApiQuery`](#useapiquery)
|
- [`useApiQuery`](#useapiquery)
|
||||||
- [`useEntityQuery`](#useentityquery)
|
- [`useEntityQuery`](#useentityquery)
|
||||||
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
In order to use them, make sure you wrap your `<App />` inside `<ClientProvider />`, so that these hooks point to your bknd instance:
|
In order to use them, make sure you wrap your `<App />` inside `<ClientProvider />`, so that these hooks point to your bknd instance:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { ClientProvider } from "bknd/client";
|
import { ClientProvider } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return <ClientProvider>
|
return <ClientProvider>{/* your app */}</ClientProvider>;
|
||||||
{/* your app */}
|
|
||||||
</ClientProvider>
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For all other examples below, we'll assume that your app is wrapped inside the `ClientProvider`.
|
For all other examples below, we'll assume that your app is wrapped inside the `ClientProvider`.
|
||||||
|
|
||||||
## `useApi()`
|
## `useApi()`
|
||||||
|
|
||||||
To use the simple hook that returns the Api, you can use:
|
To use the simple hook that returns the Api, you can use:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useApi } from "bknd/client";
|
import { useApi } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `useApiQuery()`
|
## `useApiQuery()`
|
||||||
|
|
||||||
This hook wraps the API class in an SWR hook for convenience. You can use any API endpoint
|
This hook wraps the API class in an SWR hook for convenience. You can use any API endpoint
|
||||||
supported, like so:
|
supported, like so:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useApiQuery } from "bknd/client";
|
import { useApiQuery } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { data, ...swr } = useApiQuery((api) => api.data.readMany("comments"));
|
const { data, ...swr } = useApiQuery((api) => api.data.readMany("comments"));
|
||||||
|
|
||||||
if (swr.error) return <div>Error</div>
|
if (swr.error) return <div>Error</div>;
|
||||||
if (swr.isLoading) return <div>Loading...</div>
|
if (swr.isLoading) return <div>Loading...</div>;
|
||||||
|
|
||||||
return <pre>{JSON.stringify(data, null, 2)}</pre>
|
return <pre>{JSON.stringify(data, null, 2)}</pre>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Props
|
### Props
|
||||||
* `selector: (api: Api) => FetchPromise`
|
|
||||||
|
|
||||||
The first parameter is a selector function that provides an Api instance and expects an
|
- `selector: (api: Api) => FetchPromise`
|
||||||
endpoint function to be returned.
|
|
||||||
|
|
||||||
* `options`: optional object that inherits from `SWRConfiguration`
|
The first parameter is a selector function that provides an Api instance and expects an
|
||||||
|
endpoint function to be returned.
|
||||||
|
|
||||||
|
- `options`: optional object that inherits from `SWRConfiguration`
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
type Options <Data> = import("swr").SWRConfiguration & {
|
type Options<Data> = import("swr").SWRConfiguration & {
|
||||||
enabled? : boolean;
|
enabled?: boolean;
|
||||||
refine? : (data: Data) => Data | any;
|
refine?: (data: Data) => Data | any;
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
* `enabled`: Determines whether this hook should trigger a fetch of the data or not.
|
* `enabled`: Determines whether this hook should trigger a fetch of the data or not.
|
||||||
* `refine`: Optional refinement that is called after a response from the API has been
|
* `refine`: Optional refinement that is called after a response from the API has been
|
||||||
received. Useful to omit irrelevant data from the response (see example below).
|
|
||||||
|
received. Useful to omit irrelevant data from the response (see example below).
|
||||||
|
|
||||||
### Using mutations
|
### Using mutations
|
||||||
|
|
||||||
To query and mutate data using this hook, you can leverage the parameters returned. In the
|
To query and mutate data using this hook, you can leverage the parameters returned. In the
|
||||||
following example we'll also use a `refine` function as well as `revalidateOnFocus` (option from
|
following example we'll also use a `refine` function as well as `revalidateOnFocus` (option from
|
||||||
`SWRConfiguration`) so that our data keeps updating on window focus change.
|
`SWRConfiguration`) so that our data keeps updating on window focus change.
|
||||||
@@ -83,132 +90,151 @@ import { useEffect, useState } from "react";
|
|||||||
import { useApiQuery } from "bknd/client";
|
import { useApiQuery } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const { data, api, mutate, ...q } = useApiQuery(
|
const { data, api, mutate, ...q } = useApiQuery(
|
||||||
(api) => api.data.readOne("comments", 1),
|
(api) => api.data.readOne("comments", 1),
|
||||||
{
|
{
|
||||||
// filter to a subset of the response
|
// filter to a subset of the response
|
||||||
refine: (data) => data.data,
|
refine: (data) => data.data,
|
||||||
revalidateOnFocus: true
|
revalidateOnFocus: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const comment = data ? data : null;
|
const comment = data ? data : null;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setText(comment?.content ?? "");
|
setText(comment?.content ?? "");
|
||||||
}, [comment]);
|
}, [comment]);
|
||||||
|
|
||||||
if (q.error) return <div>Error</div>
|
if (q.error) return <div>Error</div>;
|
||||||
if (q.isLoading) return <div>Loading...</div>
|
if (q.isLoading) return <div>Loading...</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={async (e) => {
|
onSubmit={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!comment) return;
|
if (!comment) return;
|
||||||
|
|
||||||
// this will automatically revalidate the query
|
// this will automatically revalidate the query
|
||||||
await mutate(async () => {
|
await mutate(async () => {
|
||||||
const res = await api.data.updateOne("comments", comment.id, {
|
const res = await api.data.updateOne("comments", comment.id, {
|
||||||
content: text
|
content: text,
|
||||||
});
|
});
|
||||||
return res.data;
|
return res.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
|
<input
|
||||||
<button type="submit">Update</button>
|
type="text"
|
||||||
</form>
|
value={text}
|
||||||
);
|
onChange={(e) => setText(e.target.value)}
|
||||||
|
/>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `useEntity()`
|
## `useEntity()`
|
||||||
|
|
||||||
This hook wraps the endpoints of `DataApi` and returns CRUD options as parameters:
|
This hook wraps the endpoints of `DataApi` and returns CRUD options as parameters:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useEntity } from "bknd/client";
|
import { useEntity } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
const { create, read, update, _delete } = useEntity("comments", 1);
|
const { create, read, update, _delete } = useEntity("comments", 1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
read().then(setData);
|
read().then(setData);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <pre>{JSON.stringify(data, null, 2)}</pre>
|
return <pre>{JSON.stringify(data, null, 2)}</pre>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you only supply the entity name as string without an ID, the `read` method will fetch a list
|
If you only supply the entity name as string without an ID, the `read` method will fetch a list
|
||||||
of entities instead of a single entry.
|
of entities instead of a single entry.
|
||||||
|
|
||||||
### Props
|
### Props
|
||||||
|
|
||||||
Following props are available when using `useEntityQuery([entity], [id?])`:
|
Following props are available when using `useEntityQuery([entity], [id?])`:
|
||||||
|
|
||||||
- `entity: string`: Specify the table name of the entity
|
- `entity: string`: Specify the table name of the entity
|
||||||
- `id?: number | string`: If an id given, it will fetch a single entry, otherwise a list
|
- `id?: number | string`: If an id given, it will fetch a single entry, otherwise a list
|
||||||
|
|
||||||
### Returned actions
|
### Returned actions
|
||||||
|
|
||||||
The following actions are returned from this hook:
|
The following actions are returned from this hook:
|
||||||
|
|
||||||
- `create: (input: object)`: Create a new entry
|
- `create: (input: object)`: Create a new entry
|
||||||
- `read: (query: Partial<RepoQuery> = {})`: If an id was given,
|
- `read: (query: Partial<RepoQuery> = {})`: If an id was given,
|
||||||
it returns a single item, otherwise a list
|
it returns a single item, otherwise a list
|
||||||
- `update: (input: object, id?: number | string)`: If an id was given, the id parameter is
|
- `update: (input: object, id?: number | string)`: If an id was given, the id parameter is
|
||||||
optional. Updates the given entry partially.
|
optional. Updates the given entry partially.
|
||||||
- `_delete: (id?: number | string)`: If an id was given, the id parameter is
|
- `_delete: (id?: number | string)`: If an id was given, the id parameter is
|
||||||
optional. Deletes the given entry.
|
optional. Deletes the given entry.
|
||||||
|
|
||||||
## `useEntityQuery()`
|
## `useEntityQuery()`
|
||||||
|
|
||||||
This hook wraps the actions from `useEntity` around `SWR`. The previous example would look like
|
This hook wraps the actions from `useEntity` around `SWR`. The previous example would look like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useEntityQuery } from "bknd/client";
|
import { useEntityQuery } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { data } = useEntityQuery("comments", 1);
|
const { data } = useEntityQuery("comments", 1);
|
||||||
|
|
||||||
return <pre>{JSON.stringify(data, null, 2)}</pre>
|
return <pre>{JSON.stringify(data, null, 2)}</pre>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using mutations
|
### Using mutations
|
||||||
|
|
||||||
All actions returned from `useEntityQuery` are conveniently wrapped around the `mutate` function,
|
All actions returned from `useEntityQuery` are conveniently wrapped around the `mutate` function,
|
||||||
so you don't have think about this:
|
so you don't have think about this:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useEntityQuery } from "bknd/client";
|
import { useEntityQuery } from "bknd/client";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const { data, update, ...q } = useEntityQuery("comments", 1);
|
const { data, update, ...q } = useEntityQuery("comments", 1);
|
||||||
|
|
||||||
const comment = data ? data : null;
|
const comment = data ? data : null;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setText(comment?.content ?? "");
|
setText(comment?.content ?? "");
|
||||||
}, [comment]);
|
}, [comment]);
|
||||||
|
|
||||||
if (q.error) return <div>Error</div>
|
if (q.error) return <div>Error</div>;
|
||||||
if (q.isLoading) return <div>Loading...</div>
|
if (q.isLoading) return <div>Loading...</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={async (e) => {
|
onSubmit={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!comment) return;
|
if (!comment) return;
|
||||||
|
|
||||||
// this will automatically revalidate the query
|
// this will automatically revalidate the query
|
||||||
await update({ content: text });
|
await update({ content: text });
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
|
<input
|
||||||
<button type="submit">Update</button>
|
type="text"
|
||||||
</form>
|
value={text}
|
||||||
);
|
onChange={(e) => setText(e.target.value)}
|
||||||
|
/>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user