bunderstack 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # bunderstack
2
2
 
3
- The server package for Bunderstack's unified, type-safe oRPC backend.
3
+ The complete backend & full-stack framework for Bun: type-safe oRPC APIs, auth, storage, realtime, jobs, email, live views, and client bindings from one single file declaration.
4
4
 
5
5
  ```sh
6
6
  bun add bunderstack better-auth drizzle-orm valibot @libsql/client
@@ -44,16 +44,28 @@ Use the in-memory Publisher for one process or configure
44
44
  `realtime: { redis: process.env.REDIS_URL! }` for multi-process delivery and
45
45
  replay. Deployment metadata is generated with `bunx bunderstack blueprint`.
46
46
 
47
+ ## Package Subpaths (0.21+)
48
+
49
+ - `bunderstack` — Backend runtime (`createBunderstack`, `provision`, `defineApi`, `buildApiRegistry`)
50
+ - `bunderstack/client` — Framework-neutral RPC & LiveView client (`createClient`, `createLiveView`)
51
+ - `bunderstack/client/rest` — Type-safe REST client
52
+ - `bunderstack/client/react`, `bunderstack/client/solid`, `bunderstack/client/vue`, `bunderstack/client/svelte` — LiveView UI bindings
53
+ - `bunderstack/query` & `bunderstack/query/react` — TanStack Query client (`createClient`, `syncRealtime`)
54
+ - `bunderstack/sync` — TanStack DB collections (`createSyncClient`)
55
+ - `bunderstack/start` & `bunderstack/start/auth` — TanStack Start full-stack integration
56
+ - `bunderstack/database/*` — Database adapters (`libsql`, `postgres-js`, `bun-sql`, `pglite`)
57
+ - `bunderstack/storage/*` — Storage adapters (`s3`, `disk`)
58
+ - `bunderstack/email/*` — Email adapters (`smtp`, `resend`, `console`)
59
+ - `bunderstack/jobs/*` — Job queue adapters (`memory`, `redis`)
60
+
47
61
  See the [workspace documentation](https://github.com/kirill-dev-pro/bunderstack#readme) for webhooks, clients,
48
62
  storage, collections, lifecycle, and complete examples.
49
63
 
50
64
  ## Upgrading
51
65
 
52
- 0.17 is a breaking release: tRPC became oRPC, generated `list` takes nested
53
- typed `filters`, error codes are oRPC's own, and realtime names tables by their
54
- schema key. Every change is listed with before/after code in the migration
55
- guides, which ship with the package as `CHANGELOG.md` and live in full at:
66
+ Every change is listed with before/after code in the migration guides, which live in full at:
56
67
 
68
+ - [Migrating to 0.21](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.21.md)
57
69
  - [Migrating to 0.17](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.17.md)
58
70
  - [Migrating to 0.16](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.16.md)
59
71
 
@@ -1,5 +1,5 @@
1
1
  import { QueryClient } from '@tanstack/react-query';
2
- import { type AnyBunderstackApp, type BunderstackSyncClient } from '../sync/index.js';
2
+ import { type AnyBunderstackApp, type BunderstackClient } from '../query/index.js';
3
3
  export { createIsomorphicFetch } from './isomorphic-fetch.js';
4
4
  export type BunderstackStartOptions = {
5
5
  /** API mount point. Defaults to '/api'. */
@@ -9,7 +9,7 @@ export type BunderstackStartOptions = {
9
9
  };
10
10
  /**
11
11
  * One-call client setup for TanStack Start apps: SSR-aware fetch, sensible
12
- * QueryClient defaults, and a sync client whose tables and buckets are
12
+ * QueryClient defaults, and a typed query client whose procedures and buckets are
13
13
  * inferred from the server app type.
14
14
  *
15
15
  * @example
@@ -20,7 +20,7 @@ export type BunderstackStartOptions = {
20
20
  */
21
21
  export declare function bunderstackStart<TApp extends AnyBunderstackApp>(options?: BunderstackStartOptions): {
22
22
  createQueryClient: () => QueryClient;
23
- createApi: (queryClient: QueryClient) => BunderstackSyncClient<TApp>;
23
+ createApi: (queryClient: QueryClient) => BunderstackClient<TApp>;
24
24
  };
