@bunbase-ae/js 2.15.0 → 2.15.1-next.355.83a242f

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunbase-ae/js",
3
- "version": "2.15.0",
3
+ "version": "2.15.1-next.355.83a242f",
4
4
  "type": "module",
5
5
  "description": "TypeScript/JavaScript SDK for BunBase",
6
6
  "license": "UNLICENSED",
package/src/admin.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  // client.admin.system — health + stats
15
15
 
16
16
  import type { HttpClient } from "./http";
17
- import { BunBaseError, type Filter } from "./types";
17
+ import { BunBaseError, type Filter, type SequenceAccessRule, type SequenceMeta } from "./types";
18
18
 
19
19
  // ─── Shared admin types ───────────────────────────────────────────────────────
20
20
 
@@ -1327,6 +1327,111 @@ class AdminTenantsClient {
1327
1327
  }
1328
1328
  }
1329
1329
 
1330
+ // ─── Sequences ────────────────────────────────────────────────────────────────
1331
+
1332
+ export interface CreateSequenceInput {
1333
+ name: string;
1334
+ /** Initial value. Defaults to 1 server-side. */
1335
+ start_value?: number;
1336
+ /** Access rule for runtime `/next` and `/peek`. Defaults to "authenticated". */
1337
+ access_next?: SequenceAccessRule;
1338
+ /**
1339
+ * When set, the sequence is scoped to that tenant — only callers whose JWT
1340
+ * carries a matching tenantId claim may call /next or /peek. When omitted
1341
+ * (or null), the sequence is global / admin-only.
1342
+ */
1343
+ tenant_id?: string | null;
1344
+ }
1345
+
1346
+ /**
1347
+ * Tenant scope for an admin mutation. The server permits multiple sequences
1348
+ * per name (one per tenant plus an optional global row); `tenant_id`
1349
+ * disambiguates which row the mutation targets.
1350
+ *
1351
+ * `tenant_id` is **omitted** by default — that targets the global row (the
1352
+ * server treats a missing `tenant_id` querystring as the `_global` sentinel,
1353
+ * the safer default established by #537). Pass a real tenant id to target
1354
+ * that tenant's row.
1355
+ */
1356
+ export interface SequenceTenantOptions {
1357
+ tenant_id?: string;
1358
+ }
1359
+
1360
+ // Sequence administration — surfaces the /api/v1/admin/sequences/* endpoints
1361
+ // added in v2.14.0 (#424/#429 family + tenant-scoping in #537/#556) so
1362
+ // operators don't need to hand-roll fetch calls to provision per-tenant
1363
+ // counters or reset them on yearly rollovers.
1364
+ class AdminSequencesClient {
1365
+ constructor(private readonly http: HttpClient) {}
1366
+
1367
+ async list(): Promise<SequenceMeta[]> {
1368
+ const res = await this.http.request<{ items: SequenceMeta[] }>(
1369
+ "GET",
1370
+ "/api/v1/admin/sequences",
1371
+ );
1372
+ return res.items;
1373
+ }
1374
+
1375
+ async create(input: CreateSequenceInput): Promise<SequenceMeta> {
1376
+ return this.http.request<SequenceMeta>("POST", "/api/v1/admin/sequences", {
1377
+ body: input,
1378
+ });
1379
+ }
1380
+
1381
+ async get(name: string, opts: SequenceTenantOptions = {}): Promise<SequenceMeta | null> {
1382
+ try {
1383
+ return await this.http.request<SequenceMeta>(
1384
+ "GET",
1385
+ `/api/v1/admin/sequences/${encodeURIComponent(name)}`,
1386
+ { query: tenantQuery(opts) },
1387
+ );
1388
+ } catch (err) {
1389
+ if (err instanceof BunBaseError && err.status === 404) return null;
1390
+ throw err;
1391
+ }
1392
+ }
1393
+
1394
+ async reset(
1395
+ name: string,
1396
+ value: number,
1397
+ opts: SequenceTenantOptions = {},
1398
+ ): Promise<SequenceMeta> {
1399
+ return this.http.request<SequenceMeta>(
1400
+ "PATCH",
1401
+ `/api/v1/admin/sequences/${encodeURIComponent(name)}`,
1402
+ { body: { value }, query: tenantQuery(opts) },
1403
+ );
1404
+ }
1405
+
1406
+ async setAccessRule(
1407
+ name: string,
1408
+ access_next: SequenceAccessRule,
1409
+ opts: SequenceTenantOptions = {},
1410
+ ): Promise<SequenceMeta> {
1411
+ return this.http.request<SequenceMeta>(
1412
+ "PATCH",
1413
+ `/api/v1/admin/sequences/${encodeURIComponent(name)}`,
1414
+ { body: { access_next }, query: tenantQuery(opts) },
1415
+ );
1416
+ }
1417
+
1418
+ async delete(name: string, opts: SequenceTenantOptions = {}): Promise<void> {
1419
+ await this.http.request("DELETE", `/api/v1/admin/sequences/${encodeURIComponent(name)}`, {
1420
+ query: tenantQuery(opts),
1421
+ });
1422
+ }
1423
+ }
1424
+
1425
+ // Build the tenant_id querystring for an admin sequence call.
1426
+ //
1427
+ // Omitting tenant_id from the request entirely makes the server target the
1428
+ // global row (the post-#537 default). We preserve that behavior — a missing
1429
+ // `tenant_id` option means no `?tenant_id=…` on the wire. Callers who want
1430
+ // a tenant-scoped row must explicitly pass `tenant_id: "<id>"`.
1431
+ function tenantQuery(opts: SequenceTenantOptions): Record<string, string> {
1432
+ return opts.tenant_id !== undefined ? { tenant_id: opts.tenant_id } : {};
1433
+ }
1434
+
1330
1435
  // ─── Main AdminClient ─────────────────────────────────────────────────────────
