tinbase 0.10.0 → 0.10.2
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 +10 -9
- package/dist/admin/api.d.ts +62 -1
- package/dist/admin/api.js +221 -10
- package/dist/admin/api.js.map +1 -1
- package/dist/admin/ui.d.ts +1 -1
- package/dist/admin/ui.js +1548 -16
- package/dist/admin/ui.js.map +1 -1
- package/dist/auth/handler.d.ts +52 -5
- package/dist/auth/handler.js +147 -36
- package/dist/auth/handler.js.map +1 -1
- package/dist/auth/inbox.d.ts +4 -2
- package/dist/auth/inbox.js +1 -0
- package/dist/auth/inbox.js.map +1 -1
- package/dist/auth/oauth.d.ts +30 -4
- package/dist/auth/oauth.js +22 -6
- package/dist/auth/oauth.js.map +1 -1
- package/dist/auth/password.d.ts +5 -0
- package/dist/auth/password.js +7 -0
- package/dist/auth/password.js.map +1 -1
- package/dist/auth/qr.d.ts +1 -1
- package/dist/auth/qr.js +1 -1
- package/dist/auth/rate-limit.d.ts +33 -0
- package/dist/auth/rate-limit.js +63 -0
- package/dist/auth/rate-limit.js.map +1 -0
- package/dist/auth/redirect.d.ts +20 -0
- package/dist/auth/redirect.js +79 -0
- package/dist/auth/redirect.js.map +1 -0
- package/dist/auth/settings.d.ts +55 -0
- package/dist/auth/settings.js +116 -0
- package/dist/auth/settings.js.map +1 -0
- package/dist/auth/totp.js +1 -1
- package/dist/cli.js +43 -21
- package/dist/cli.js.map +1 -1
- package/dist/cron/service.d.ts +15 -2
- package/dist/cron/service.js +19 -2
- package/dist/cron/service.js.map +1 -1
- package/dist/db/bootstrap.d.ts +13 -6
- package/dist/db/bootstrap.js +26 -5
- package/dist/db/bootstrap.js.map +1 -1
- package/dist/db/database.d.ts +61 -3
- package/dist/db/database.js +72 -9
- package/dist/db/database.js.map +1 -1
- package/dist/db/emulated.d.ts +39 -2
- package/dist/db/emulated.js +39 -23
- package/dist/db/emulated.js.map +1 -1
- package/dist/db/engine.d.ts +19 -5
- package/dist/db/engine.js +4 -2
- package/dist/db/engine.js.map +1 -1
- package/dist/db/inspect.d.ts +6 -1
- package/dist/db/inspect.js +2 -1
- package/dist/db/inspect.js.map +1 -1
- package/dist/db/pglite-engine.d.ts +7 -1
- package/dist/db/pglite-engine.js +7 -1
- package/dist/db/pglite-engine.js.map +1 -1
- package/dist/db/pgmem-engine.d.ts +9 -3
- package/dist/db/pgmem-engine.js +13 -7
- package/dist/db/pgmem-engine.js.map +1 -1
- package/dist/db/schema-diff.d.ts +9 -1
- package/dist/db/schema-diff.js +19 -5
- package/dist/db/schema-diff.js.map +1 -1
- package/dist/db/sql-compat.d.ts +2 -2
- package/dist/db/sql-compat.js +2 -2
- package/dist/functions/deno-shim.d.ts +6 -17
- package/dist/functions/deno-shim.js +42 -10
- package/dist/functions/deno-shim.js.map +1 -1
- package/dist/functions/handler.d.ts +9 -4
- package/dist/functions/handler.js +9 -1
- package/dist/functions/handler.js.map +1 -1
- package/dist/gen-types.d.ts +6 -1
- package/dist/gen-types.js +53 -41
- package/dist/gen-types.js.map +1 -1
- package/dist/index.d.ts +33 -3
- package/dist/index.js +158 -28
- package/dist/index.js.map +1 -1
- package/dist/jwt.d.ts +4 -1
- package/dist/jwt.js +4 -2
- package/dist/jwt.js.map +1 -1
- package/dist/log-buffer.d.ts +7 -1
- package/dist/log-buffer.js +3 -0
- package/dist/log-buffer.js.map +1 -1
- package/dist/net/service.d.ts +35 -6
- package/dist/net/service.js +72 -17
- package/dist/net/service.js.map +1 -1
- package/dist/node/bun-server.d.ts +2 -1
- package/dist/node/bun-server.js +11 -1
- package/dist/node/bun-server.js.map +1 -1
- package/dist/node/bundle-function.d.ts +1 -1
- package/dist/node/bundle-function.js +1 -1
- package/dist/node/config-toml.d.ts +31 -0
- package/dist/node/config-toml.js +186 -0
- package/dist/node/config-toml.js.map +1 -0
- package/dist/node/db-diff.d.ts +13 -1
- package/dist/node/db-diff.js +3 -1
- package/dist/node/db-diff.js.map +1 -1
- package/dist/node/fs-driver.d.ts +16 -1
- package/dist/node/fs-driver.js +20 -1
- package/dist/node/fs-driver.js.map +1 -1
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/load-config.d.ts +80 -0
- package/dist/node/load-config.js +230 -0
- package/dist/node/load-config.js.map +1 -0
- package/dist/node/load-functions.d.ts +17 -2
- package/dist/node/load-functions.js +17 -4
- package/dist/node/load-functions.js.map +1 -1
- package/dist/node/native/engine.d.ts +7 -0
- package/dist/node/native/engine.js +58 -7
- package/dist/node/native/engine.js.map +1 -1
- package/dist/node/native/wire.d.ts +15 -1
- package/dist/node/native/wire.js +32 -10
- package/dist/node/native/wire.js.map +1 -1
- package/dist/node/project.d.ts +15 -1
- package/dist/node/project.js +19 -7
- package/dist/node/project.js.map +1 -1
- package/dist/node/server-shared.d.ts +4 -1
- package/dist/node/server.d.ts +11 -0
- package/dist/node/server.js +11 -0
- package/dist/node/server.js.map +1 -1
- package/dist/node/ws.d.ts +26 -1
- package/dist/node/ws.js +26 -3
- package/dist/node/ws.js.map +1 -1
- package/dist/realtime/engine.d.ts +6 -0
- package/dist/realtime/engine.js +45 -34
- package/dist/realtime/engine.js.map +1 -1
- package/dist/rest/build.d.ts +37 -1
- package/dist/rest/build.js +48 -8
- package/dist/rest/build.js.map +1 -1
- package/dist/rest/errors.d.ts +8 -0
- package/dist/rest/errors.js +12 -1
- package/dist/rest/errors.js.map +1 -1
- package/dist/rest/handler.d.ts +17 -1
- package/dist/rest/handler.js +48 -5
- package/dist/rest/handler.js.map +1 -1
- package/dist/rest/parse.d.ts +24 -1
- package/dist/rest/parse.js +7 -1
- package/dist/rest/parse.js.map +1 -1
- package/dist/retention/service.d.ts +3 -0
- package/dist/retention/service.js +3 -1
- package/dist/retention/service.js.map +1 -1
- package/dist/security.d.ts +22 -0
- package/dist/security.js +47 -0
- package/dist/security.js.map +1 -0
- package/dist/storage/driver.d.ts +8 -1
- package/dist/storage/driver.js +4 -1
- package/dist/storage/driver.js.map +1 -1
- package/dist/storage/handler.d.ts +10 -1
- package/dist/storage/handler.js +93 -12
- package/dist/storage/handler.js.map +1 -1
- package/dist/types.d.ts +77 -1
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/dist/webhooks/service.d.ts +25 -2
- package/dist/webhooks/service.js +21 -3
- package/dist/webhooks/service.js.map +1 -1
- package/package.json +5 -3
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public configuration and shared types for the tinbase package. {@link BackendConfig}
|
|
3
|
+
* is the primary input to {@link import('./index.js').createBackend}; the rest are
|
|
4
|
+
* the small structural types that config and handlers exchange.
|
|
5
|
+
*/
|
|
1
6
|
import type { JwtClaims } from './jwt.js';
|
|
7
|
+
/** A single SQL migration, in Supabase CLI form (one file under supabase/migrations). */
|
|
2
8
|
export interface MigrationFile {
|
|
3
9
|
/** e.g. "20240101120000_create_posts" (no extension) */
|
|
4
10
|
name: string;
|
|
11
|
+
/** Raw SQL applied in one statement batch. */
|
|
5
12
|
sql: string;
|
|
6
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for {@link import('./index.js').createBackend}. Every field is
|
|
16
|
+
* optional; an empty config boots an in-memory PGlite backend on the Supabase
|
|
17
|
+
* local-dev defaults. The CLI derives this object from supabase/config.toml plus
|
|
18
|
+
* the project's migrations/functions/seed.
|
|
19
|
+
*/
|
|
7
20
|
export interface BackendConfig {
|
|
8
21
|
/**
|
|
9
22
|
* PGlite data directory. Node: a filesystem path. Browser: "idb://name" or
|
|
@@ -24,16 +37,43 @@ export interface BackendConfig {
|
|
|
24
37
|
databaseUrl?: string;
|
|
25
38
|
/** Secret used to sign/verify every JWT. Defaults to the Supabase local-dev secret. */
|
|
26
39
|
jwtSecret?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Schemas exposed through the Data API (/rest/v1) for anon/authenticated -
|
|
42
|
+
* PostgREST's db-schemas. Requests profiling into any other schema get a 406
|
|
43
|
+
* unless made with the service_role key. Default: ['public'].
|
|
44
|
+
*/
|
|
45
|
+
dbSchemas?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* Auth setting defaults (the committed baseline, e.g. read from
|
|
48
|
+
* supabase/config.toml's [auth] section). Live studio edits, persisted in the
|
|
49
|
+
* auth.config table, are layered on top. Any omitted key falls back to the
|
|
50
|
+
* built-in default.
|
|
51
|
+
*/
|
|
52
|
+
authSettings?: Partial<import('./auth/settings.js').AuthSettings>;
|
|
27
53
|
/**
|
|
28
54
|
* Key used to encrypt Vault secrets at rest (pgcrypto). Held only in a session
|
|
29
55
|
* GUC, never stored in the database. Defaults to a value derived from
|
|
30
|
-
* jwtSecret
|
|
56
|
+
* jwtSecret. Required when binding to a network-exposed host (see `host`);
|
|
57
|
+
* always set a dedicated key in production.
|
|
31
58
|
*/
|
|
32
59
|
vaultKey?: string;
|
|
33
60
|
/** External URL of this backend, used as JWT issuer. */
|
|
34
61
|
siteUrl?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Host the server is bound to. Used only to decide whether the backend is
|
|
64
|
+
* network-exposed: a non-loopback host turns the default JWT secret and the
|
|
65
|
+
* derived vault key from warnings into hard startup errors. Default: treated
|
|
66
|
+
* as loopback (local dev) when omitted.
|
|
67
|
+
*/
|
|
68
|
+
host?: string;
|
|
35
69
|
/** Access token lifetime in seconds (default 3600). */
|
|
36
70
|
jwtExpiry?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Redirect targets allowed beyond the site URL's own origin (GoTrue's
|
|
73
|
+
* URI_ALLOW_LIST). Entries may use `*`/`**` globs. A `redirect_to` matching
|
|
74
|
+
* neither the site origin nor an entry falls back to the site URL.
|
|
75
|
+
*/
|
|
76
|
+
uriAllowList?: string[];
|
|
37
77
|
/** Migrations to apply on boot (Supabase CLI convention: sorted by name). */
|
|
38
78
|
migrations?: MigrationFile[];
|
|
39
79
|
/** SQL from supabase/seed.sql, applied once after the first migration run. */
|
|
@@ -66,17 +106,42 @@ export interface BackendConfig {
|
|
|
66
106
|
logMailBody?: boolean;
|
|
67
107
|
/** Data-retention windows for the background cleanup sweep. */
|
|
68
108
|
retention?: import('./retention/service.js').RetentionConfig;
|
|
109
|
+
/** Max rows a single REST read returns (PostgREST db-max-rows; config.toml api.max_rows). Unlimited if unset. */
|
|
110
|
+
maxRows?: number;
|
|
111
|
+
/** Default per-bucket file size limit in bytes (config.toml storage.file_size_limit). */
|
|
112
|
+
storageFileSizeLimit?: number;
|
|
113
|
+
/** Buckets to create at boot if absent (config.toml storage.buckets.*). */
|
|
114
|
+
buckets?: BucketSeed[];
|
|
115
|
+
/** Force sign-out after this many seconds regardless of activity (config.toml auth.sessions.timebox). */
|
|
116
|
+
sessionTimeboxSeconds?: number;
|
|
117
|
+
/** Sign out after this many seconds of inactivity (config.toml auth.sessions.inactivity_timeout). */
|
|
118
|
+
sessionInactivitySeconds?: number;
|
|
119
|
+
/** Per-endpoint auth rate-limit rules (config.toml auth.rate_limit.*). Defaults applied when unset. */
|
|
120
|
+
authRateLimits?: Record<string, import('./auth/rate-limit.js').RateLimitRule>;
|
|
121
|
+
/** Mount the auth service. Default true; config.toml auth.enabled = false turns /auth/v1 off. */
|
|
122
|
+
authEnabled?: boolean;
|
|
69
123
|
}
|
|
124
|
+
/** A rendered outbound email (OTP code, magic link, recovery, etc.). */
|
|
70
125
|
export interface MailMessage {
|
|
71
126
|
to: string;
|
|
72
127
|
subject: string;
|
|
128
|
+
/** Plain-text body. Carries OTP codes / magic links, so it is not logged by default. */
|
|
73
129
|
text: string;
|
|
74
130
|
}
|
|
75
131
|
/** Pluggable mail transport. Default implementation logs to the console. */
|
|
76
132
|
export interface Mailer {
|
|
77
133
|
send(msg: MailMessage): Promise<void>;
|
|
78
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* The public Supabase local-dev JWT secret. Used when no `jwtSecret` is set so
|
|
137
|
+
* default keys match a stock `supabase start`.
|
|
138
|
+
*
|
|
139
|
+
* SECURITY: forgeable by anyone (it is public). Startup refuses to bind to a
|
|
140
|
+
* network-exposed host while still using it - see {@link import('./security.js').assertSecretsSafe}.
|
|
141
|
+
*/
|
|
79
142
|
export declare const DEFAULT_JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long";
|
|
143
|
+
/** tinbase package version, surfaced in health/root responses. Keep in sync with package.json. */
|
|
144
|
+
export declare const TINBASE_VERSION = "0.9.0";
|
|
80
145
|
/** Per-request execution context derived from apikey/Authorization headers. */
|
|
81
146
|
export interface RequestContext {
|
|
82
147
|
/** Postgres role to SET LOCAL: anon | authenticated | service_role */
|
|
@@ -84,12 +149,23 @@ export interface RequestContext {
|
|
|
84
149
|
/** Verified JWT claims (published to request.jwt.claims for RLS). */
|
|
85
150
|
claims: JwtClaims | null;
|
|
86
151
|
}
|
|
152
|
+
/** A bucket to create at boot (from config.toml [storage.buckets.<id>]). */
|
|
153
|
+
export interface BucketSeed {
|
|
154
|
+
id: string;
|
|
155
|
+
public: boolean;
|
|
156
|
+
/** Per-bucket byte limit, or null for none. */
|
|
157
|
+
fileSizeLimit: number | null;
|
|
158
|
+
/** Allowed MIME types, or null for any. */
|
|
159
|
+
allowedMimeTypes: string[] | null;
|
|
160
|
+
}
|
|
161
|
+
/** Pluggable object-storage backend for bucket bytes (in-memory, fs, etc.). */
|
|
87
162
|
export interface StorageDriver {
|
|
88
163
|
put(key: string, data: Uint8Array): Promise<void>;
|
|
89
164
|
get(key: string): Promise<Uint8Array | null>;
|
|
90
165
|
delete(key: string): Promise<void>;
|
|
91
166
|
deleteMany(keys: string[]): Promise<void>;
|
|
92
167
|
}
|
|
168
|
+
/** Error carrying an HTTP status + JSON body, thrown by handlers and rendered as-is to the client. */
|
|
93
169
|
export declare class ApiError extends Error {
|
|
94
170
|
status: number;
|
|
95
171
|
body: Record<string, unknown>;
|
package/dist/types.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public Supabase local-dev JWT secret. Used when no `jwtSecret` is set so
|
|
3
|
+
* default keys match a stock `supabase start`.
|
|
4
|
+
*
|
|
5
|
+
* SECURITY: forgeable by anyone (it is public). Startup refuses to bind to a
|
|
6
|
+
* network-exposed host while still using it - see {@link import('./security.js').assertSecretsSafe}.
|
|
7
|
+
*/
|
|
1
8
|
export const DEFAULT_JWT_SECRET = 'super-secret-jwt-token-with-at-least-32-characters-long';
|
|
9
|
+
/** tinbase package version, surfaced in health/root responses. Keep in sync with package.json. */
|
|
10
|
+
export const TINBASE_VERSION = '0.9.0';
|
|
11
|
+
/** Error carrying an HTTP status + JSON body, thrown by handlers and rendered as-is to the client. */
|
|
2
12
|
export class ApiError extends Error {
|
|
3
13
|
status;
|
|
4
14
|
body;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2IA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,yDAAyD,CAAA;AAE3F,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA;AA4BtC,sGAAsG;AACtG,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IACA;IAFT,YACS,MAAc,EACd,IAA6B;QAEpC,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QAHtE,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAyB;IAGtC,CAAC;CACF"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Database webhooks
|
|
2
|
+
* Database webhooks - fire an HTTP request when rows change, the tinbase
|
|
3
3
|
* equivalent of Supabase Database Webhooks (which use pg_net under the hood).
|
|
4
4
|
* Built on the existing CDC pipeline (triggers + pg_notify), so it needs no C
|
|
5
5
|
* extension and works on both engines. The POST body matches Supabase's
|
|
6
6
|
* webhook payload exactly: { type, table, schema, record, old_record }.
|
|
7
7
|
*/
|
|
8
8
|
import type { CdcEvent, Database } from '../db/database.js';
|
|
9
|
+
/** A registered database webhook: which changes to watch and where to POST them. */
|
|
9
10
|
export interface WebhookConfig {
|
|
10
11
|
/** table to watch */
|
|
11
12
|
table: string;
|
|
13
|
+
/** schema of the watched table; defaults to 'public' */
|
|
12
14
|
schema?: string;
|
|
13
15
|
/** which events fire the hook; default all */
|
|
14
16
|
events?: ('INSERT' | 'UPDATE' | 'DELETE')[];
|
|
@@ -21,26 +23,47 @@ export interface WebhookConfig {
|
|
|
21
23
|
/** request timeout ms (default 5000) */
|
|
22
24
|
timeoutMs?: number;
|
|
23
25
|
}
|
|
26
|
+
/** Result of one webhook delivery attempt, passed to the optional `onDelivery` callback. */
|
|
24
27
|
export interface WebhookDelivery {
|
|
25
28
|
webhook: WebhookConfig;
|
|
29
|
+
/** the CDC event that triggered this delivery */
|
|
26
30
|
event: CdcEvent;
|
|
31
|
+
/** HTTP response status; null when the request never got a reply (error/blocked) */
|
|
27
32
|
status: number | null;
|
|
33
|
+
/** true when the response was 2xx */
|
|
28
34
|
ok: boolean;
|
|
35
|
+
/** failure reason (network error, blocked SSRF target); undefined on success */
|
|
29
36
|
error?: string;
|
|
30
37
|
}
|
|
38
|
+
/** Watches the CDC stream and POSTs matching row changes to registered webhooks. */
|
|
31
39
|
export declare class WebhooksService {
|
|
32
40
|
private db;
|
|
33
41
|
private fetchImpl;
|
|
34
42
|
private onDelivery?;
|
|
43
|
+
/**
|
|
44
|
+
* Block delivery to loopback/private/link-local targets (SSRF guard). Off by
|
|
45
|
+
* default so local dev can point a webhook at a local edge function, as
|
|
46
|
+
* `supabase start` does; the backend turns it on when network-exposed.
|
|
47
|
+
*/
|
|
48
|
+
private restrictTargets;
|
|
35
49
|
private hooks;
|
|
36
50
|
private stop;
|
|
37
51
|
private started;
|
|
38
|
-
constructor(db: Database, fetchImpl?: typeof fetch, onDelivery?: ((d: WebhookDelivery) => void) | undefined
|
|
52
|
+
constructor(db: Database, fetchImpl?: typeof fetch, onDelivery?: ((d: WebhookDelivery) => void) | undefined,
|
|
53
|
+
/**
|
|
54
|
+
* Block delivery to loopback/private/link-local targets (SSRF guard). Off by
|
|
55
|
+
* default so local dev can point a webhook at a local edge function, as
|
|
56
|
+
* `supabase start` does; the backend turns it on when network-exposed.
|
|
57
|
+
*/
|
|
58
|
+
restrictTargets?: boolean);
|
|
59
|
+
/** All currently registered webhooks. */
|
|
39
60
|
list(): WebhookConfig[];
|
|
40
61
|
/** Register a webhook (ensures the CDC trigger + subscription are live). */
|
|
41
62
|
register(hook: WebhookConfig): Promise<void>;
|
|
63
|
+
/** Register an initial set of webhooks and start dispatching if any exist. */
|
|
42
64
|
start(initial?: WebhookConfig[]): Promise<void>;
|
|
43
65
|
private ensureStarted;
|
|
66
|
+
/** Unsubscribe from the CDC stream; registered hooks are retained. */
|
|
44
67
|
stopService(): void;
|
|
45
68
|
private dispatch;
|
|
46
69
|
private deliver;
|
package/dist/webhooks/service.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
import { guardedFetch } from '../net/service.js';
|
|
2
|
+
/** Watches the CDC stream and POSTs matching row changes to registered webhooks. */
|
|
1
3
|
export class WebhooksService {
|
|
2
4
|
db;
|
|
3
5
|
fetchImpl;
|
|
4
6
|
onDelivery;
|
|
7
|
+
restrictTargets;
|
|
5
8
|
hooks = [];
|
|
6
9
|
stop = null;
|
|
7
10
|
started = false;
|
|
8
|
-
constructor(db, fetchImpl = fetch, onDelivery
|
|
11
|
+
constructor(db, fetchImpl = fetch, onDelivery,
|
|
12
|
+
/**
|
|
13
|
+
* Block delivery to loopback/private/link-local targets (SSRF guard). Off by
|
|
14
|
+
* default so local dev can point a webhook at a local edge function, as
|
|
15
|
+
* `supabase start` does; the backend turns it on when network-exposed.
|
|
16
|
+
*/
|
|
17
|
+
restrictTargets = false) {
|
|
9
18
|
this.db = db;
|
|
10
19
|
this.fetchImpl = fetchImpl;
|
|
11
20
|
this.onDelivery = onDelivery;
|
|
21
|
+
this.restrictTargets = restrictTargets;
|
|
12
22
|
}
|
|
23
|
+
/** All currently registered webhooks. */
|
|
13
24
|
list() {
|
|
14
25
|
return [...this.hooks];
|
|
15
26
|
}
|
|
@@ -19,6 +30,7 @@ export class WebhooksService {
|
|
|
19
30
|
await this.db.ensureCdcTrigger(hook.schema ?? 'public', hook.table).catch(() => { });
|
|
20
31
|
await this.ensureStarted();
|
|
21
32
|
}
|
|
33
|
+
/** Register an initial set of webhooks and start dispatching if any exist. */
|
|
22
34
|
async start(initial = []) {
|
|
23
35
|
for (const h of initial) {
|
|
24
36
|
this.hooks.push(h);
|
|
@@ -33,6 +45,7 @@ export class WebhooksService {
|
|
|
33
45
|
this.started = true;
|
|
34
46
|
this.stop = await this.db.onCdcEvent((e) => this.dispatch(e));
|
|
35
47
|
}
|
|
48
|
+
/** Unsubscribe from the CDC stream; registered hooks are retained. */
|
|
36
49
|
stopService() {
|
|
37
50
|
this.stop?.();
|
|
38
51
|
this.stop = null;
|
|
@@ -61,12 +74,17 @@ export class WebhooksService {
|
|
|
61
74
|
const controller = new AbortController();
|
|
62
75
|
const timer = setTimeout(() => controller.abort(), hook.timeoutMs ?? 5000);
|
|
63
76
|
try {
|
|
64
|
-
const
|
|
77
|
+
const init = {
|
|
65
78
|
method: hook.method ?? 'POST',
|
|
66
79
|
headers: { 'content-type': 'application/json', ...(hook.headers ?? {}) },
|
|
67
80
|
body: JSON.stringify(payload),
|
|
68
81
|
signal: controller.signal,
|
|
69
|
-
}
|
|
82
|
+
};
|
|
83
|
+
// When network-exposed, apply the SSRF guard (incl. redirect re-validation);
|
|
84
|
+
// on loopback dev, deliver directly so localhost webhooks still work.
|
|
85
|
+
const res = this.restrictTargets
|
|
86
|
+
? await guardedFetch(this.fetchImpl, hook.url, init)
|
|
87
|
+
: await this.fetchImpl(hook.url, init);
|
|
70
88
|
this.onDelivery?.({ webhook: hook, event, status: res.status, ok: res.ok });
|
|
71
89
|
}
|
|
72
90
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/webhooks/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/webhooks/service.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAiChD,oFAAoF;AACpF,MAAM,OAAO,eAAe;IAMhB;IACA;IACA;IAMA;IAbF,KAAK,GAAoB,EAAE,CAAA;IAC3B,IAAI,GAAwB,IAAI,CAAA;IAChC,OAAO,GAAG,KAAK,CAAA;IAEvB,YACU,EAAY,EACZ,YAA0B,KAAK,EAC/B,UAAyC;IACjD;;;;OAIG;IACK,kBAAkB,KAAK;QARvB,OAAE,GAAF,EAAE,CAAU;QACZ,cAAS,GAAT,SAAS,CAAsB;QAC/B,eAAU,GAAV,UAAU,CAA+B;QAMzC,oBAAe,GAAf,eAAe,CAAQ;IAC9B,CAAC;IAEJ,yCAAyC;IACzC,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,QAAQ,CAAC,IAAmB;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrB,MAAM,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACnF,MAAM,IAAI,CAAC,aAAa,EAAE,CAAA;IAC5B,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,KAAK,CAAC,UAA2B,EAAE;QACvC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAClB,MAAM,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC/E,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,aAAa,EAAE,CAAA;IACvD,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAM;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,sEAAsE;IACtE,WAAW;QACT,IAAI,CAAC,IAAI,EAAE,EAAE,CAAA;QACb,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAEO,QAAQ,CAAC,KAAe;QAC9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,CAAC,MAAM;gBAAE,SAAQ;YACxD,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;gBAAE,SAAQ;YACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAC1C,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAAmB,EAAE,KAAe;QACxD,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;YAC5B,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI;SACrC,CAAA;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAA;QAC1E,IAAI,CAAC;YACH,MAAM,IAAI,GAAgB;gBACxB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM;gBAC7B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;gBACxE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAA;YACD,6EAA6E;YAC7E,sEAAsE;YACtE,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe;gBAC9B,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC;gBACpD,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACxC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;QAC7E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,EAAE,IAAI;gBACb,KAAK;gBACL,MAAM,EAAE,IAAI;gBACZ,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aAClD,CAAC,CAAA;QACJ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;IACH,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinbase",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "A Docker-free, Supabase-compatible local backend — real Postgres (embedded native or PGlite/WASM), wire-compatible with supabase-js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Sanket Sahu",
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "npm run build:admin && tsc -p tsconfig.json",
|
|
24
24
|
"dev": "tsx src/cli.ts start",
|
|
25
|
+
"db:reset": "tsx src/cli.ts db reset",
|
|
25
26
|
"test": "vitest run",
|
|
26
27
|
"test:watch": "vitest",
|
|
27
28
|
"build:binary": "npm run build && bun build --compile src/cli.ts --outfile dist-bin/tinbase --external @electric-sql/pglite --define 'process.env.TINBASE_SINGLE_BINARY=\"1\"'",
|
|
28
29
|
"prepublishOnly": "npm run build && npm test",
|
|
29
|
-
"
|
|
30
|
+
"install:admin": "npm --prefix admin-ui ci || npm --prefix admin-ui install",
|
|
31
|
+
"build:admin": "npm run install:admin && npm --prefix admin-ui run build",
|
|
30
32
|
"parity": "tsx parity/harness.ts"
|
|
31
33
|
},
|
|
32
34
|
"engines": {
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"type": "git",
|
|
55
57
|
"url": "git+https://github.com/tinbase/tinbase.git"
|
|
56
58
|
},
|
|
57
|
-
"homepage": "https://tinbase.
|
|
59
|
+
"homepage": "https://tinbase.dev",
|
|
58
60
|
"bugs": {
|
|
59
61
|
"url": "https://github.com/tinbase/tinbase/issues"
|
|
60
62
|
},
|