@rebasepro/types 0.17.3 → 0.18.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.
Files changed (71) hide show
  1. package/README.md +4 -0
  2. package/dist/call_context.d.ts +20 -0
  3. package/dist/controllers/client.d.ts +36 -4
  4. package/dist/controllers/data.d.ts +120 -10
  5. package/dist/errors.d.ts +83 -4
  6. package/dist/index.es.js +522 -160
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/types/admin_block.d.ts +2 -2
  9. package/dist/types/auth_adapter.d.ts +41 -6
  10. package/dist/types/backend.d.ts +48 -0
  11. package/dist/types/collections.d.ts +25 -1
  12. package/dist/types/cron.d.ts +34 -0
  13. package/dist/types/database_adapter.d.ts +39 -0
  14. package/dist/types/entity_callbacks.d.ts +14 -1
  15. package/dist/types/filter-operators.d.ts +24 -1
  16. package/dist/types/policy.d.ts +29 -1
  17. package/dist/types/properties.d.ts +216 -3
  18. package/dist/types/relations.d.ts +65 -7
  19. package/dist/types/resource_kinds.d.ts +173 -17
  20. package/dist/types/resources.d.ts +108 -7
  21. package/dist/types/rls-functions.d.ts +11 -0
  22. package/dist/types/storage_source.d.ts +12 -23
  23. package/package.json +24 -23
  24. package/src/call_context.ts +0 -120
  25. package/src/controllers/auth_state.ts +0 -24
  26. package/src/controllers/client.ts +0 -494
  27. package/src/controllers/collection_registry.ts +0 -62
  28. package/src/controllers/data.ts +0 -1012
  29. package/src/controllers/data_driver.ts +0 -576
  30. package/src/controllers/effective_role.ts +0 -4
  31. package/src/controllers/email.ts +0 -91
  32. package/src/controllers/index.ts +0 -11
  33. package/src/controllers/storage.ts +0 -252
  34. package/src/errors.ts +0 -119
  35. package/src/index.ts +0 -5
  36. package/src/types/admin_block.ts +0 -209
  37. package/src/types/api_keys.ts +0 -108
  38. package/src/types/auth_adapter.ts +0 -580
  39. package/src/types/backend.ts +0 -987
  40. package/src/types/backup.ts +0 -26
  41. package/src/types/channel_bus.ts +0 -202
  42. package/src/types/chips.ts +0 -34
  43. package/src/types/collection_contract.ts +0 -278
  44. package/src/types/collections.ts +0 -763
  45. package/src/types/component_ref.ts +0 -92
  46. package/src/types/cron.ts +0 -213
  47. package/src/types/data_source.ts +0 -357
  48. package/src/types/database_adapter.ts +0 -267
  49. package/src/types/entities.ts +0 -226
  50. package/src/types/entity_callbacks.ts +0 -229
  51. package/src/types/filter-operators.ts +0 -444
  52. package/src/types/history.ts +0 -66
  53. package/src/types/index.ts +0 -36
  54. package/src/types/indexes.ts +0 -180
  55. package/src/types/policy.ts +0 -328
  56. package/src/types/postgres_introspection.ts +0 -101
  57. package/src/types/project_manifest.ts +0 -598
  58. package/src/types/properties.ts +0 -1368
  59. package/src/types/relations.ts +0 -417
  60. package/src/types/resource_kinds.ts +0 -390
  61. package/src/types/resources.ts +0 -368
  62. package/src/types/rls-functions.ts +0 -98
  63. package/src/types/schema_editing.ts +0 -157
  64. package/src/types/schema_version.ts +0 -112
  65. package/src/types/search.ts +0 -247
  66. package/src/types/security_rules.ts +0 -344
  67. package/src/types/storage_authorize.ts +0 -77
  68. package/src/types/storage_source.ts +0 -248
  69. package/src/types/websockets.ts +0 -117
  70. package/src/users/index.ts +0 -2
  71. package/src/users/user.ts +0 -69
