updated App options "seed", changed examples to file db

This commit is contained in:
dswbx
2025-02-18 20:01:08 +01:00
parent a4e46a2768
commit a01b99be27
8 changed files with 38 additions and 29 deletions

View File

@@ -3,7 +3,7 @@
"type": "module", "type": "module",
"sideEffects": false, "sideEffects": false,
"bin": "./dist/cli/index.js", "bin": "./dist/cli/index.js",
"version": "0.8.0-rc.9", "version": "0.8.0-rc.10",
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, Remix, Astro, Cloudflare, Bun, Node, AWS Lambda & more.", "description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, Remix, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
"homepage": "https://bknd.io", "homepage": "https://bknd.io",
"repository": { "repository": {

View File

@@ -4,6 +4,7 @@ import { Connection, type LibSqlCredentials, LibsqlConnection } from "data";
import type { Hono } from "hono"; import type { Hono } from "hono";
import { import {
type InitialModuleConfigs, type InitialModuleConfigs,
type ModuleBuildContext,
ModuleManager, ModuleManager,
type ModuleManagerOptions, type ModuleManagerOptions,
type Modules type Modules
@@ -28,7 +29,8 @@ export const AppEvents = { AppConfigUpdatedEvent, AppBuiltEvent, AppFirstBoot }
export type AppOptions = { export type AppOptions = {
plugins?: AppPlugin[]; plugins?: AppPlugin[];
manager?: Omit<ModuleManagerOptions, "initial" | "onUpdated">; seed?: (ctx: ModuleBuildContext) => Promise<void>;
manager?: Omit<ModuleManagerOptions, "initial" | "onUpdated" | "seed">;
}; };
export type CreateAppConfig = { export type CreateAppConfig = {
connection?: connection?:
@@ -61,6 +63,7 @@ export class App {
this.modules = new ModuleManager(connection, { this.modules = new ModuleManager(connection, {
...(options?.manager ?? {}), ...(options?.manager ?? {}),
initial: _initialConfig, initial: _initialConfig,
seed: options?.seed,
onUpdated: async (key, config) => { onUpdated: async (key, config) => {
// if the EventManager was disabled, we assume we shouldn't // if the EventManager was disabled, we assume we shouldn't
// respond to events, such as "onUpdated". // respond to events, such as "onUpdated".

View File

@@ -67,6 +67,7 @@ described above, or an class instance that extends from `Connection`:
```ts ```ts
import { createApp } from "bknd"; import { createApp } from "bknd";
import { Connection } from "bknd/data"; import { Connection } from "bknd/data";
import { Kysely } from "kysely";
class CustomConnection extends Connection { class CustomConnection extends Connection {
constructor() { constructor() {
@@ -85,6 +86,7 @@ const app = createApp({ connection })
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:
```ts ```ts
import { createApp } from "bknd";
import { em, entity, text, number } from "bknd/data"; import { em, entity, text, number } from "bknd/data";
const schema = em({ const schema = em({
@@ -142,9 +144,9 @@ All entity related functions use the types defined in `DB` from `bknd/core`. To
```ts ```ts
import { em } from "bknd/data"; import { em } from "bknd/data";
import { Api } from "bknd"; 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/core" {
@@ -160,7 +162,7 @@ The type completion is available for the API as well as all provided [React hook
### 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` ([reference](/usage/introduction#modulebuildcontext)) as the first argument. provides the `ModuleBuildContext` as the first argument.
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 configuration
already exists in the database, it will not be executed. already exists in the database, it will not be executed.

View File

@@ -157,7 +157,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).
### `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:
@@ -174,23 +174,9 @@ Since each plugin has full access to the `app` instance, it can add routes, modi
structure, add custom middlewares, respond to or add events, etc. Plugins are very powerful, so structure, add custom middlewares, respond to or add events, etc. Plugins are very powerful, so
make sure to only run trusted ones. make sure to only run trusted ones.
### `options` ### `options.seed`
This object is passed to the `ModuleManager` which is responsible for: 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:
- validating and maintaining configuration of all modules
- building all modules (data, auth, media, flows)
- maintaining the `ModuleBuildContext` used by the modules
The `options` object has the following properties:
- `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
the given or fetched configuration.
- `onFirstBoot` (`() => Promise<void>`): A function that is called when the app is booted for
the first time.
- `seed` (`(ctx: ModuleBuildContext) => Promise<void>`): A function that is called when the app is
booted for the first time and an initial partial configuration is provided.
## `ModuleBuildContext`
```ts ```ts
type ModuleBuildContext = { type ModuleBuildContext = {
connection: Connection; connection: Connection;
@@ -199,4 +185,25 @@ type ModuleBuildContext = {
emgr: EventManager; emgr: EventManager;
guard: Guard; guard: Guard;
}; };
const seed = async (ctx: ModuleBuildContext) => {
// seed the database
await ctx.em.mutator("todos").insertMany([
{ title: "Learn bknd", done: true },
{ title: "Build something cool", done: false }
]);
};
``` ```
### `options.manager`
This object is passed to the `ModuleManager` which is responsible for:
- validating and maintaining configuration of all modules
- building all modules (data, auth, media, flows)
- maintaining the `ModuleBuildContext` used by the modules
The `options.manager` object has the following properties:
- `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
the given or fetched configuration.
- `onFirstBoot` (`() => Promise<void>`): A function that is called when the app is booted for
the first time.

View File

@@ -27,7 +27,7 @@ declare module "bknd/core" {
export const ALL = serve<APIContext>({ export const ALL = serve<APIContext>({
// we can use any libsql config, and if omitted, uses in-memory // we can use any libsql config, and if omitted, uses in-memory
connection: { connection: {
url: "file:test.db" url: "file:data.db"
}, },
// an initial config is only applied if the database is empty // an initial config is only applied if the database is empty
initialConfig: { initialConfig: {

View File

@@ -7,7 +7,7 @@ import { type BunBkndConfig, serve } from "bknd/adapter/bun";
// this is optional, if omitted, it uses an in-memory database // this is optional, if omitted, it uses an in-memory database
const config: BunBkndConfig = { const config: BunBkndConfig = {
connection: { connection: {
url: ":memory:" url: "file:data.db"
} }
}; };

View File

@@ -7,7 +7,7 @@ import { serve } from "bknd/adapter/node";
/** @type {import("bknd/adapter/node").NodeBkndConfig} */ /** @type {import("bknd/adapter/node").NodeBkndConfig} */
const config = { const config = {
connection: { connection: {
url: ":memory:" url: "file:data.db"
} }
}; };

View File

@@ -1,6 +1,5 @@
import { type MetaFunction, useLoaderData } from "@remix-run/react"; import { type MetaFunction, useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs } from "@remix-run/server-runtime"; import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
import { useAuth } from "bknd/client";
export const meta: MetaFunction = () => { export const meta: MetaFunction = () => {
return [{ title: "Remix & bknd" }, { name: "description", content: "Welcome to Remix & bknd!" }]; return [{ title: "Remix & bknd" }, { name: "description", content: "Welcome to Remix & bknd!" }];
@@ -13,8 +12,6 @@ export const loader = async ({ context: { api } }: LoaderFunctionArgs) => {
export default function Index() { export default function Index() {
const { data, user } = useLoaderData<typeof loader>(); const { data, user } = useLoaderData<typeof loader>();
const auth = useAuth();
console.log("auth", auth);
return ( return (
<div> <div>