25
25
  type StartRequestContext = {
26
26
  request: Request;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/start/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,uBAAuB,GAAG;IACpC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,SAAS,iBAAiB,EAC7D,OAAO,GAAE,uBAA4B;;6BAUV,WAAW,KAAG,qBAAqB,CAAC,IAAI,CAAC;EAOrE;AAED,KAAK,mBAAmB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAC/C,KAAK,YAAY,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE;IACrC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC7C,GAAG;IACF,GAAG,EAAE,YAAY,CAAA;IACjB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,YAAY,CAAA;CACrB,CAGA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE;QACJ,GAAG,EAAE;YACH,UAAU,EAAE,CAAC,IAAI,EAAE;gBACjB,OAAO,EAAE,OAAO,CAAA;aACjB,KAAK,OAAO,CAAC;gBAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;aAAE,GAAG,IAAI,CAAC,CAAA;SACnD,CAAA;KACF,CAAA;CACF,CAAA;AAED,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAG7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/start/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,uBAAuB,GAAG;IACpC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,SAAS,iBAAiB,EAC7D,OAAO,GAAE,uBAA4B;;6BAUV,WAAW,KAAG,iBAAiB,CAAC,IAAI,CAAC;EAOjE;AAED,KAAK,mBAAmB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAC/C,KAAK,YAAY,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE;IACrC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC7C,GAAG;IACF,GAAG,EAAE,YAAY,CAAA;IACjB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,YAAY,CAAA;CACrB,CAGA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE;QACJ,GAAG,EAAE;YACH,UAAU,EAAE,CAAC,IAAI,EAAE;gBACjB,OAAO,EAAE,OAAO,CAAA;aACjB,KAAK,OAAO,CAAC;gBAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;aAAE,GAAG,IAAI,CAAC,CAAA;SACnD,CAAA;KACF,CAAA;CACF,CAAA;AAED,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAG7B"}
@@ -1,10 +1,10 @@
1
1
  import { QueryClient } from '@tanstack/react-query';
2
- import { createSyncClient, } from '../sync/index.js';
2
+ import { createClient, } from '../query/index.js';
3
3
  import { createIsomorphicFetch } from './isomorphic-fetch.js';
4
4
  export { createIsomorphicFetch } from './isomorphic-fetch.js';
5
5
  /**
6
6
  * One-call client setup for TanStack Start apps: SSR-aware fetch, sensible
7
- * QueryClient defaults, and a sync client whose tables and buckets are
7
+ * QueryClient defaults, and a typed query client whose procedures and buckets are
8
8
  * inferred from the server app type.
9
9
  *
10
10
  * @example
@@ -21,7 +21,7 @@ export function bunderstackStart(options = {}) {
21
21
  queries: { staleTime: options.staleTime ?? 30_000 },
22
22
  },
23
23
  }),
24
- createApi: (queryClient) => createSyncClient({
24
+ createApi: (queryClient) => createClient({
25
25
  queryClient,
26
26
  fetch: isoFetch,
27
27
  baseUrl: options.baseUrl,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/start/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,EACL,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAS1D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAmC,EAAE;IAErC,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,OAAO;QACL,iBAAiB,EAAE,GAAG,EAAE,CACtB,IAAI,WAAW,CAAC;YACd,cAAc,EAAE;gBACd,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM,EAAE;aACpD;SACF,CAAC;QACJ,SAAS,EAAE,CAAC,WAAwB,EAA+B,EAAE,CACnE,gBAAgB,CAAO;YACrB,WAAW;YACX,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;KACL,CAAA;AACH,CAAC;AAKD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAEjC;IAMC,MAAM,MAAM,GAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAClE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AACrE,CAAC;AAoBD,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,OAAgB;IAEhB,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3E,OAAO,OAAO,EAAE,IAAI,IAAI,IAAI,CAAA;AAC9B,CAAC","sourcesContent":["import { QueryClient } from '@tanstack/react-query'\n\nimport {\n createSyncClient,\n type AnyBunderstackApp,\n type BunderstackSyncClient,\n} from '../sync/index'\nimport { createIsomorphicFetch } from './isomorphic-fetch'\n\nexport { createIsomorphicFetch } from './isomorphic-fetch'\n\nexport type BunderstackStartOptions = {\n /** API mount point. Defaults to '/api'. */\n baseUrl?: string\n /** Default query staleTime (ms). Defaults to 30_000. */\n staleTime?: number\n}\n\n/**\n * One-call client setup for TanStack Start apps: SSR-aware fetch, sensible\n * QueryClient defaults, and a sync client whose tables and buckets are\n * inferred from the server app type.\n *\n * @example\n * // src/api.ts — NOT src/client.ts, which is a reserved TanStack Start\n * // entry-point name (it would replace the hydration entry).\n * import type { App } from './bunderstack'\n * export const { createQueryClient, createApi } = bunderstackStart<App>()\n */\nexport function bunderstackStart<TApp extends AnyBunderstackApp>(\n options: BunderstackStartOptions = {},\n) {\n const isoFetch = createIsomorphicFetch()\n return {\n createQueryClient: () =>\n new QueryClient({\n defaultOptions: {\n queries: { staleTime: options.staleTime ?? 30_000 },\n },\n }),\n createApi: (queryClient: QueryClient): BunderstackSyncClient<TApp> =>\n createSyncClient<TApp>({\n queryClient,\n fetch: isoFetch,\n baseUrl: options.baseUrl,\n }),\n }\n}\n\ntype StartRequestContext = { request: Request }\ntype StartHandler = (ctx: StartRequestContext) => Promise<Response>\n\n/**\n * Handlers object for the catch-all API file route.\n *\n * @example\n * // src/routes/api/$.tsx\n * export const Route = createFileRoute('/api/$')({\n * server: { handlers: createApiHandlers(app) },\n * })\n */\nexport function createApiHandlers(app: {\n handler: (req: Request) => Promise<Response>\n}): {\n GET: StartHandler\n POST: StartHandler\n PATCH: StartHandler\n DELETE: StartHandler\n} {\n const handle: StartHandler = ({ request }) => app.handler(request)\n return { GET: handle, POST: handle, PATCH: handle, DELETE: handle }\n}\n\nexport type SessionUser = {\n id: string\n email: string\n name: string\n image?: string | null\n role?: string\n}\n\ntype SessionApp = {\n auth: {\n api: {\n getSession: (opts: {\n headers: Headers\n }) => Promise<{ user: SessionUser | null } | null>\n }\n }\n}\n\n/** Resolve the BetterAuth session user for an incoming request (server-side). */\nexport async function getSessionUser(\n app: SessionApp,\n request: Request,\n): Promise<SessionUser | null> {\n const session = await app.auth.api.getSession({ headers: request.headers })\n return session?.user ?? null\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/start/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,EACL,YAAY,GAGb,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAS1D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAmC,EAAE;IAErC,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,OAAO;QACL,iBAAiB,EAAE,GAAG,EAAE,CACtB,IAAI,WAAW,CAAC;YACd,cAAc,EAAE;gBACd,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM,EAAE;aACpD;SACF,CAAC;QACJ,SAAS,EAAE,CAAC,WAAwB,EAA2B,EAAE,CAC/D,YAAY,CAAO;YACjB,WAAW;YACX,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;KACL,CAAA;AACH,CAAC;AAKD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAEjC;IAMC,MAAM,MAAM,GAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAClE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AACrE,CAAC;AAoBD,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,OAAgB;IAEhB,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3E,OAAO,OAAO,EAAE,IAAI,IAAI,IAAI,CAAA;AAC9B,CAAC","sourcesContent":["import { QueryClient } from '@tanstack/react-query'\n\nimport {\n createClient,\n type AnyBunderstackApp,\n type BunderstackClient,\n} from '../query/index'\nimport { createIsomorphicFetch } from './isomorphic-fetch'\n\nexport { createIsomorphicFetch } from './isomorphic-fetch'\n\nexport type BunderstackStartOptions = {\n /** API mount point. Defaults to '/api'. */\n baseUrl?: string\n /** Default query staleTime (ms). Defaults to 30_000. */\n staleTime?: number\n}\n\n/**\n * One-call client setup for TanStack Start apps: SSR-aware fetch, sensible\n * QueryClient defaults, and a typed query client whose procedures and buckets are\n * inferred from the server app type.\n *\n * @example\n * // src/api.ts — NOT src/client.ts, which is a reserved TanStack Start\n * // entry-point name (it would replace the hydration entry).\n * import type { App } from './bunderstack'\n * export const { createQueryClient, createApi } = bunderstackStart<App>()\n */\nexport function bunderstackStart<TApp extends AnyBunderstackApp>(\n options: BunderstackStartOptions = {},\n) {\n const isoFetch = createIsomorphicFetch()\n return {\n createQueryClient: () =>\n new QueryClient({\n defaultOptions: {\n queries: { staleTime: options.staleTime ?? 30_000 },\n },\n }),\n createApi: (queryClient: QueryClient): BunderstackClient<TApp> =>\n createClient<TApp>({\n queryClient,\n fetch: isoFetch,\n baseUrl: options.baseUrl,\n }),\n }\n}\n\ntype StartRequestContext = { request: Request }\ntype StartHandler = (ctx: StartRequestContext) => Promise<Response>\n\n/**\n * Handlers object for the catch-all API file route.\n *\n * @example\n * // src/routes/api/$.tsx\n * export const Route = createFileRoute('/api/$')({\n * server: { handlers: createApiHandlers(app) },\n * })\n */\nexport function createApiHandlers(app: {\n handler: (req: Request) => Promise<Response>\n}): {\n GET: StartHandler\n POST: StartHandler\n PATCH: StartHandler\n DELETE: StartHandler\n} {\n const handle: StartHandler = ({ request }) => app.handler(request)\n return { GET: handle, POST: handle, PATCH: handle, DELETE: handle }\n}\n\nexport type SessionUser = {\n id: string\n email: string\n name: string\n image?: string | null\n role?: string\n}\n\ntype SessionApp = {\n auth: {\n api: {\n getSession: (opts: {\n headers: Headers\n }) => Promise<{ user: SessionUser | null } | null>\n }\n }\n}\n\n/** Resolve the BetterAuth session user for an incoming request (server-side). */\nexport async function getSessionUser(\n app: SessionApp,\n request: Request,\n): Promise<SessionUser | null> {\n const session = await app.auth.api.getSession({ headers: request.headers })\n return session?.user ?? null\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunderstack",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "Batteries-included backend framework for Bun: type-safe oRPC APIs, auth, storage, realtime, jobs, email, and validated env from one config.",
5
5
  "keywords": [
6
6
  "backend",