@@ -1,252 +0,0 @@
1
- /**
2
- * Path prefix that marks an object as **public**. Files stored under this
3
- * prefix are served without any auth token via a stable, permanent,
4
- * CDN-cacheable URL (see {@link StorageSource.getSignedUrl}). Shared by the
5
- * client SDK and the backend so both agree on which objects are public.
6
- *
7
- * @group Models
8
- */
9
- export const PUBLIC_STORAGE_PREFIX = "public/";
10
-
11
- /**
12
- * True when a storage key/path points at a public object (lives under
13
- * {@link PUBLIC_STORAGE_PREFIX}). The check is applied to the key *within the
14
- * bucket* — strip any `bucket/` and `scheme://` prefixes first.
15
- *
16
- * @group Models
17
- */
18
- export function isPublicStoragePath(path: string | null | undefined): boolean {
19
- if (!path) return false;
20
- let p = path;
21
- const scheme = p.indexOf("://");
22
- if (scheme !== -1) p = p.substring(scheme + 3);
23
- p = p.replace(/^\/+/, "");
24
-
25
- // Defense-in-depth: a path containing traversal segments is never public,
26
- // so an attacker can't reach a private object via `public/../secret`.
27
- if (p.split("/").some((seg) => seg === "..")) return false;
28
-
29
- // Public iff the object **key** starts with the public prefix. A single
30
- // leading `default/` bucket segment is tolerated (the default bucket).
31
- // A substring match is deliberately NOT used — a private object under a
32
- // folder literally named `public` (e.g. `reports/public/q3.pdf`) must stay
33
- // private. Named buckets: pass the key (not `bucket/key`) so the prefix is
34
- // anchored; otherwise it falls back to a private, token-scoped URL (safe).
35
- return p.startsWith(PUBLIC_STORAGE_PREFIX) || p.startsWith(`default/${PUBLIC_STORAGE_PREFIX}`);
36
- }
37
-
38
- /**
39
- * @group Models
40
- */
41
- export interface UploadFileProps {
42
- file: File,
43
- key: string,
44
- metadata?: Record<string, unknown>,
45
- bucket?: string,
46
- /**
47
- * Store this object as **public**: it is placed under
48
- * {@link PUBLIC_STORAGE_PREFIX} and served via a stable, token-less,
49
- * permanent URL (safe to persist in a database and cache on a CDN).
50
- * Defaults to `false` (private, short-lived signed URLs).
51
- */
52
- public?: boolean
53
- }
54
-
55
- /**
56
- * @group Models
57
- */
58
- export interface UploadFileResult {
59
- /**
60
- * Storage key including the file name where the file was uploaded.
61
- */
62
- key: string;
63
- /**
64
- * Bucket where the file was uploaded
65
- */
66
- bucket: string;
67
-
68
- /**
69
- * Fully qualified storage URL for the uploaded file.
70
- *
71
- * For example: `s3://my-bucket/path/to/file.png`. Every controller in the
72
- * framework returns one — S3, GCS and local alike — and a caller that stores
73
- * the reference needs it, so it is part of the result rather than a maybe.
74
- */
75
- storageUrl: string;
76
- }
77
-
78
- /**
79
- * @group Models
80
- */
81
- export interface DownloadConfig {
82
- /**
83
- * Temporal url that can be used to download the file
84
- */
85
- url: string | null;
86
-
87
- metadata?: DownloadMetadata;
88
-
89
- fileNotFound?: boolean;
90
- }
91
-
92
- /**
93
- * The full set of object metadata, including read-only properties.
94
- * @public
95
- */
96
- export declare interface DownloadMetadata {
97
- /**
98
- * The bucket this object is contained in.
99
- */
100
- bucket: string;
101
- /**
102
- * The full path of this object.
103
- */
104
- fullPath: string;
105
- /**
106
- * The short name of this object, which is the last component of the full path.
107
- * For example, if path is 'full/path/image.png', name is 'image.png'.
108
- */
109
- name: string;
110
- /**
111
- * The size of this object, in bytes.
112
- */
113
- size: number;
114
- /**
115
- * Type of the uploaded file
116
- * e.g. "image/jpeg"
117
- */
118
- contentType: string;
119
-
120
- customMetadata: Record<string, unknown>;
121
- /**
122
- * Optional short-lived download token (for local/server-mediated storage).
123
- * Absent for public objects, which need no token.
124
- */
125
- token?: string;
126
- /**
127
- * Optional remaining lifetime of the token, in seconds.
128
- */
129
- tokenExpiresIn?: number;
130
- /**
131
- * True when this object is public: it is served without a token via a
132
- * stable, permanent, CDN-cacheable URL. When set, the client builds a
133
- * token-less URL and caches it indefinitely.
134
- */
135
- public?: boolean;
136
- }
137
-
138
- /**
139
- * @group Models
140
- */
141
- export interface StorageSource {
142
- /**
143
- * Upload an object, specifying a key
144
- * @param file
145
- * @param key
146
- * @param metadata
147
- * @param bucket
148
- */
149
- putObject: ({
150
- file,
151
- key,
152
- metadata,
153
- bucket
154
- }: UploadFileProps) => Promise<UploadFileResult>;
155
-
156
- /**
157
- * Convert a storage key or URL into a download configuration (signed URL equivalent)
158
- * @param keyOrUrl
159
- * @param bucket
160
- */
161
- getSignedUrl: (keyOrUrl: string, bucket?: string) => Promise<DownloadConfig>;
162
-
163
- /**
164
- * Get an object from a storage key.
165
- * It returns null if the object does not exist.
166
- * @param key
167
- * @param bucket
168
- */
169
- getObject: (key: string, bucket?: string) => Promise<File | null>;
170
-
171
- /**
172
- * Delete an object.
173
- * @param key
174
- * @param bucket
175
- */
176
- deleteObject: (key: string, bucket?: string) => Promise<void>;
177
-
178
- /**
179
- * List the contents of a prefix.
180
- * @param prefix
181
- * @param options
182
- */
183
- listObjects: (prefix: string, options?: {
184
- bucket?: string,
185
- maxResults?: number,
186
- pageToken?: string
187
- }) => Promise<StorageListResult>;
188
-
189
- }
190
-
191
- /**
192
- * Result returned by list().
193
- * @public
194
- */
195
- export declare interface StorageListResult {
196
- /**
197
- * References to prefixes (sub-folders). You can call list() on them to
198
- * get its contents.
199
- *
200
- * Folders are implicit based on '/' in the object paths.
201
- * For example, if a bucket has two objects '/a/b/1' and '/a/b/2', list('/a')
202
- * will return '/a/b' as a prefix.
203
- */
204
- prefixes: StorageReference[];
205
- /**
206
- * Objects in this directory.
207
- * You can call getMetadata() and getDownloadUrl() on them.
208
- */
209
- items: StorageReference[];
210
- /**
211
- * If set, there might be more results for this list. Use this token to resume the list.
212
- */
213
- nextPageToken?: string;
214
- }
215
-
216
- /**
217
- * Represents a reference to an S3-compatible storage object. Developers can
218
- * upload, download, and delete objects, as well as get/set object metadata.
219
- * @public
220
- */
221
- export declare interface StorageReference {
222
- /**
223
- * Returns a s3:// URL for this object in the form
224
- * `s3://<bucket>/<path>/<to>/<object>`
225
- * @returns The s3:// URL.
226
- */
227
- toString(): string;
228
-
229
- /**
230
- * A reference to the root of this object's bucket.
231
- */
232
- root: StorageReference;
233
- /**
234
- * The name of the bucket containing this reference's object.
235
- */
236
- bucket: string;
237
- /**
238
- * The full path of this object.
239
- */
240
- fullPath: string;
241
- /**
242
- * The short name of this object, which is the last component of the full path.
243
- * For example, if path is 'full/path/image.png', name is 'image.png'.
244
- */
245
- name: string;
246
-
247
- /**
248
- * A reference pointing to the parent location of this reference, or null if
249
- * this reference is the root.
250
- */
251
- parent: StorageReference | null;
252
- }
package/src/errors.ts DELETED
@@ -1,119 +0,0 @@
1
- /**
2
- * The error codes every route can produce, as `RebaseApiError.code`.
3
- *
4
- * These are the defaults on `ApiError`'s static constructors server-side, so
5
- * any endpoint can answer with one. They are **not** the complete set: routes
6
- * pass their own more specific codes too (`EMAIL_EXISTS`, `TOKEN_EXPIRED`,
7
- * `INVALID_BULK_BODY`, …), and auth alone defines a couple of dozen.
8
- *
9
- * Hence the union is deliberately open rather than closed. It exists to give
10
- * autocomplete and to catch a typo in the common cases — `code` was a bare
11
- * `string`, so `e.code === "NOT_FOUND"` and `e.code === "NOTFOUND"` were
12
- * equally valid and only one of them worked. Closing it would be a lie that
13
- * broke the moment a route added a code.
14
- *
15
- * @example
16
- * if (e instanceof RebaseApiError) {
17
- * switch (e.code) {
18
- * case "NOT_FOUND": return null; // completed
19
- * case "FORBIDDEN": return redirect();
20
- * default: throw e; // routes' own codes land here
21
- * }
22
- * }
23
- *
24
- * @group Errors
25
- */
26
- export type RebaseErrorCode =
27
- | "BAD_REQUEST"
28
- | "UNAUTHORIZED"
29
- | "FORBIDDEN"
30
- | "NOT_FOUND"
31
- | "CONFLICT"
32
- | "INTERNAL_ERROR"
33
- | "SERVICE_UNAVAILABLE"
34
- | "DB_PERMISSION_DENIED"
35
- | "SCHEMA_DRIFT"
36
- // `string & {}` keeps the union open while preserving completion on the
37
- // literals above — a bare `| string` would collapse them and offer nothing.
38
- | (string & {});
39
-
40
- /**
41
- * Structured initializer for {@link RebaseApiError}.
42
- *
43
- * @group Errors
44
- */
45
- export interface RebaseErrorInit {
46
- /**
47
- * HTTP status code, when the error originated from an HTTP response.
48
- * Left `undefined` for realtime/WebSocket, network, and client-side
49
- * logic errors that have no HTTP status.
50
- */
51
- status?: number;
52
- /** Stable, machine-readable error code. See {@link RebaseErrorCode}. */
53
- code?: RebaseErrorCode;
54
- /** Structured error payload returned by the server, when present. */
55
- details?: unknown;
56
- /** The underlying error this one wraps, if any. */
57
- cause?: unknown;
58
- }
59
-
60
- /**
61
- * The single error type thrown across the entire Rebase client surface —
62
- * HTTP data/control-plane calls, realtime/WebSocket operations, and
63
- * client-side logic errors (e.g. an unknown collection accessor). A `catch`
64
- * block only ever needs to check for this one class:
65
- *
66
- * ```ts
67
- * import { RebaseApiError } from "@rebasepro/client"; // re-exported
68
- *
69
- * try {
70
- * await client.data.products.update(id, { price: 9 });
71
- * } catch (e) {
72
- * if (e instanceof RebaseApiError) {
73
- * if (e.status === 404) { ... } // HTTP failures carry a status
74
- * console.error(e.code, e.details);
75
- * }
76
- * }
77
- * ```
78
- *
79
- * `status` is present for HTTP failures and `undefined` otherwise, so its
80
- * presence distinguishes transport-level errors from realtime/logic errors.
81
- *
82
- * @group Errors
83
- */
84
- export class RebaseApiError extends Error {
85
- /** HTTP status code, or `undefined` for non-HTTP errors. */
86
- readonly status?: number;
87
- /** Stable machine-readable error code, when the server supplied one. See {@link RebaseErrorCode}. */
88
- readonly code?: RebaseErrorCode;
89
- /** Structured error payload from the server, when present. */
90
- readonly details?: unknown;
91
-
92
- constructor(message: string, init: RebaseErrorInit = {}) {
93
- super(message);
94
- this.name = "RebaseApiError";
95
- this.status = init.status;
96
- this.code = init.code;
97
- this.details = init.details;
98
- if (init.cause !== undefined) {
99
- // `cause` is standard on Error but not always in the lib target's type.
100
- (this as { cause?: unknown }).cause = init.cause;
101
- }
102
- }
103
- }
104
-
105
- /**
106
- * Client-side logic error — raised before any request is made (e.g. accessing
107
- * an unknown collection accessor when a typed dictionary is configured).
108
- *
109
- * A subclass of {@link RebaseApiError} (with no `status`), so a single
110
- * `catch (e) { if (e instanceof RebaseApiError) ... }` handles it too.
111
- *
112
- * @group Errors
113
- */
114
- export class RebaseClientError extends RebaseApiError {
115
- constructor(message: string) {
116
- super(message);
117
- this.name = "RebaseClientError";
118
- }
119
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from "./errors";
2
- export * from "./call_context";
3
- export * from "./types";
4
- export * from "./controllers";
5
- export * from "./users";
@@ -1,209 +0,0 @@
1
- /**
2
- * The keys of a collection's admin block, as data.
3
- *
4
- * There is no *type* for the block in this package any more, and that is the point:
5
- * `admin` is not declared on `BaseCollectionConfig` or on any property here, so a
6
- * BaaS install cannot even write one. `@rebasepro/cms-types` adds the field back by
7
- * declaration merging, which is why installing it is what makes the admin surface
8
- * appear.
9
- *
10
- * The *list* still has to live here, because three runtime consumers need it and two
11
- * of them are core — see below.
12
- */
13
-
14
- /**
15
- * Every key that belongs inside a collection's `admin` block, as data.
16
- *
17
- * The type that describes these fields is `AdminCollectionOptions` in
18
- * `@rebasepro/cms-types`, and it is erased at build time — but three runtime
19
- * consumers need the list, and two of them are core:
20
- *
21
- * - `serializeCollections`, to drop the block from the contract
22
- * - the ts-morph schema editor in `@rebasepro/server`, which rewrites collection
23
- * files on disk from the admin panel and has to know where each key goes. A key
24
- * missing from this list gets written to the *top level* of the file, where the
25
- * backend ignores it and the panel never finds it again.
26
- * - the `collections-admin-block` codemod
27
- *
28
- * `@rebasepro/cms-types` re-exports this and asserts it names only real option
29
- * keys; the count is pinned by a test there.
30
- *
31
- * @group Models
32
- */
33
- export const ADMIN_COLLECTION_KEYS = [
34
- "Actions",
35
- "additionalFields",
36
- "alwaysApplyDefaultValues",
37
- "components",
38
- "customViews",
39
- "defaultEntityAction",
40
- "defaultFilter",
41
- "defaultSelectedView",
42
- "defaultSize",
43
- "defaultViewMode",
44
- "disableDefaultActions",
45
- "display",
46
- "enabledViews",
47
- "entityActions",
48
- "entityViews",
49
- "exportable",
50
- "filterPresets",
51
- "fixedFilter",
52
- "form",
53
- "formAutoSave",
54
- "formView",
55
- "group",
56
- "hideFromEntityViews",
57
- "hideFromNavigation",
58
- "hideIdFromCollection",
59
- "hideIdFromForm",
60
- "icon",
61
- "includeJsonView",
62
- "inlineEditing",
63
- "kanban",
64
- "listProperties",
65
- "localChangesBackup",
66
- "openEntityMode",
67
- "orderProperty",
68
- "pagination",
69
- "previewProperties",
70
- "propertiesOrder",
71
- "selectionController",
72
- "selectionEnabled",
73
- "sideDialogWidth",
74
- "sort"
75
- ] as const;
76
-
77
- /** A key of a collection's `admin` block. @group Models */
78
- export type AdminCollectionKey = typeof ADMIN_COLLECTION_KEYS[number];
79
-
80
- /**
81
- * Every key that belongs inside a *property's* `admin` block, as data.
82
- *
83
- * The union of `AdminPropertyOptions` and its per-type extensions
84
- * (`AdminStringOptions`, `AdminArrayOptions`, …) in `@rebasepro/cms-types`.
85
- * It lives here for the same reason {@link ADMIN_COLLECTION_KEYS} does: the
86
- * runtime consumers are core packages that the BaaS guard forbids from
87
- * importing `@rebasepro/cms-types`. Here it is the boot-time collection
88
- * validator in `@rebasepro/server`, which has to tell "you left `readOnly` at
89
- * the top of the property, where nothing reads it" apart from "you invented a
90
- * key we have never heard of".
91
- *
92
- * `@rebasepro/cms-types` re-exports this and asserts it names only real
93
- * option keys.
94
- *
95
- * @group Models
96
- */
97
- export const ADMIN_PROPERTY_KEYS = [
98
- "canAddElements",
99
- "clearable",
100
- "columnWidth",
101
- "customProps",
102
- "disabled",
103
- "expanded",
104
- "Field",
105
- "Filter",
106
- "filterOperators",
107
- "fixedFilter",
108
- "hideFromCollection",
109
- "includeEntityLink",
110
- "includeId",
111
- "markdown",
112
- "minimalistView",
113
- "multiline",
114
- "Preview",
115
- "previewAsTag",
116
- "previewProperties",
117
- "readOnly",
118
- "sortable",
119
- "span",
120
- "spreadChildren",
121
- "urlPreview",
122
- "widget",
123
- ] as const;
124
-
125
- /** A key of a property's `admin` block. @group Models */
126
- export type AdminPropertyKey = typeof ADMIN_PROPERTY_KEYS[number];
127
-
128
- /**
129
- * Move flattened admin keys back down into the `admin` block.
130
- *
131
- * The admin panel works with a *flat* view model — the block merged onto the
132
- * collection — so what comes back from a form has `icon` and `defaultViewMode`
133
- * at the top level while `admin` still holds whatever the file was loaded with.
134
- * This is the way back.
135
- *
136
- * **The top-level value wins.** It is the one the form just wrote; the block is
137
- * the copy the collection was loaded with, and preferring it resolves every edit
138
- * in favour of the value the user changed away from.
139
- *
140
- * This lives here, next to the key lists, because it had two implementations —
141
- * `toAdminCollectionConfig` in `@rebasepro/cms-types` and `nestAdminKeys` in
142
- * `@rebasepro/server`'s schema editor — that agreed on everything except that
143
- * precedence, which is the only part that decides whether a save is visible.
144
- *
145
- * @group Models
146
- */
147
- export function nestAdminKeysOf(
148
- source: Record<string, unknown>,
149
- adminKeys: readonly string[]
150
- ): Record<string, unknown> {
151
- const keys = new Set<string>(adminKeys);
152
- const top: Record<string, unknown> = {};
153
- const block: Record<string, unknown> = { ...((source.admin as Record<string, unknown> | undefined) ?? {}) };
154
-
155
- for (const [key, value] of Object.entries(source)) {
156
- if (key === "admin") continue;
157
- if (keys.has(key)) block[key] = value;
158
- else top[key] = value;
159
- }
160
-
161
- if (Object.keys(block).length > 0) top.admin = block;
162
- return top;
163
- }
164
-
165
- /**
166
- * {@link nestAdminKeysOf} for a collection.
167
- *
168
- * @group Models
169
- */
170
- export function nestAdminCollectionKeys(collection: Record<string, unknown>): Record<string, unknown> {
171
- return nestAdminKeysOf(collection, ADMIN_COLLECTION_KEYS);
172
- }
173
-
174
- /**
175
- * {@link nestAdminKeysOf} for a property, applied to its children too.
176
- *
177
- * A map property carries `properties`, an array property carries `of`, and both
178
- * hold properties with `admin` blocks of their own. A flat `readOnly` left on a
179
- * child is as dead — and as fatal at the next boot — as one left on the parent,
180
- * so the walk goes all the way down.
181
- *
182
- * @group Models
183
- */
184
- export function nestAdminPropertyKeys(property: Record<string, unknown>): Record<string, unknown> {
185
- const nested = nestAdminKeysOf(property, ADMIN_PROPERTY_KEYS);
186
-
187
- const children = nested.properties;
188
- if (children && typeof children === "object" && !Array.isArray(children)) {
189
- nested.properties = Object.fromEntries(
190
- Object.entries(children as Record<string, unknown>).map(([key, child]) => [
191
- key,
192
- child && typeof child === "object" && !Array.isArray(child)
193
- ? nestAdminPropertyKeys(child as Record<string, unknown>)
194
- : child
195
- ])
196
- );
197
- }
198
-
199
- const of = nested.of;
200
- if (Array.isArray(of)) {
201
- nested.of = of.map(entry => entry && typeof entry === "object" && !Array.isArray(entry)
202
- ? nestAdminPropertyKeys(entry as Record<string, unknown>)
203
- : entry);
204
- } else if (of && typeof of === "object") {
205
- nested.of = nestAdminPropertyKeys(of as Record<string, unknown>);
206
- }
207
-
208
- return nested;
209
- }
@@ -1,108 +0,0 @@
1
- /**
2
- * Service API keys — machine-to-machine authentication for scripts, cron jobs
3
- * and third-party integrations.
4
- *
5
- * The wire contract lives here because all three sides need it and used to
6
- * declare it separately: `@rebasepro/server` implements the routes,
7
- * `@rebasepro/client` calls them, and {@link ApiKeysAPI} types the SDK surface.
8
- * The client's copy had already drifted — it never gained `admin`.
9
- *
10
- * The database row itself (`ApiKey`, which carries `key_hash`) stays in the
11
- * server package: nothing off the server may see it.
12
- */
13
-
14
- /**
15
- * A single permission entry scoping an API key to a collection and set of
16
- * operations.
17
- *
18
- * Use `"*"` as the collection value to grant access to all collections (and all
19
- * custom functions). Custom functions are addressed with the `functions`
20
- * namespace: `"functions"` grants every function, `"functions/<name>"` grants a
21
- * single one.
22
- *
23
- * @group Models
24
- */
25
- export interface ApiKeyPermission {
26
- /** Collection slug, `"functions"`/`"functions/<name>"`, or `"*"` for everything. */
27
- collection: string;
28
- /** Allowed operations on the collection. */
29
- operations: ("read" | "write" | "delete")[];
30
- }
31
-
32
- /**
33
- * An API key with the secret portion masked — what list / get / update return.
34
- * @group Models
35
- */
36
- export interface ApiKeyMasked {
37
- id: string;
38
- name: string;
39
- /** First 12 characters of the plaintext key, for display only. */
40
- key_prefix: string;
41
- permissions: ApiKeyPermission[];
42
- /**
43
- * When true, the key is granted the `admin` role: it passes the admin-gated
44
- * routes (users, roles, cron, backups, logs, API keys) and the RLS
45
- * `default_admin` policies. Non-admin keys carry only the `service` role —
46
- * RLS grants them nothing unless a collection policy names that role.
47
- */
48
- admin: boolean;
49
- /**
50
- * Requests per 15-minute window. `null` means "no per-key override" — the
51
- * data rate limiter then applies its default API-key limit (1000/window
52
- * unless configured otherwise), not unlimited.
53
- */
54
- rate_limit: number | null;
55
- created_by: string;
56
- created_at: string;
57
- updated_at: string;
58
- last_used_at: string | null;
59
- expires_at: string | null;
60
- revoked_at: string | null;
61
- }
62
-
63
- /**
64
- * Returned exactly once, when a key is created. The `key` field holds the full
65
- * plaintext key — it is never stored or returned again.
66
- * @group Models
67
- */
68
- export interface ApiKeyWithSecret extends ApiKeyMasked {
69
- /** Full plaintext API key (e.g. `rk_live_abc123...`). */
70
- key: string;
71
- }
72
-
73
- /**
74
- * Payload for creating a new API key.
75
- * @group Models
76
- */
77
- export interface CreateApiKeyRequest {
78
- name: string;
79
- permissions: ApiKeyPermission[];
80
- /** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
81
- admin?: boolean;
82
- /** Requests per 15-minute window. Omit or `null` for the server default. */
83
- rate_limit?: number | null;
84
- /** ISO-8601 expiration timestamp. Omit for no expiration. */
85
- expires_at?: string | null;
86
- }
87
-
88
- /**
89
- * Payload for updating an existing API key. Only the fields provided change.
90
- * @group Models
91
- */
92
- export interface UpdateApiKeyRequest {
93
- name?: string;
94
- permissions?: ApiKeyPermission[];
95
- /** When true, grants the `admin` role. See {@link ApiKeyMasked.admin}. */
96
- admin?: boolean;
97
- rate_limit?: number | null;
98
- expires_at?: string | null;
99
- }
100
-
101
- /** @group Models */
102
- export interface ApiKeysAPI {
103
- listKeys(): Promise<{ keys: ApiKeyMasked[] }>;
104
- getKey(id: string): Promise<{ key: ApiKeyMasked }>;
105
- createKey(data: CreateApiKeyRequest): Promise<{ key: ApiKeyWithSecret }>;
106
- updateKey(id: string, data: UpdateApiKeyRequest): Promise<{ key: ApiKeyMasked }>;
107
- revokeKey(id: string): Promise<{ success: boolean }>;
108
- }