better-supabase 0.0.0 → 0.2.0
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/LICENSE +21 -0
- package/README.md +88 -1
- package/bin/better-supabase.js +4 -0
- package/dist/casing-da0uRTqt.js +14 -0
- package/dist/claims-CoTobNC-.js +25 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +15 -0
- package/dist/cli/index.d.ts +226 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli-DrSgDOQC.js +6646 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +112 -0
- package/dist/compiler-CZ9nIuqy.d.ts +14 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +3 -0
- package/dist/config-ClDXmVtY.js +277 -0
- package/dist/define-BXMYD9AY.js +1071 -0
- package/dist/define-e3zI4_4g.d.ts +679 -0
- package/dist/edge/index.d.ts +43 -0
- package/dist/edge/index.js +103 -0
- package/dist/entitlements-CTEBm7IB.js +20 -0
- package/dist/entitlements-Dng-ctuT.d.ts +42 -0
- package/dist/env/index.d.ts +2 -0
- package/dist/env/index.js +2 -0
- package/dist/env-BEToab0I.js +204 -0
- package/dist/errors-Bl3rkOzo.js +196 -0
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.js +2 -0
- package/dist/events-BuzTgn2D.js +135 -0
- package/dist/events-DOt3nSO-.d.ts +84 -0
- package/dist/executor-BYXQ9AGn.d.ts +25 -0
- package/dist/executor-CGdNQ27g.d.ts +195 -0
- package/dist/executor-DeppvirK.js +89 -0
- package/dist/guards-BnzDvFrz.js +10 -0
- package/dist/hono/index.d.ts +45 -0
- package/dist/hono/index.js +70 -0
- package/dist/index-Bw1bwtC0.d.ts +144 -0
- package/dist/index-CBDufH1M.d.ts +120 -0
- package/dist/index-CG69s15v.d.ts +38 -0
- package/dist/index-Ciu5Xlml.d.ts +74 -0
- package/dist/index-D4v7sncu.d.ts +62 -0
- package/dist/index-DOsjFvMf.d.ts +618 -0
- package/dist/index-DbxFr7XG.d.ts +76 -0
- package/dist/index-DuP14VHo.d.ts +216 -0
- package/dist/index-Dy6kuF0P.d.ts +71 -0
- package/dist/index-K-3WM2Hp.d.ts +117 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +43 -0
- package/dist/invalidate-DbxuL2jL.js +18 -0
- package/dist/jobs/index.d.ts +173 -0
- package/dist/jobs/index.js +478 -0
- package/dist/json-schema-BpYqkCKf.js +182 -0
- package/dist/lint/index.d.ts +75 -0
- package/dist/lint/index.js +167 -0
- package/dist/list/index.d.ts +2 -0
- package/dist/list/index.js +410 -0
- package/dist/live-D8rV1Ldw.js +168 -0
- package/dist/live-DJyZMD6w.d.ts +191 -0
- package/dist/logger-glM28NVN.js +21 -0
- package/dist/mcp/index.d.ts +142 -0
- package/dist/mcp/index.js +463 -0
- package/dist/mfa-CpLfJSde.js +541 -0
- package/dist/mfa-TVia554c.d.ts +44 -0
- package/dist/next/image/index.d.ts +34 -0
- package/dist/next/image/index.js +40 -0
- package/dist/next/index.d.ts +210 -0
- package/dist/next/index.js +427 -0
- package/dist/openapi/index.d.ts +2 -0
- package/dist/openapi/index.js +332 -0
- package/dist/orpc/index.d.ts +46 -0
- package/dist/orpc/index.js +50 -0
- package/dist/otel/index.d.ts +40 -0
- package/dist/otel/index.js +168 -0
- package/dist/path-Cv__-OTj.d.ts +17 -0
- package/dist/permdock-sql-CghlHPuH.js +117 -0
- package/dist/plugin-BqR6wKMB.js +23 -0
- package/dist/plugin-C4TR9J0Z.d.ts +118 -0
- package/dist/plugins/actor/index.d.ts +13 -0
- package/dist/plugins/actor/index.js +43 -0
- package/dist/plugins/rules/index.d.ts +89 -0
- package/dist/plugins/rules/index.js +167 -0
- package/dist/plugins/soft-delete/index.d.ts +38 -0
- package/dist/plugins/soft-delete/index.js +69 -0
- package/dist/plugins/tenant/index.d.ts +49 -0
- package/dist/plugins/tenant/index.js +75 -0
- package/dist/plugins/timestamps/index.d.ts +9 -0
- package/dist/plugins/timestamps/index.js +37 -0
- package/dist/plugins/validation/index.d.ts +24 -0
- package/dist/plugins/validation/index.js +59 -0
- package/dist/pool-R2m_DkXi.d.ts +37 -0
- package/dist/postgres/index.d.ts +28 -0
- package/dist/postgres/index.js +79 -0
- package/dist/postgrest-cAEQ_IQN.d.ts +43 -0
- package/dist/problem-BTkTtRV9.js +97 -0
- package/dist/problem-DlgB0lYl.d.ts +47 -0
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.js +3 -0
- package/dist/query-ChvDbsDE.js +186 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.js +5 -0
- package/dist/react/server.d.ts +13 -0
- package/dist/react/server.js +25 -0
- package/dist/react/session.d.ts +2 -0
- package/dist/react/session.js +3 -0
- package/dist/react-C83BdBGt.js +242 -0
- package/dist/read-set-4lI3W_gZ.js +216 -0
- package/dist/realtime/index.d.ts +4 -0
- package/dist/realtime/index.js +268 -0
- package/dist/resolve-CjHILk2w.d.ts +170 -0
- package/dist/resource-BHEWmQJK.js +175 -0
- package/dist/resource-CgZa3YG_.d.ts +65 -0
- package/dist/respond-DMcbQwfN.js +383 -0
- package/dist/respond-Dne1ARSa.d.ts +169 -0
- package/dist/result-CTkCZ6JA.d.ts +198 -0
- package/dist/result-DWXatkd6.js +103 -0
- package/dist/scope-CDHcS7dE.js +90 -0
- package/dist/seed-CzecODcJ.js +101 -0
- package/dist/server/index.d.ts +42 -0
- package/dist/server/index.js +68 -0
- package/dist/session-C3LxnQ0e.d.ts +22 -0
- package/dist/session-CqEwzVup.js +20 -0
- package/dist/shared-_6-uPL7E.js +57 -0
- package/dist/simplify-bwJpLnaS.js +665 -0
- package/dist/spec-pins-C3oc-Tdp.js +20 -0
- package/dist/spec-pins-CqorWDnO.d.ts +20 -0
- package/dist/sql-DTjA1LPj.js +260 -0
- package/dist/ssr/index.d.ts +5 -0
- package/dist/ssr/index.js +4 -0
- package/dist/standard-CyhRzctb.d.ts +7 -0
- package/dist/standard-FUi3Z3-7.js +21 -0
- package/dist/stats-C5W-rBfR.js +566 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage-DuGn38fr.js +527 -0
- package/dist/tables-rZxRxNPW.js +59 -0
- package/dist/template-mbvlysOo.d.ts +6 -0
- package/dist/testing/index.d.ts +325 -0
- package/dist/testing/index.js +819 -0
- package/dist/types-6cYK9pbJ.js +29 -0
- package/dist/types-C83v5SQz.d.ts +248 -0
- package/dist/version-Cqq1m3UY.js +4 -0
- package/dist/view-D1s0wa0T.d.ts +49 -0
- package/dist/view-aOYizTeE.js +36 -0
- package/dist/webhooks/index.d.ts +152 -0
- package/dist/webhooks/index.js +2 -0
- package/dist/webhooks-DMipjhSP.js +139 -0
- package/package.json +250 -17
- package/schemas/config-v1.json +373 -0
- package/schemas/doctor-report-v1.json +106 -0
- package/schemas/snapshot-v2.json +1006 -0
- package/skills/better-supabase/SKILL.md +84 -0
- package/skills/better-supabase/references/plugins.md +65 -0
- package/skills/better-supabase/references/troubleshooting.md +39 -0
- package/skills/better-supabase-api/SKILL.md +67 -0
- package/skills/better-supabase-api/references/adapters.md +108 -0
- package/skills/better-supabase-testing/SKILL.md +66 -0
- package/index.js +0 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { N as TableKey, O as Row, n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
|
|
2
|
+
import { l as CountMode } from "./executor-CGdNQ27g.js";
|
|
3
|
+
import { b as ValidationIssue, t as AsyncResult } from "./result-CTkCZ6JA.js";
|
|
4
|
+
import { C as FindExt, Ct as WhereInput, O as RepositoryOf, T as OffsetPageArgs, dt as IncludeArg, gt as OrderByArg, t as BetterSupabase, vt as Payload, w as OffsetPage, xt as SelectArg } from "./define-e3zI4_4g.js";
|
|
5
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
|
+
//#region src/list/index.d.ts
|
|
7
|
+
/** Facet value meaning "not set": filters with `is null`. */
|
|
8
|
+
declare const UNSET = "__unset__";
|
|
9
|
+
type Column<M extends AnyModels, T extends keyof M> = Extract<keyof Row<M, T>, string>;
|
|
10
|
+
type TextColumn<M extends AnyModels, T extends keyof M> = { [K in Column<M, T>]: [NonNullable<Row<M, T>[K]>] extends [string] ? K : never; }[Column<M, T>];
|
|
11
|
+
interface ListQueryConfig<M extends AnyModels, T extends keyof M, S extends string, F extends string, C extends boolean = boolean> {
|
|
12
|
+
/**
|
|
13
|
+
* Also count rows per facet value, with one grouped aggregate that runs
|
|
14
|
+
* next to the page: 2 calls, 1 wave. Needs PostgREST aggregates.
|
|
15
|
+
*/
|
|
16
|
+
readonly facetCounts?: C;
|
|
17
|
+
/** How the page total is counted. Defaults to `'exact'`. */
|
|
18
|
+
readonly count?: CountMode;
|
|
19
|
+
/** Text columns matched case-insensitively (OR), or a full-text column. */
|
|
20
|
+
readonly search?: readonly TextColumn<M, T>[] | {
|
|
21
|
+
readonly fts: Column<M, T>;
|
|
22
|
+
readonly config?: string;
|
|
23
|
+
};
|
|
24
|
+
/** Filterable columns by URL key. Values are validated against enums and CHECK unions. */
|
|
25
|
+
readonly facets?: { readonly [K in F]: Column<M, T>; };
|
|
26
|
+
/** Named orderings. Add a unique column last for stable pages. */
|
|
27
|
+
readonly sorts: { readonly [K in S]: OrderByArg<M, T>; };
|
|
28
|
+
readonly defaultSort: NoInfer<S>;
|
|
29
|
+
/** Defaults to 50. */
|
|
30
|
+
readonly pageSize?: number;
|
|
31
|
+
/** Defaults to 200. */
|
|
32
|
+
readonly maxPageSize?: number;
|
|
33
|
+
/** Defaults to 200 characters. */
|
|
34
|
+
readonly maxSearchLength?: number;
|
|
35
|
+
}
|
|
36
|
+
interface ListQuery<S extends string, F extends string> {
|
|
37
|
+
readonly q?: string;
|
|
38
|
+
readonly sort: S;
|
|
39
|
+
/** 1-based. */
|
|
40
|
+
readonly page: number;
|
|
41
|
+
readonly size: number;
|
|
42
|
+
readonly facets: { readonly [K in F]?: readonly string[]; };
|
|
43
|
+
}
|
|
44
|
+
/** Typed input (JSON APIs, actions, MCP tools). Everything is optional. */
|
|
45
|
+
interface ListQueryInput<S extends string, F extends string> {
|
|
46
|
+
readonly q?: string;
|
|
47
|
+
readonly sort?: S;
|
|
48
|
+
readonly page?: number;
|
|
49
|
+
readonly size?: number;
|
|
50
|
+
readonly facets?: { readonly [K in F]?: readonly string[]; };
|
|
51
|
+
}
|
|
52
|
+
/** URL input: `URLSearchParams` or a Next.js `searchParams` record. */
|
|
53
|
+
type ListSearchParams = URLSearchParams | Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
54
|
+
type ListParseResult<S extends string, F extends string> = {
|
|
55
|
+
readonly ok: true;
|
|
56
|
+
readonly value: ListQuery<S, F>;
|
|
57
|
+
readonly issues?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
readonly ok: false;
|
|
60
|
+
readonly value?: undefined;
|
|
61
|
+
readonly issues: readonly ValidationIssue[];
|
|
62
|
+
};
|
|
63
|
+
interface ParserSpec<V> {
|
|
64
|
+
parse(value: string): V | null;
|
|
65
|
+
serialize(value: V): string;
|
|
66
|
+
}
|
|
67
|
+
interface OpenApiParameter {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly in: "query";
|
|
70
|
+
readonly required: false;
|
|
71
|
+
readonly description: string;
|
|
72
|
+
readonly schema: Readonly<Record<string, unknown>>;
|
|
73
|
+
readonly style?: "form";
|
|
74
|
+
readonly explode?: boolean;
|
|
75
|
+
}
|
|
76
|
+
interface FacetInfo {
|
|
77
|
+
readonly key: string;
|
|
78
|
+
readonly column: string;
|
|
79
|
+
readonly nullable: boolean;
|
|
80
|
+
/** Allowed values when the column is an enum or CHECK union. */
|
|
81
|
+
readonly values?: readonly string[];
|
|
82
|
+
}
|
|
83
|
+
/** Rows per facet value, keyed by facet and then by value (`UNSET` for empty). */
|
|
84
|
+
type FacetCounts<F extends string> = { readonly [K in F]: Readonly<Record<string, number>>; };
|
|
85
|
+
/** A page of a list; with `facetCounts: true`, also the counts per facet value. */
|
|
86
|
+
type ListPage<R, F extends string, C extends boolean> = OffsetPage<R> & ([C] extends [true] ? {
|
|
87
|
+
readonly facetCounts: FacetCounts<F>;
|
|
88
|
+
} : [C] extends [false] ? unknown : {
|
|
89
|
+
readonly facetCounts?: FacetCounts<F>;
|
|
90
|
+
});
|
|
91
|
+
interface ListDefinition<M extends AnyModels, T extends TableKey<M>, E, S extends string, F extends string, C extends boolean = false> {
|
|
92
|
+
readonly table: T;
|
|
93
|
+
readonly defaults: ListQuery<S, F>;
|
|
94
|
+
readonly facets: readonly FacetInfo[];
|
|
95
|
+
/** Validates typed input or URL params. Also a Standard Schema (`schema`). */
|
|
96
|
+
parse(input: ListQueryInput<S, F> | ListSearchParams | undefined): ListParseResult<S, F>;
|
|
97
|
+
readonly schema: StandardSchemaV1<ListQueryInput<S, F> | ListSearchParams | undefined, ListQuery<S, F>>;
|
|
98
|
+
/** URL params, leaving out defaults. */
|
|
99
|
+
toSearchParams(query: Partial<ListQuery<S, F>>): URLSearchParams;
|
|
100
|
+
/** `{ parse, serialize }` per URL key, for routers and nuqs (`list.nuqs(createParser)`). */
|
|
101
|
+
readonly parsers: ListParsers<S, F>;
|
|
102
|
+
nuqs<P>(createParser: (spec: ParserSpec<unknown>) => P): { readonly [K in keyof ListParsers<S, F>]: P; };
|
|
103
|
+
/** Repository arguments: `where`, `orderBy`, `page`, `size`, `count`. */
|
|
104
|
+
args(query: ListQuery<S, F>): OffsetPageArgs<M, T>;
|
|
105
|
+
/**
|
|
106
|
+
* Runs the list against a table, merging your `select`, `include`, `where`
|
|
107
|
+
* and `count`. One request, plus one for `facetCounts`, always one wave.
|
|
108
|
+
*/
|
|
109
|
+
run<const A extends ListExtra<M, T> & FindExt<E, M, T>>(db: { readonly [K in T]: RepositoryOf<M, K, E>; }, query: ListQuery<S, F>, extra?: A): AsyncResult<ListPage<Payload<M, T, A>, F, C>>;
|
|
110
|
+
/** OpenAPI 3.1 query parameters. */
|
|
111
|
+
readonly openapi: readonly OpenApiParameter[];
|
|
112
|
+
/** JSON Schema of the typed input, e.g. for MCP tool arguments. */
|
|
113
|
+
readonly jsonSchema: Readonly<Record<string, unknown>>;
|
|
114
|
+
}
|
|
115
|
+
interface ListExtra<M extends AnyModels, T extends keyof M> {
|
|
116
|
+
readonly select?: SelectArg<M, T>;
|
|
117
|
+
readonly include?: IncludeArg<M, T>;
|
|
118
|
+
readonly where?: WhereInput<M, T>;
|
|
119
|
+
/** Overrides the config's `count` for this run. */
|
|
120
|
+
readonly count?: CountMode;
|
|
121
|
+
}
|
|
122
|
+
type ListParsers<S extends string, F extends string> = {
|
|
123
|
+
readonly q: ParserSpec<string>;
|
|
124
|
+
readonly sort: ParserSpec<S>;
|
|
125
|
+
readonly page: ParserSpec<number>;
|
|
126
|
+
readonly size: ParserSpec<number>;
|
|
127
|
+
} & { readonly [K in F]: ParserSpec<readonly string[]>; };
|
|
128
|
+
/**
|
|
129
|
+
* A reusable list endpoint for one table: search, facets, sorts and
|
|
130
|
+
* pagination, validated from URL params or typed input, with URL parsers,
|
|
131
|
+
* OpenAPI parameters and a JSON Schema derived from the same definition.
|
|
132
|
+
*
|
|
133
|
+
* ```ts
|
|
134
|
+
* export const customerList = defineListQuery(sb, 'customers', {
|
|
135
|
+
* search: ['name', 'kvk'],
|
|
136
|
+
* facets: { status: 'status' },
|
|
137
|
+
* sorts: { name: { name: 'asc' }, newest: [{ createdAt: 'desc' }, { id: 'asc' }] },
|
|
138
|
+
* defaultSort: 'newest',
|
|
139
|
+
* });
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
declare function defineListQuery<M extends AnyModels, D, Fn extends AnyFunctions, E, T extends TableKey<M>, const S extends string, const F extends string = never, const C extends boolean = false>(sb: BetterSupabase<M, D, Fn, E>, table: T, config: ListQueryConfig<M, T, S, F, C>): ListDefinition<M, T, E, S, F, C>;
|
|
143
|
+
//#endregion
|
|
144
|
+
export { ListPage as a, ListQuery as c, ListSearchParams as d, OpenApiParameter as f, defineListQuery as h, ListExtra as i, ListQueryConfig as l, UNSET as m, FacetInfo as n, ListParseResult as o, ParserSpec as p, ListDefinition as r, ListParsers as s, FacetCounts as t, ListQueryInput as u };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { p as DbError } from "./result-CTkCZ6JA.js";
|
|
2
|
+
import { Z as QuerySpec } from "./define-e3zI4_4g.js";
|
|
3
|
+
import { i as BrowserAuth, t as AuthSnapshot } from "./index-D4v7sncu.js";
|
|
4
|
+
import { n as TemplateValues } from "./template-mbvlysOo.js";
|
|
5
|
+
import { t as AuthSession } from "./view-D1s0wa0T.js";
|
|
6
|
+
import { a as LiveSource, g as Topic, h as SubscriptionStatus, p as SubscribeOptions, r as LiveCountSeed, u as EventSchemas, v as TopicHandlers, y as TopicMessage } from "./live-DJyZMD6w.js";
|
|
7
|
+
import "./entitlements-Dng-ctuT.js";
|
|
8
|
+
import "./session-C3LxnQ0e.js";
|
|
9
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
10
|
+
import { ReactNode } from "react";
|
|
11
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
12
|
+
import { QueryClient } from "@tanstack/query-core";
|
|
13
|
+
//#region src/react/index.d.ts
|
|
14
|
+
/** The parts of `createBrowser()` the provider needs. */
|
|
15
|
+
interface BrowserLike {
|
|
16
|
+
readonly sb: LiveSource;
|
|
17
|
+
readonly supabase: SupabaseClient;
|
|
18
|
+
readonly auth: BrowserAuth;
|
|
19
|
+
readonly db: object;
|
|
20
|
+
readonly queries: object;
|
|
21
|
+
}
|
|
22
|
+
interface BetterSupabaseProviderProps {
|
|
23
|
+
readonly browser: BrowserLike;
|
|
24
|
+
/** better-supabase queries are removed when the user signs out or changes. */
|
|
25
|
+
readonly queryClient?: QueryClient;
|
|
26
|
+
readonly children?: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/** Provides the browser client to the hooks. */
|
|
29
|
+
declare function BetterSupabaseProvider(props: BetterSupabaseProviderProps): ReactNode;
|
|
30
|
+
/** The session state for UI: `loading`, `signed-out` or `signed-in` with the user and claims. */
|
|
31
|
+
declare function useAuth(): AuthSnapshot;
|
|
32
|
+
declare function useSupabase(): SupabaseClient;
|
|
33
|
+
interface BetterHooks<B extends BrowserLike> {
|
|
34
|
+
/** Repositories bound to the current session. Re-renders when the user changes. */
|
|
35
|
+
readonly useDb: () => B["db"];
|
|
36
|
+
/** TanStack Query option factories: `useQuery(useQueries().customers.findMany())`. */
|
|
37
|
+
readonly useQueries: () => B["queries"];
|
|
38
|
+
readonly useSupabase: () => SupabaseClient;
|
|
39
|
+
readonly useAuth: () => AuthSnapshot;
|
|
40
|
+
/** `useSession()` typed by the browser's `sb.claims(schema)` and `sb.userMetadata(schema)`. */
|
|
41
|
+
readonly useSession: () => AuthSession<ClaimsOf<B>, ProfileOf<B>>;
|
|
42
|
+
}
|
|
43
|
+
/** The claims type of a browser's `sb.claims(schema)`, `unknown` without one. */
|
|
44
|
+
type ClaimsOf<B extends BrowserLike> = B["sb"] extends {
|
|
45
|
+
readonly claimsSchema: StandardSchemaV1<unknown, infer C> | undefined;
|
|
46
|
+
} ? C : unknown;
|
|
47
|
+
/** The profile type of a browser's `sb.userMetadata(schema)`, `unknown` without one. */
|
|
48
|
+
type ProfileOf<B extends BrowserLike> = B["sb"] extends {
|
|
49
|
+
readonly userMetadataSchema: StandardSchemaV1<unknown, infer P> | undefined;
|
|
50
|
+
} ? P : unknown;
|
|
51
|
+
/**
|
|
52
|
+
* Hooks typed for your schema.
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* export const { useDb, useQueries, useAuth } = createHooks<typeof browser>();
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function createHooks<B extends BrowserLike>(): BetterHooks<B>;
|
|
59
|
+
interface BroadcastOptions extends Omit<SubscribeOptions, "onStatus"> {
|
|
60
|
+
/**
|
|
61
|
+
* Refetch after each message: table keys (every query that read one of
|
|
62
|
+
* them), or a function returning query keys. Needs `queryClient` on the
|
|
63
|
+
* provider.
|
|
64
|
+
*/
|
|
65
|
+
readonly invalidate?: readonly string[] | ((message: TopicMessage) => readonly (readonly unknown[])[]);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Subscribes to a topic while mounted. Pass `null` values to pause. It
|
|
69
|
+
* resubscribes when the topic or the signed-in user changes.
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* useBroadcast(customersTopic, orgId ? { orgId } : null, {}, { invalidate: ['customers'] });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare function useBroadcast<P extends string, E extends EventSchemas>(topic: Topic<P, E>, values: TemplateValues<P> | null | undefined, handlers?: TopicHandlers<E>, options?: BroadcastOptions): SubscriptionStatus;
|
|
76
|
+
interface LiveQueryHookOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Tenant for tenant-scoped tables. Defaults to the `config.claims.tenant`
|
|
79
|
+
* claim (`tenant_id`, top-level or in `app_metadata`).
|
|
80
|
+
*/
|
|
81
|
+
readonly tenant?: string;
|
|
82
|
+
/** Defaults to 100 ms. */
|
|
83
|
+
readonly debounceMs?: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Keeps a query fresh: invalidates every cached query that read a table the
|
|
87
|
+
* spec touches whenever one of them changes. Pass `null` to pause. It
|
|
88
|
+
* resubscribes when the spec, tenant or user changes.
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* const spec = sb.spec.customers.findMany({ include: { notes: true } });
|
|
92
|
+
* const { data } = useQuery(q.$spec(spec));
|
|
93
|
+
* useLiveQuery(spec);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function useLiveQuery(spec: QuerySpec | null | undefined, options?: LiveQueryHookOptions): SubscriptionStatus;
|
|
97
|
+
interface LiveCountHookOptions extends LiveQueryHookOptions {
|
|
98
|
+
/** The count to show before the first fetch, e.g. from the server. */
|
|
99
|
+
readonly initial?: number;
|
|
100
|
+
}
|
|
101
|
+
interface LiveCount {
|
|
102
|
+
/** `undefined` until the first count arrives. */
|
|
103
|
+
readonly count: number | undefined;
|
|
104
|
+
readonly status: SubscriptionStatus;
|
|
105
|
+
/** The last failed refetch; the previous count stays. */
|
|
106
|
+
readonly error: DbError | undefined;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A count that stays current: refetches only the `count` spec (a HEAD
|
|
110
|
+
* request) after each debounced change to a table it reads, and after the
|
|
111
|
+
* channel rejoins. Takes a spec or a `next.liveCount()` seed; pass `null` to
|
|
112
|
+
* pause. Doesn't need a `QueryClient`.
|
|
113
|
+
*
|
|
114
|
+
* ```tsx
|
|
115
|
+
* const { count } = useLiveCount(seed); // seed = await next.liveCount(spec)
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
declare function useLiveCount(source: QuerySpec<string, "count", number> | LiveCountSeed | null | undefined, options?: LiveCountHookOptions): LiveCount;
|
|
119
|
+
//#endregion
|
|
120
|
+
export { BrowserLike as a, LiveCountHookOptions as c, createHooks as d, useAuth as f, useSupabase as g, useLiveQuery as h, BroadcastOptions as i, LiveQueryHookOptions as l, useLiveCount as m, BetterSupabaseProvider as n, ClaimsOf as o, useBroadcast as p, BetterSupabaseProviderProps as r, LiveCount as s, BetterHooks as t, ProfileOf as u };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { m as StoredSession } from "./resolve-CjHILk2w.js";
|
|
2
|
+
import "./view-D1s0wa0T.js";
|
|
3
|
+
import "./entitlements-Dng-ctuT.js";
|
|
4
|
+
//#region src/auth/refresh.d.ts
|
|
5
|
+
interface RefreshOptions {
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly publishableKey: string;
|
|
8
|
+
/**
|
|
9
|
+
* Sends `Sb-Forwarded-For: ip` with the secret key, so Auth rate-limits the
|
|
10
|
+
* refresh by the user's IP (when IP forwarding is on for the project).
|
|
11
|
+
*/
|
|
12
|
+
readonly forwardedFor?: {
|
|
13
|
+
readonly ip: string;
|
|
14
|
+
readonly secretKey: string;
|
|
15
|
+
};
|
|
16
|
+
readonly fetch?: typeof fetch;
|
|
17
|
+
readonly now?: () => number;
|
|
18
|
+
}
|
|
19
|
+
type RefreshOutcome = {
|
|
20
|
+
readonly ok: true;
|
|
21
|
+
readonly session: StoredSession;
|
|
22
|
+
/** Served from a concurrent or just-finished refresh of the same token. */
|
|
23
|
+
readonly shared?: boolean;
|
|
24
|
+
} | {
|
|
25
|
+
readonly ok: false;
|
|
26
|
+
/** `rejected`: the refresh token is dead, sign the user out. `network`: keep the session and retry later. */
|
|
27
|
+
readonly reason: "rejected" | "network";
|
|
28
|
+
readonly status?: number;
|
|
29
|
+
readonly message: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Exchanges a refresh token for a new session. Concurrent calls with the same
|
|
33
|
+
* token share one request, and a successful result is reused for a short
|
|
34
|
+
* window so parallel requests carrying the old cookie converge on one session.
|
|
35
|
+
*/
|
|
36
|
+
declare function refreshSession(refreshToken: string, options: RefreshOptions): Promise<RefreshOutcome>;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { RefreshOutcome as n, refreshSession as r, RefreshOptions as t };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { A as SchemaMeta } from "./types-C83v5SQz.js";
|
|
2
|
+
import { a as EventHub, s as MutationNotice } from "./events-DOt3nSO-.js";
|
|
3
|
+
import { l as MutationKind } from "./plugin-C4TR9J0Z.js";
|
|
4
|
+
//#region src/events/index.d.ts
|
|
5
|
+
/** A CloudEvents 1.0 event. Extension attributes are lowercase alphanumerics. */
|
|
6
|
+
interface CloudEvent<T = unknown> {
|
|
7
|
+
readonly specversion: "1.0";
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly source: string;
|
|
10
|
+
readonly type: string;
|
|
11
|
+
readonly subject?: string;
|
|
12
|
+
readonly time?: string;
|
|
13
|
+
readonly datacontenttype?: string;
|
|
14
|
+
readonly dataschema?: string;
|
|
15
|
+
readonly data?: T;
|
|
16
|
+
readonly [extension: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
declare const ROW_EVENT_TYPES: { readonly [K in MutationKind]: string; };
|
|
19
|
+
interface RowEventData {
|
|
20
|
+
readonly table: string;
|
|
21
|
+
readonly row: Readonly<Record<string, unknown>>;
|
|
22
|
+
}
|
|
23
|
+
interface CloudEventOptions {
|
|
24
|
+
/** URI-reference of the producer, e.g. `https://crm.example.com` or `/crm`. */
|
|
25
|
+
readonly source: string;
|
|
26
|
+
/** Replaces the `dev.better-supabase` type prefix. */
|
|
27
|
+
readonly typePrefix?: string;
|
|
28
|
+
readonly id?: () => string;
|
|
29
|
+
readonly now?: () => Date;
|
|
30
|
+
}
|
|
31
|
+
/** Sends events somewhere: a queue, a bus, an outbox table, an HTTP endpoint. */
|
|
32
|
+
interface EventSink {
|
|
33
|
+
send(events: readonly CloudEvent[]): void | Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One CloudEvent per mutated row: `dev.better-supabase.row.created` with the
|
|
37
|
+
* app-cased row as `data`, the primary key as `subject`, the tenant as
|
|
38
|
+
* `partitionkey` and the actor as `actorid`.
|
|
39
|
+
*/
|
|
40
|
+
declare function toCloudEvents(notice: MutationNotice, options: CloudEventOptions & {
|
|
41
|
+
readonly meta?: SchemaMeta;
|
|
42
|
+
}): CloudEvent<RowEventData>[];
|
|
43
|
+
interface ForwardOptions extends CloudEventOptions {
|
|
44
|
+
/** Only forward these tables or kinds. */
|
|
45
|
+
readonly filter?: (notice: MutationNotice) => boolean;
|
|
46
|
+
/** Sink failures never fail the mutation. Defaults to the `Logger`. */
|
|
47
|
+
readonly onError?: (error: unknown, events: readonly CloudEvent[]) => void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sends a CloudEvent for every mutation to `sink`. Returns a function that
|
|
51
|
+
* stops forwarding. Use an outbox (SQL kit) when events must not be lost.
|
|
52
|
+
*/
|
|
53
|
+
declare function forwardMutations(sb: {
|
|
54
|
+
readonly events: EventHub;
|
|
55
|
+
readonly meta: SchemaMeta;
|
|
56
|
+
}, sink: EventSink, options: ForwardOptions): () => void;
|
|
57
|
+
type HttpMode = "structured" | "binary" | "batch";
|
|
58
|
+
/** The HTTP protocol binding: headers and body for one event (or a batch). */
|
|
59
|
+
declare function toHttp(events: CloudEvent | readonly CloudEvent[], mode?: HttpMode): {
|
|
60
|
+
headers: Record<string, string>;
|
|
61
|
+
body: string;
|
|
62
|
+
}[];
|
|
63
|
+
declare function isCloudEvent(value: unknown): value is CloudEvent;
|
|
64
|
+
/** Reads CloudEvents from a request in any of the three HTTP modes. */
|
|
65
|
+
declare function fromHttp(request: Request): Promise<CloudEvent[]>;
|
|
66
|
+
interface HttpSinkOptions {
|
|
67
|
+
readonly mode?: HttpMode;
|
|
68
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
69
|
+
readonly fetch?: typeof fetch;
|
|
70
|
+
}
|
|
71
|
+
/** POSTs events to `url`. Non-2xx responses reject. */
|
|
72
|
+
declare function httpSink(url: string | URL, options?: HttpSinkOptions): EventSink;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { HttpMode as a, RowEventData as c, httpSink as d, isCloudEvent as f, ForwardOptions as i, forwardMutations as l, toHttp as m, CloudEventOptions as n, HttpSinkOptions as o, toCloudEvents as p, EventSink as r, ROW_EVENT_TYPES as s, CloudEvent as t, fromHttp as u };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { n as AnyModels, t as AnyFunctions } from "./types-C83v5SQz.js";
|
|
2
|
+
import { t as BetterSupabase, y as Db } from "./define-e3zI4_4g.js";
|
|
3
|
+
import { c as PublicEnv } from "./index-Dy6kuF0P.js";
|
|
4
|
+
import { i as Queries } from "./index-K-3WM2Hp.js";
|
|
5
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
6
|
+
//#region src/client/index.d.ts
|
|
7
|
+
interface BrowserOptions {
|
|
8
|
+
/** URL and publishable key. Not needed when `client` is given. */
|
|
9
|
+
readonly env?: PublicEnv;
|
|
10
|
+
/** Bring your own supabase-js client (React Native, custom storage). */
|
|
11
|
+
readonly client?: SupabaseClient;
|
|
12
|
+
/**
|
|
13
|
+
* `cookies` (default) shares the session with the server through
|
|
14
|
+
* `@supabase/ssr`; `local` keeps it in localStorage for SPAs without a server.
|
|
15
|
+
*/
|
|
16
|
+
readonly storage?: "cookies" | "local";
|
|
17
|
+
}
|
|
18
|
+
interface AuthUser {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly email?: string;
|
|
21
|
+
readonly role?: string;
|
|
22
|
+
}
|
|
23
|
+
/** What the UI needs to know. Claims are decoded, not verified: RLS enforces access. */
|
|
24
|
+
type AuthSnapshot = {
|
|
25
|
+
readonly status: "loading";
|
|
26
|
+
readonly user: null;
|
|
27
|
+
readonly claims: null;
|
|
28
|
+
} | {
|
|
29
|
+
readonly status: "signed-out";
|
|
30
|
+
readonly user: null;
|
|
31
|
+
readonly claims: null;
|
|
32
|
+
} | {
|
|
33
|
+
readonly status: "signed-in";
|
|
34
|
+
readonly user: AuthUser;
|
|
35
|
+
readonly claims: Readonly<Record<string, unknown>>;
|
|
36
|
+
};
|
|
37
|
+
interface BrowserAuth {
|
|
38
|
+
readonly current: () => AuthSnapshot;
|
|
39
|
+
/** `useSyncExternalStore`-compatible. */
|
|
40
|
+
readonly subscribe: (listener: () => void) => () => void;
|
|
41
|
+
}
|
|
42
|
+
interface BetterBrowser<M extends AnyModels, F extends AnyFunctions, E, C = unknown, P = unknown> {
|
|
43
|
+
/** The definition the browser was created from (schema metadata, specs, live queries). */
|
|
44
|
+
readonly sb: BetterSupabase<M, unknown, F, E, C, P>;
|
|
45
|
+
readonly supabase: SupabaseClient;
|
|
46
|
+
/** Repositories with the current session's actor and claims. */
|
|
47
|
+
readonly db: Db<M, F, E, SupabaseClient>;
|
|
48
|
+
/** TanStack Query option factories over `db`. */
|
|
49
|
+
readonly queries: Queries<M, E, F>;
|
|
50
|
+
readonly auth: BrowserAuth;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The browser side: a supabase-js client, repositories that follow the
|
|
54
|
+
* session, TanStack Query options and an auth store for UI state.
|
|
55
|
+
*
|
|
56
|
+
* ```ts
|
|
57
|
+
* export const browser = createBrowser(sb, { env: { url, publishableKey } });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function createBrowser<M extends AnyModels, D, F extends AnyFunctions, E, C = unknown, P = unknown>(sb: BetterSupabase<M, D, F, E, C, P>, options?: BrowserOptions): BetterBrowser<M, F, E, C, P>;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { BrowserOptions as a, BrowserAuth as i, AuthUser as n, createBrowser as o, BetterBrowser as r, AuthSnapshot as t };
|