@kividb/client 0.1.0 → 0.1.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 +34 -0
- package/dist/index.cjs +37 -0
- package/dist/index.d.cts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +36 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,3 +134,37 @@ channel.unsubscribe();
|
|
|
134
134
|
One WebSocket is shared per project across all channels. It reconnects with
|
|
135
135
|
backoff and re-subscribes automatically; `DELETE` postgres events are delivered
|
|
136
136
|
only to `service_role` tokens (a documented v1 server limitation).
|
|
137
|
+
|
|
138
|
+
## Migrations
|
|
139
|
+
|
|
140
|
+
Create and evolve your schema from code instead of the dashboard. Requires the
|
|
141
|
+
**service key** (server-side only — never ship it to a browser):
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const kdb = createClient(KIVIDB_URL, process.env.KIVIDB_SERVICE_KEY!);
|
|
145
|
+
|
|
146
|
+
await kdb.migrations.apply([
|
|
147
|
+
{
|
|
148
|
+
name: "0001_messages",
|
|
149
|
+
sql: `
|
|
150
|
+
create table messages (
|
|
151
|
+
id uuid primary key default gen_random_uuid(),
|
|
152
|
+
room text not null,
|
|
153
|
+
body text not null,
|
|
154
|
+
created_at timestamptz not null default now()
|
|
155
|
+
);
|
|
156
|
+
alter table messages enable row level security;
|
|
157
|
+
`,
|
|
158
|
+
},
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
const { data } = await kdb.migrations.list(); // the applied-migrations ledger
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`apply` is idempotent: each migration is recorded by name in a per-project
|
|
165
|
+
ledger, so re-running the same list skips what's already applied — keep one
|
|
166
|
+
array in your repo, append to it, and run it on every deploy. Applied
|
|
167
|
+
migrations are immutable (changing an applied name's SQL is a 409; add a new
|
|
168
|
+
one instead). Each migration runs in its own transaction as the project owner
|
|
169
|
+
role, with your project schema as the `search_path` — remember to enable RLS
|
|
170
|
+
on new tables, and don't put `begin`/`commit` inside the SQL.
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
FilterBuilder: () => FilterBuilder,
|
|
25
25
|
FromBuilder: () => FromBuilder,
|
|
26
26
|
KividbClient: () => KividbClient,
|
|
27
|
+
MigrationsClient: () => MigrationsClient,
|
|
27
28
|
RealtimeChannel: () => RealtimeChannel,
|
|
28
29
|
RealtimeClient: () => RealtimeClient,
|
|
29
30
|
StorageClient: () => StorageClient,
|
|
@@ -302,6 +303,34 @@ function base64UrlDecode(segment) {
|
|
|
302
303
|
return new TextDecoder().decode(bytes);
|
|
303
304
|
}
|
|
304
305
|
|
|
306
|
+
// src/migrations.ts
|
|
307
|
+
var MigrationsClient = class {
|
|
308
|
+
constructor(cfg) {
|
|
309
|
+
this.cfg = cfg;
|
|
310
|
+
}
|
|
311
|
+
cfg;
|
|
312
|
+
get endpoint() {
|
|
313
|
+
return `${this.cfg.rest}/${this.cfg.project}/-/migrations`;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Apply migrations in order, skipping ones already applied. On a failure the
|
|
317
|
+
* error's `details` carry `failed` (the migration that broke) plus the
|
|
318
|
+
* `applied`/`skipped` progress before it; already-applied migrations stay
|
|
319
|
+
* applied and skip on the next run.
|
|
320
|
+
*/
|
|
321
|
+
apply(migrations) {
|
|
322
|
+
return request(this.endpoint, {
|
|
323
|
+
method: "POST",
|
|
324
|
+
body: JSON.stringify({ migrations }),
|
|
325
|
+
token: this.cfg.key
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
/** The applied-migrations ledger, oldest first. */
|
|
329
|
+
list() {
|
|
330
|
+
return request(this.endpoint, { token: this.cfg.key });
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
305
334
|
// src/postgrest.ts
|
|
306
335
|
var FromBuilder = class {
|
|
307
336
|
constructor(ctx, table) {
|
|
@@ -770,6 +799,11 @@ var KividbClient = class {
|
|
|
770
799
|
anonKey,
|
|
771
800
|
session: this.session
|
|
772
801
|
});
|
|
802
|
+
this.migrations = new MigrationsClient({
|
|
803
|
+
rest: this.endpoints.rest,
|
|
804
|
+
project: this.project,
|
|
805
|
+
key: anonKey
|
|
806
|
+
});
|
|
773
807
|
this.session.hydrateSync();
|
|
774
808
|
void this.session.hydrate();
|
|
775
809
|
}
|
|
@@ -778,6 +812,8 @@ var KividbClient = class {
|
|
|
778
812
|
auth;
|
|
779
813
|
realtime;
|
|
780
814
|
storage;
|
|
815
|
+
/** Schema migrations — requires the client to hold the service key. */
|
|
816
|
+
migrations;
|
|
781
817
|
project;
|
|
782
818
|
endpoints;
|
|
783
819
|
session;
|
|
@@ -819,6 +855,7 @@ function createServerClient(url, anonKey, options) {
|
|
|
819
855
|
FilterBuilder,
|
|
820
856
|
FromBuilder,
|
|
821
857
|
KividbClient,
|
|
858
|
+
MigrationsClient,
|
|
822
859
|
RealtimeChannel,
|
|
823
860
|
RealtimeClient,
|
|
824
861
|
StorageClient,
|
package/dist/index.d.cts
CHANGED
|
@@ -203,6 +203,58 @@ interface CookieMethods {
|
|
|
203
203
|
/** Cookie name carrying the JSON session for a given project. */
|
|
204
204
|
declare function sessionCookieName(project: string): string;
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Schema migrations, applied through the data API's service_role-only
|
|
208
|
+
* `/:project/-/migrations` endpoint. Create the client with the project's
|
|
209
|
+
* **service key** (never ship that key to a browser):
|
|
210
|
+
*
|
|
211
|
+
* const kdb = createClient(url, serviceKey);
|
|
212
|
+
* await kdb.migrations.apply([
|
|
213
|
+
* { name: "0001_messages", sql: `create table messages (…); alter table messages enable row level security;` },
|
|
214
|
+
* ]);
|
|
215
|
+
*
|
|
216
|
+
* Applying is idempotent: each migration is recorded in a per-project ledger
|
|
217
|
+
* by name, so re-running the same list skips what's already applied. Applied
|
|
218
|
+
* migrations are immutable — changing the SQL of an applied name is a 409;
|
|
219
|
+
* add a new migration instead.
|
|
220
|
+
*/
|
|
221
|
+
/** A named schema migration. Names must be unique and are applied in order. */
|
|
222
|
+
interface Migration {
|
|
223
|
+
name: string;
|
|
224
|
+
sql: string;
|
|
225
|
+
}
|
|
226
|
+
interface ApplyMigrationsResult {
|
|
227
|
+
/** Names applied by this call, in order. */
|
|
228
|
+
applied: string[];
|
|
229
|
+
/** Names already in the ledger (identical SQL), skipped. */
|
|
230
|
+
skipped: string[];
|
|
231
|
+
}
|
|
232
|
+
/** A ledger entry for an applied migration. */
|
|
233
|
+
interface AppliedMigration {
|
|
234
|
+
name: string;
|
|
235
|
+
/** sha256 of the SQL as applied. */
|
|
236
|
+
checksum: string;
|
|
237
|
+
applied_at: string;
|
|
238
|
+
}
|
|
239
|
+
declare class MigrationsClient {
|
|
240
|
+
private readonly cfg;
|
|
241
|
+
constructor(cfg: {
|
|
242
|
+
rest: string;
|
|
243
|
+
project: string;
|
|
244
|
+
key: string;
|
|
245
|
+
});
|
|
246
|
+
private get endpoint();
|
|
247
|
+
/**
|
|
248
|
+
* Apply migrations in order, skipping ones already applied. On a failure the
|
|
249
|
+
* error's `details` carry `failed` (the migration that broke) plus the
|
|
250
|
+
* `applied`/`skipped` progress before it; already-applied migrations stay
|
|
251
|
+
* applied and skip on the next run.
|
|
252
|
+
*/
|
|
253
|
+
apply(migrations: Migration[]): Promise<KividbResponse<ApplyMigrationsResult>>;
|
|
254
|
+
/** The applied-migrations ledger, oldest first. */
|
|
255
|
+
list(): Promise<KividbResponse<AppliedMigration[]>>;
|
|
256
|
+
}
|
|
257
|
+
|
|
206
258
|
interface Context {
|
|
207
259
|
rest: string;
|
|
208
260
|
project: string;
|
|
@@ -463,6 +515,8 @@ declare class KividbClient {
|
|
|
463
515
|
readonly auth: AuthClient;
|
|
464
516
|
readonly realtime: RealtimeClient;
|
|
465
517
|
readonly storage: StorageClient;
|
|
518
|
+
/** Schema migrations — requires the client to hold the service key. */
|
|
519
|
+
readonly migrations: MigrationsClient;
|
|
466
520
|
readonly project: string;
|
|
467
521
|
private readonly endpoints;
|
|
468
522
|
private readonly session;
|
|
@@ -490,4 +544,4 @@ declare function createServerClient(url: string, anonKey: string, options: Omit<
|
|
|
490
544
|
cookies: CookieMethods;
|
|
491
545
|
}): KividbClient;
|
|
492
546
|
|
|
493
|
-
export { AuthClient, type AuthEvent, type AuthListener, type ClientOptions, type CookieMethods, type CookieOptions, FilterBuilder, FromBuilder, KividbClient, type KividbError, type KividbResponse, type OAuthProvider, type PostgresChange, RealtimeChannel, RealtimeClient, type Row, type Session, type SessionStore, type SignedUrl, StorageClient, type StorageObjectInfo, type TransformOptions, type UploadBody, type UploadOptions, type User, createBrowserClient, createClient, createServerClient, projectFromAnonKey, sessionCookieName };
|
|
547
|
+
export { type AppliedMigration, type ApplyMigrationsResult, AuthClient, type AuthEvent, type AuthListener, type ClientOptions, type CookieMethods, type CookieOptions, FilterBuilder, FromBuilder, KividbClient, type KividbError, type KividbResponse, type Migration, MigrationsClient, type OAuthProvider, type PostgresChange, RealtimeChannel, RealtimeClient, type Row, type Session, type SessionStore, type SignedUrl, StorageClient, type StorageObjectInfo, type TransformOptions, type UploadBody, type UploadOptions, type User, createBrowserClient, createClient, createServerClient, projectFromAnonKey, sessionCookieName };
|
package/dist/index.d.ts
CHANGED
|
@@ -203,6 +203,58 @@ interface CookieMethods {
|
|
|
203
203
|
/** Cookie name carrying the JSON session for a given project. */
|
|
204
204
|
declare function sessionCookieName(project: string): string;
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Schema migrations, applied through the data API's service_role-only
|
|
208
|
+
* `/:project/-/migrations` endpoint. Create the client with the project's
|
|
209
|
+
* **service key** (never ship that key to a browser):
|
|
210
|
+
*
|
|
211
|
+
* const kdb = createClient(url, serviceKey);
|
|
212
|
+
* await kdb.migrations.apply([
|
|
213
|
+
* { name: "0001_messages", sql: `create table messages (…); alter table messages enable row level security;` },
|
|
214
|
+
* ]);
|
|
215
|
+
*
|
|
216
|
+
* Applying is idempotent: each migration is recorded in a per-project ledger
|
|
217
|
+
* by name, so re-running the same list skips what's already applied. Applied
|
|
218
|
+
* migrations are immutable — changing the SQL of an applied name is a 409;
|
|
219
|
+
* add a new migration instead.
|
|
220
|
+
*/
|
|
221
|
+
/** A named schema migration. Names must be unique and are applied in order. */
|
|
222
|
+
interface Migration {
|
|
223
|
+
name: string;
|
|
224
|
+
sql: string;
|
|
225
|
+
}
|
|
226
|
+
interface ApplyMigrationsResult {
|
|
227
|
+
/** Names applied by this call, in order. */
|
|
228
|
+
applied: string[];
|
|
229
|
+
/** Names already in the ledger (identical SQL), skipped. */
|
|
230
|
+
skipped: string[];
|
|
231
|
+
}
|
|
232
|
+
/** A ledger entry for an applied migration. */
|
|
233
|
+
interface AppliedMigration {
|
|
234
|
+
name: string;
|
|
235
|
+
/** sha256 of the SQL as applied. */
|
|
236
|
+
checksum: string;
|
|
237
|
+
applied_at: string;
|
|
238
|
+
}
|
|
239
|
+
declare class MigrationsClient {
|
|
240
|
+
private readonly cfg;
|
|
241
|
+
constructor(cfg: {
|
|
242
|
+
rest: string;
|
|
243
|
+
project: string;
|
|
244
|
+
key: string;
|
|
245
|
+
});
|
|
246
|
+
private get endpoint();
|
|
247
|
+
/**
|
|
248
|
+
* Apply migrations in order, skipping ones already applied. On a failure the
|
|
249
|
+
* error's `details` carry `failed` (the migration that broke) plus the
|
|
250
|
+
* `applied`/`skipped` progress before it; already-applied migrations stay
|
|
251
|
+
* applied and skip on the next run.
|
|
252
|
+
*/
|
|
253
|
+
apply(migrations: Migration[]): Promise<KividbResponse<ApplyMigrationsResult>>;
|
|
254
|
+
/** The applied-migrations ledger, oldest first. */
|
|
255
|
+
list(): Promise<KividbResponse<AppliedMigration[]>>;
|
|
256
|
+
}
|
|
257
|
+
|
|
206
258
|
interface Context {
|
|
207
259
|
rest: string;
|
|
208
260
|
project: string;
|
|
@@ -463,6 +515,8 @@ declare class KividbClient {
|
|
|
463
515
|
readonly auth: AuthClient;
|
|
464
516
|
readonly realtime: RealtimeClient;
|
|
465
517
|
readonly storage: StorageClient;
|
|
518
|
+
/** Schema migrations — requires the client to hold the service key. */
|
|
519
|
+
readonly migrations: MigrationsClient;
|
|
466
520
|
readonly project: string;
|
|
467
521
|
private readonly endpoints;
|
|
468
522
|
private readonly session;
|
|
@@ -490,4 +544,4 @@ declare function createServerClient(url: string, anonKey: string, options: Omit<
|
|
|
490
544
|
cookies: CookieMethods;
|
|
491
545
|
}): KividbClient;
|
|
492
546
|
|
|
493
|
-
export { AuthClient, type AuthEvent, type AuthListener, type ClientOptions, type CookieMethods, type CookieOptions, FilterBuilder, FromBuilder, KividbClient, type KividbError, type KividbResponse, type OAuthProvider, type PostgresChange, RealtimeChannel, RealtimeClient, type Row, type Session, type SessionStore, type SignedUrl, StorageClient, type StorageObjectInfo, type TransformOptions, type UploadBody, type UploadOptions, type User, createBrowserClient, createClient, createServerClient, projectFromAnonKey, sessionCookieName };
|
|
547
|
+
export { type AppliedMigration, type ApplyMigrationsResult, AuthClient, type AuthEvent, type AuthListener, type ClientOptions, type CookieMethods, type CookieOptions, FilterBuilder, FromBuilder, KividbClient, type KividbError, type KividbResponse, type Migration, MigrationsClient, type OAuthProvider, type PostgresChange, RealtimeChannel, RealtimeClient, type Row, type Session, type SessionStore, type SignedUrl, StorageClient, type StorageObjectInfo, type TransformOptions, type UploadBody, type UploadOptions, type User, createBrowserClient, createClient, createServerClient, projectFromAnonKey, sessionCookieName };
|
package/dist/index.js
CHANGED
|
@@ -265,6 +265,34 @@ function base64UrlDecode(segment) {
|
|
|
265
265
|
return new TextDecoder().decode(bytes);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
// src/migrations.ts
|
|
269
|
+
var MigrationsClient = class {
|
|
270
|
+
constructor(cfg) {
|
|
271
|
+
this.cfg = cfg;
|
|
272
|
+
}
|
|
273
|
+
cfg;
|
|
274
|
+
get endpoint() {
|
|
275
|
+
return `${this.cfg.rest}/${this.cfg.project}/-/migrations`;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Apply migrations in order, skipping ones already applied. On a failure the
|
|
279
|
+
* error's `details` carry `failed` (the migration that broke) plus the
|
|
280
|
+
* `applied`/`skipped` progress before it; already-applied migrations stay
|
|
281
|
+
* applied and skip on the next run.
|
|
282
|
+
*/
|
|
283
|
+
apply(migrations) {
|
|
284
|
+
return request(this.endpoint, {
|
|
285
|
+
method: "POST",
|
|
286
|
+
body: JSON.stringify({ migrations }),
|
|
287
|
+
token: this.cfg.key
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
/** The applied-migrations ledger, oldest first. */
|
|
291
|
+
list() {
|
|
292
|
+
return request(this.endpoint, { token: this.cfg.key });
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
268
296
|
// src/postgrest.ts
|
|
269
297
|
var FromBuilder = class {
|
|
270
298
|
constructor(ctx, table) {
|
|
@@ -733,6 +761,11 @@ var KividbClient = class {
|
|
|
733
761
|
anonKey,
|
|
734
762
|
session: this.session
|
|
735
763
|
});
|
|
764
|
+
this.migrations = new MigrationsClient({
|
|
765
|
+
rest: this.endpoints.rest,
|
|
766
|
+
project: this.project,
|
|
767
|
+
key: anonKey
|
|
768
|
+
});
|
|
736
769
|
this.session.hydrateSync();
|
|
737
770
|
void this.session.hydrate();
|
|
738
771
|
}
|
|
@@ -741,6 +774,8 @@ var KividbClient = class {
|
|
|
741
774
|
auth;
|
|
742
775
|
realtime;
|
|
743
776
|
storage;
|
|
777
|
+
/** Schema migrations — requires the client to hold the service key. */
|
|
778
|
+
migrations;
|
|
744
779
|
project;
|
|
745
780
|
endpoints;
|
|
746
781
|
session;
|
|
@@ -781,6 +816,7 @@ export {
|
|
|
781
816
|
FilterBuilder,
|
|
782
817
|
FromBuilder,
|
|
783
818
|
KividbClient,
|
|
819
|
+
MigrationsClient,
|
|
784
820
|
RealtimeChannel,
|
|
785
821
|
RealtimeClient,
|
|
786
822
|
StorageClient,
|