1331
1436
 
1332
1437
  export class AdminClient {
@@ -1343,6 +1448,7 @@ export class AdminClient {
1343
1448
  readonly logs: AdminLogsClient;
1344
1449
  readonly system: AdminSystemClient;
1345
1450
  readonly tenants: AdminTenantsClient;
1451
+ readonly sequences: AdminSequencesClient;
1346
1452
 
1347
1453
  constructor(http: HttpClient) {
1348
1454
  this.users = new AdminUsersClient(http);
@@ -1358,5 +1464,6 @@ export class AdminClient {
1358
1464
  this.logs = new AdminLogsClient(http);
1359
1465
  this.system = new AdminSystemClient(http);
1360
1466
  this.tenants = new AdminTenantsClient(http);
1467
+ this.sequences = new AdminSequencesClient(http);
1361
1468
  }
1362
1469
  }
package/src/index.ts CHANGED
@@ -22,6 +22,7 @@ export {
22
22
  type CreateHookInput,
23
23
  type CreateNamedQueryInput,
24
24
  type CreateRelationParams,
25
+ type CreateSequenceInput,
25
26
  type EmailTemplate,
26
27
  type HealthResponse,
27
28
  type HookConfig,
@@ -37,6 +38,7 @@ export {
37
38
  type Relation,
38
39
  type RelationOnDelete,
39
40
  type RelationType,
41
+ type SequenceTenantOptions,
40
42
  type ServerSettings,
41
43
  type SettingsAuditEntry,
42
44
  type StatsResponse,
@@ -90,6 +92,8 @@ export {
90
92
  type RealtimeCallback,
91
93
  type RealtimeEvent,
92
94
  type RealtimeEventType,
95
+ type SequenceAccessRule,
96
+ type SequenceMeta,
93
97
  type StorageAdapter,
94
98
  type SwitchTenantResult,
95
99
  type TenantMembership,
package/src/types.ts CHANGED
@@ -370,6 +370,38 @@ export interface ApiKey {
370
370
  created_at: number;
371
371
  }
372
372
 
373
+ // ─── Sequences ────────────────────────────────────────────────────────────────
374
+
375
+ /**
376
+ * Access rule controlling who may call the runtime `next`/`peek` endpoints
377
+ * for a sequence.
378
+ *
379
+ * Mirrors the server's AccessRule shape:
380
+ * - "public" — anyone (no auth required)
381
+ * - "authenticated" — any logged-in user (default)
382
+ * - "disabled" — runtime calls always denied (admin-only sequence)
383
+ * - { role: "..." } — only users with that role
384
+ */
385
+ export type SequenceAccessRule = "public" | "authenticated" | "disabled" | { role: string };
386
+
387
+ /**
388
+ * A sequence row as returned by the admin API. The wire shape exactly matches
389
+ * `SequenceMeta` exported from `@bunbase/core`.
390
+ *
391
+ * `tenant_id === null` is the global row (admin-only). A non-null `tenant_id`
392
+ * scopes the sequence to that tenant — only callers whose JWT carries a
393
+ * matching `tenantId` claim can call `/next` or `/peek` on it.
394
+ */
395
+ export interface SequenceMeta {
396
+ name: string;
397
+ tenant_id: string | null;
398
+ value: number;
399
+ start_value: number;
400
+ access_next: SequenceAccessRule;
401
+ created_at: number;
402
+ updated_at: number;
403
+ }
404
+
373
405
  // ─── Multi-tenancy ────────────────────────────────────────────────────────────
374
406
 
375
407
  /** A single tenant membership for the authenticated user. Returned by `AuthClient.listTenants()`. */