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.
Files changed (156) hide show
  1. package/README.md +10 -9
  2. package/dist/admin/api.d.ts +62 -1
  3. package/dist/admin/api.js +221 -10
  4. package/dist/admin/api.js.map +1 -1
  5. package/dist/admin/ui.d.ts +1 -1
  6. package/dist/admin/ui.js +1548 -16
  7. package/dist/admin/ui.js.map +1 -1
  8. package/dist/auth/handler.d.ts +52 -5
  9. package/dist/auth/handler.js +147 -36
  10. package/dist/auth/handler.js.map +1 -1
  11. package/dist/auth/inbox.d.ts +4 -2
  12. package/dist/auth/inbox.js +1 -0
  13. package/dist/auth/inbox.js.map +1 -1
  14. package/dist/auth/oauth.d.ts +30 -4
  15. package/dist/auth/oauth.js +22 -6
  16. package/dist/auth/oauth.js.map +1 -1
  17. package/dist/auth/password.d.ts +5 -0
  18. package/dist/auth/password.js +7 -0
  19. package/dist/auth/password.js.map +1 -1
  20. package/dist/auth/qr.d.ts +1 -1
  21. package/dist/auth/qr.js +1 -1
  22. package/dist/auth/rate-limit.d.ts +33 -0
  23. package/dist/auth/rate-limit.js +63 -0
  24. package/dist/auth/rate-limit.js.map +1 -0
  25. package/dist/auth/redirect.d.ts +20 -0
  26. package/dist/auth/redirect.js +79 -0
  27. package/dist/auth/redirect.js.map +1 -0
  28. package/dist/auth/settings.d.ts +55 -0
  29. package/dist/auth/settings.js +116 -0
  30. package/dist/auth/settings.js.map +1 -0
  31. package/dist/auth/totp.js +1 -1
  32. package/dist/cli.js +43 -21
  33. package/dist/cli.js.map +1 -1
  34. package/dist/cron/service.d.ts +15 -2
  35. package/dist/cron/service.js +19 -2
  36. package/dist/cron/service.js.map +1 -1
  37. package/dist/db/bootstrap.d.ts +13 -6
  38. package/dist/db/bootstrap.js +26 -5
  39. package/dist/db/bootstrap.js.map +1 -1
  40. package/dist/db/database.d.ts +61 -3
  41. package/dist/db/database.js +72 -9
  42. package/dist/db/database.js.map +1 -1
  43. package/dist/db/emulated.d.ts +39 -2
  44. package/dist/db/emulated.js +39 -23
  45. package/dist/db/emulated.js.map +1 -1
  46. package/dist/db/engine.d.ts +19 -5
  47. package/dist/db/engine.js +4 -2
  48. package/dist/db/engine.js.map +1 -1
  49. package/dist/db/inspect.d.ts +6 -1
  50. package/dist/db/inspect.js +2 -1
  51. package/dist/db/inspect.js.map +1 -1
  52. package/dist/db/pglite-engine.d.ts +7 -1
  53. package/dist/db/pglite-engine.js +7 -1
  54. package/dist/db/pglite-engine.js.map +1 -1
  55. package/dist/db/pgmem-engine.d.ts +9 -3
  56. package/dist/db/pgmem-engine.js +13 -7
  57. package/dist/db/pgmem-engine.js.map +1 -1
  58. package/dist/db/schema-diff.d.ts +9 -1
  59. package/dist/db/schema-diff.js +19 -5
  60. package/dist/db/schema-diff.js.map +1 -1
  61. package/dist/db/sql-compat.d.ts +2 -2
  62. package/dist/db/sql-compat.js +2 -2
  63. package/dist/functions/deno-shim.d.ts +6 -17
  64. package/dist/functions/deno-shim.js +42 -10
  65. package/dist/functions/deno-shim.js.map +1 -1
  66. package/dist/functions/handler.d.ts +9 -4
  67. package/dist/functions/handler.js +9 -1
  68. package/dist/functions/handler.js.map +1 -1
  69. package/dist/gen-types.d.ts +6 -1
  70. package/dist/gen-types.js +53 -41
  71. package/dist/gen-types.js.map +1 -1
  72. package/dist/index.d.ts +33 -3
  73. package/dist/index.js +158 -28
  74. package/dist/index.js.map +1 -1
  75. package/dist/jwt.d.ts +4 -1
  76. package/dist/jwt.js +4 -2
  77. package/dist/jwt.js.map +1 -1
  78. package/dist/log-buffer.d.ts +7 -1
  79. package/dist/log-buffer.js +3 -0
  80. package/dist/log-buffer.js.map +1 -1
  81. package/dist/net/service.d.ts +35 -6
  82. package/dist/net/service.js +72 -17
  83. package/dist/net/service.js.map +1 -1
  84. package/dist/node/bun-server.d.ts +2 -1
  85. package/dist/node/bun-server.js +11 -1
  86. package/dist/node/bun-server.js.map +1 -1
  87. package/dist/node/bundle-function.d.ts +1 -1
  88. package/dist/node/bundle-function.js +1 -1
  89. package/dist/node/config-toml.d.ts +31 -0
  90. package/dist/node/config-toml.js +186 -0
  91. package/dist/node/config-toml.js.map +1 -0
  92. package/dist/node/db-diff.d.ts +13 -1
  93. package/dist/node/db-diff.js +3 -1
  94. package/dist/node/db-diff.js.map +1 -1
  95. package/dist/node/fs-driver.d.ts +16 -1
  96. package/dist/node/fs-driver.js +20 -1
  97. package/dist/node/fs-driver.js.map +1 -1
  98. package/dist/node/index.d.ts +2 -2
  99. package/dist/node/index.js +1 -1
  100. package/dist/node/index.js.map +1 -1
  101. package/dist/node/load-config.d.ts +80 -0
  102. package/dist/node/load-config.js +230 -0
  103. package/dist/node/load-config.js.map +1 -0
  104. package/dist/node/load-functions.d.ts +17 -2
  105. package/dist/node/load-functions.js +17 -4
  106. package/dist/node/load-functions.js.map +1 -1
  107. package/dist/node/native/engine.d.ts +7 -0
  108. package/dist/node/native/engine.js +58 -7
  109. package/dist/node/native/engine.js.map +1 -1
  110. package/dist/node/native/wire.d.ts +15 -1
  111. package/dist/node/native/wire.js +32 -10
  112. package/dist/node/native/wire.js.map +1 -1
  113. package/dist/node/project.d.ts +15 -1
  114. package/dist/node/project.js +19 -7
  115. package/dist/node/project.js.map +1 -1
  116. package/dist/node/server-shared.d.ts +4 -1
  117. package/dist/node/server.d.ts +11 -0
  118. package/dist/node/server.js +11 -0
  119. package/dist/node/server.js.map +1 -1
  120. package/dist/node/ws.d.ts +26 -1
  121. package/dist/node/ws.js +26 -3
  122. package/dist/node/ws.js.map +1 -1
  123. package/dist/realtime/engine.d.ts +6 -0
  124. package/dist/realtime/engine.js +45 -34
  125. package/dist/realtime/engine.js.map +1 -1
  126. package/dist/rest/build.d.ts +37 -1
  127. package/dist/rest/build.js +48 -8
  128. package/dist/rest/build.js.map +1 -1
  129. package/dist/rest/errors.d.ts +8 -0
  130. package/dist/rest/errors.js +12 -1
  131. package/dist/rest/errors.js.map +1 -1
  132. package/dist/rest/handler.d.ts +17 -1
  133. package/dist/rest/handler.js +48 -5
  134. package/dist/rest/handler.js.map +1 -1
  135. package/dist/rest/parse.d.ts +24 -1
  136. package/dist/rest/parse.js +7 -1
  137. package/dist/rest/parse.js.map +1 -1
  138. package/dist/retention/service.d.ts +3 -0
  139. package/dist/retention/service.js +3 -1
  140. package/dist/retention/service.js.map +1 -1
  141. package/dist/security.d.ts +22 -0
  142. package/dist/security.js +47 -0
  143. package/dist/security.js.map +1 -0
  144. package/dist/storage/driver.d.ts +8 -1
  145. package/dist/storage/driver.js +4 -1
  146. package/dist/storage/driver.js.map +1 -1
  147. package/dist/storage/handler.d.ts +10 -1
  148. package/dist/storage/handler.js +93 -12
  149. package/dist/storage/handler.js.map +1 -1
  150. package/dist/types.d.ts +77 -1
  151. package/dist/types.js +10 -0
  152. package/dist/types.js.map +1 -1
  153. package/dist/webhooks/service.d.ts +25 -2
  154. package/dist/webhooks/service.js +21 -3
  155. package/dist/webhooks/service.js.map +1 -1
  156. 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; set a dedicated key in production.
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":"AAmFA,MAAM,CAAC,MAAM,kBAAkB,GAAG,yDAAyD,CAAA;AAiB3F,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
+ {"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 — fire an HTTP request when rows change, the tinbase
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;
@@ -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 res = await this.fetchImpl(hook.url, {
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":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/webhooks/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinbase",
3
- "version": "0.10.0",
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
- "build:admin": "cd admin-ui && npm run build",
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.vercel.app",
59
+ "homepage": "https://tinbase.dev",
58
60
  "bugs": {
59
61
  "url": "https://github.com/tinbase/tinbase/issues"
60
62
  },