@rebasepro/types 0.8.0 → 0.9.1-canary.09aaf62

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 (88) hide show
  1. package/README.md +13 -13
  2. package/dist/controllers/auth.d.ts +7 -1
  3. package/dist/controllers/client.d.ts +204 -6
  4. package/dist/controllers/collection_registry.d.ts +3 -3
  5. package/dist/controllers/customization_controller.d.ts +1 -1
  6. package/dist/controllers/data.d.ts +309 -35
  7. package/dist/controllers/data_driver.d.ts +92 -37
  8. package/dist/controllers/email.d.ts +2 -2
  9. package/dist/controllers/index.d.ts +1 -1
  10. package/dist/controllers/local_config_persistence.d.ts +4 -4
  11. package/dist/controllers/navigation.d.ts +2 -2
  12. package/dist/controllers/registry.d.ts +21 -8
  13. package/dist/controllers/{side_entity_controller.d.ts → side_panel_controller.d.ts} +7 -7
  14. package/dist/controllers/storage.d.ts +39 -0
  15. package/dist/errors.d.ts +64 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.es.js +160 -15
  18. package/dist/index.es.js.map +1 -1
  19. package/dist/rebase_context.d.ts +8 -4
  20. package/dist/types/auth_adapter.d.ts +29 -4
  21. package/dist/types/backend.d.ts +33 -26
  22. package/dist/types/backup.d.ts +20 -0
  23. package/dist/types/builders.d.ts +2 -2
  24. package/dist/types/collections.d.ts +84 -75
  25. package/dist/types/component_overrides.d.ts +61 -3
  26. package/dist/types/cron.d.ts +11 -2
  27. package/dist/types/data_source.d.ts +15 -2
  28. package/dist/types/database_adapter.d.ts +21 -4
  29. package/dist/types/entities.d.ts +7 -7
  30. package/dist/types/entity_actions.d.ts +7 -7
  31. package/dist/types/entity_callbacks.d.ts +39 -39
  32. package/dist/types/entity_views.d.ts +3 -3
  33. package/dist/types/filter-operators.d.ts +62 -17
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/modify_collections.d.ts +2 -2
  36. package/dist/types/plugins.d.ts +9 -9
  37. package/dist/types/policy.d.ts +111 -11
  38. package/dist/types/properties.d.ts +54 -9
  39. package/dist/types/relations.d.ts +3 -3
  40. package/dist/types/slots.d.ts +14 -14
  41. package/dist/types/translations.d.ts +5 -1
  42. package/dist/types/user_management_delegate.d.ts +8 -2
  43. package/dist/types/websockets.d.ts +46 -13
  44. package/dist/users/user.d.ts +21 -9
  45. package/package.json +5 -6
  46. package/src/controllers/auth.tsx +7 -1
  47. package/src/controllers/client.ts +235 -7
  48. package/src/controllers/collection_registry.ts +3 -3
  49. package/src/controllers/customization_controller.tsx +1 -1
  50. package/src/controllers/data.ts +330 -39
  51. package/src/controllers/data_driver.ts +93 -40
  52. package/src/controllers/email.ts +2 -2
  53. package/src/controllers/index.ts +1 -1
  54. package/src/controllers/local_config_persistence.tsx +4 -4
  55. package/src/controllers/navigation.ts +2 -2
  56. package/src/controllers/registry.ts +22 -8
  57. package/src/controllers/{side_entity_controller.tsx → side_panel_controller.tsx} +7 -7
  58. package/src/controllers/storage.ts +60 -1
  59. package/src/errors.ts +80 -0
  60. package/src/index.ts +1 -0
  61. package/src/rebase_context.tsx +8 -4
  62. package/src/types/auth_adapter.ts +29 -4
  63. package/src/types/backend.ts +44 -36
  64. package/src/types/backup.ts +26 -0
  65. package/src/types/builders.ts +2 -2
  66. package/src/types/collections.ts +101 -91
  67. package/src/types/component_overrides.ts +72 -5
  68. package/src/types/cron.ts +11 -2
  69. package/src/types/data_source.ts +24 -2
  70. package/src/types/database_adapter.ts +19 -4
  71. package/src/types/entities.ts +7 -7
  72. package/src/types/entity_actions.tsx +7 -7
  73. package/src/types/entity_callbacks.ts +42 -42
  74. package/src/types/entity_views.tsx +3 -3
  75. package/src/types/filter-operators.ts +96 -23
  76. package/src/types/index.ts +1 -0
  77. package/src/types/modify_collections.tsx +2 -2
  78. package/src/types/plugins.tsx +9 -9
  79. package/src/types/policy.ts +114 -9
  80. package/src/types/properties.ts +58 -9
  81. package/src/types/relations.ts +3 -3
  82. package/src/types/slots.tsx +14 -14
  83. package/src/types/translations.ts +5 -1
  84. package/src/types/user_management_delegate.ts +8 -2
  85. package/src/types/websockets.ts +43 -14
  86. package/src/users/user.ts +22 -9
  87. package/dist/index.umd.js +0 -458
  88. package/dist/index.umd.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Email service types — portable interface shared by RebaseClient and server-core.
2
+ * Email service types — portable interface shared by RebaseClient and server.
3
3
  *
4
- * The concrete SMTP implementation lives in `@rebasepro/server-core/email`.
4
+ * The concrete SMTP implementation lives in `@rebasepro/server/email`.
5
5
  * This file provides only the consumer-facing contract so that it can be
6
6
  * referenced from `RebaseClient` without dragging in nodemailer.
7
7
  */
@@ -11,7 +11,7 @@ export * from "./storage";
11
11
  export * from "./email";
12
12
  export * from "./client";
13
13
  export * from "./customization_controller";
14
- export * from "./side_entity_controller";
14
+ export * from "./side_panel_controller";
15
15
  export * from "./side_dialogs_controller";
16
16
  export * from "./dialogs_controller";
17
17
  export * from "./snackbar";
@@ -1,16 +1,16 @@
1
- import type { EntityCollection } from "../types/collections";
1
+ import type { CollectionConfig } from "../types/collections";
2
2
  /**
3
3
  * @group Models
4
4
  */
5
- export type PartialEntityCollection<M extends Record<string, unknown> = Record<string, unknown>> = Partial<EntityCollection<M>>;
5
+ export type PartialCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>> = Partial<CollectionConfig<M>>;
6
6
  /**
7
7
  * This interface is in charge of defining the controller that persists
8
8
  * modifications to a collection or collection, and retrieves them back from
9
9
  * a data source, such as local storage or Firestore.
10
10
  */
11
11
  export interface UserConfigurationPersistence {
12
- onCollectionModified: <M extends Record<string, unknown> = Record<string, unknown>>(path: string, partialCollection: PartialEntityCollection<M>) => void;
13
- getCollectionConfig: <M extends Record<string, unknown> = Record<string, unknown>>(path: string) => PartialEntityCollection<M>;
12
+ onCollectionModified: <M extends Record<string, unknown> = Record<string, unknown>>(path: string, partialCollection: PartialCollectionConfig<M>) => void;
13
+ getCollectionConfig: <M extends Record<string, unknown> = Record<string, unknown>>(path: string) => PartialCollectionConfig<M>;
14
14
  recentlyVisitedPaths: string[];
15
15
  setRecentlyVisitedPaths: (paths: string[]) => void;
16
16
  favouritePaths: string[];
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EntityCollection } from "../types/collections";
2
+ import type { CollectionConfig } from "../types/collections";
3
3
  /**
4
4
  * Controller that handles URL path building and resolution.
5
5
  * @group Models
@@ -212,7 +212,7 @@ export interface NavigationEntry {
212
212
  name: string;
213
213
  slug: string;
214
214
  type: "collection" | "view" | "admin";
215
- collection?: EntityCollection;
215
+ collection?: CollectionConfig;
216
216
  view?: AppView;
217
217
  description?: string;
218
218
  group: string;
@@ -1,12 +1,12 @@
1
1
  import { ReactNode } from "react";
2
- import type { EntityCollection } from "../types/collections";
3
- import type { EntityCollectionsBuilder, AppViewsBuilder } from "../types/builders";
2
+ import type { CollectionConfig } from "../types/collections";
3
+ import type { CollectionConfigsBuilder, AppViewsBuilder } from "../types/builders";
4
4
  import type { EntityCustomView } from "../types/entity_views";
5
5
  import type { EntityAction } from "../types/entity_actions";
6
6
  import type { AppView, NavigationGroupMapping } from "./navigation";
7
7
  /**
8
8
  * Options to enable the built-in collection editor.
9
- * When provided to `<RebaseCMS>`, the editor is auto-wired as a native feature.
9
+ * When provided to `<RebaseAdmin>`, the editor is auto-wired as a native feature.
10
10
  */
11
11
  export interface CollectionEditorOptions {
12
12
  /**
@@ -19,8 +19,8 @@ export interface CollectionEditorOptions {
19
19
  /** Suggested base paths shown when creating new collections. */
20
20
  pathSuggestions?: string[];
21
21
  }
22
- export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection> {
23
- collections?: EC[] | EntityCollectionsBuilder<EC>;
22
+ export interface RebaseAdminConfig<EC extends CollectionConfig = CollectionConfig> {
23
+ collections?: EC[] | CollectionConfigsBuilder<EC>;
24
24
  /**
25
25
  * Custom top-level views added to the main navigation.
26
26
  * Accepts a static array of views or an async builder function
@@ -45,9 +45,22 @@ export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection>
45
45
  * are all auto-wired — no plugin or manual view injection needed.
46
46
  */
47
47
  collectionEditor?: boolean | CollectionEditorOptions;
48
+ /**
49
+ * URL path prefix the admin is mounted under, when it does not live at the
50
+ * site root. Set this when the admin is rendered inside a path-prefixed
51
+ * route (e.g. `<Route path="/admin/*">`) so URL⇄collection resolution
52
+ * accounts for the prefix — otherwise the current path won't be recognized
53
+ * as a collection path and views hang on a spinner with no data fetch.
54
+ *
55
+ * Do NOT set this when mounting via a react-router `basename` — react-router
56
+ * already strips the prefix from the location, so the default (`/`) is correct.
57
+ *
58
+ * @default "/"
59
+ */
60
+ basePath?: string;
48
61
  }
49
62
  export interface RebaseStudioConfig {
50
- tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs" | "api-keys")[];
63
+ tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "backups" | "api" | "logs" | "api-keys")[];
51
64
  homePage?: ReactNode;
52
65
  devViews?: AppView[];
53
66
  }
@@ -55,10 +68,10 @@ export interface RebaseAuthConfig {
55
68
  loginView?: ReactNode;
56
69
  }
57
70
  export interface RebaseRegistryController {
58
- cmsConfig: RebaseCMSConfig | null;
71
+ cmsConfig: RebaseAdminConfig | null;
59
72
  studioConfig: RebaseStudioConfig | null;
60
73
  authConfig: RebaseAuthConfig | null;
61
- registerCMS: (config: RebaseCMSConfig) => void;
74
+ registerCMS: (config: RebaseAdminConfig) => void;
62
75
  unregisterCMS: () => void;
63
76
  registerStudio: (config: RebaseStudioConfig) => void;
64
77
  unregisterStudio: () => void;
@@ -1,10 +1,10 @@
1
1
  import type { Entity } from "../types/entities";
2
- import type { EntityCollection } from "../types/collections";
2
+ import type { CollectionConfig } from "../types/collections";
3
3
  /**
4
4
  * Props used to open a side dialog
5
5
  * @group Hooks and utilities
6
6
  */
7
- export interface EntitySidePanelProps<M extends Record<string, unknown> = Record<string, unknown>> {
7
+ export interface SidePanelBindingProps<M extends Record<string, unknown> = Record<string, unknown>> {
8
8
  /**
9
9
  * Absolute path of the entity
10
10
  */
@@ -31,7 +31,7 @@ export interface EntitySidePanelProps<M extends Record<string, unknown> = Record
31
31
  * Collection representing the entities of this view.
32
32
  * If you leave it blank it will be induced by your navigation
33
33
  */
34
- collection?: EntityCollection<M>;
34
+ collection?: CollectionConfig<M>;
35
35
  /**
36
36
  * Should update the URL when opening the dialog.
37
37
  * Consider that if the collection that you provide is not defined in the base
@@ -74,7 +74,7 @@ export interface EntitySidePanelProps<M extends Record<string, unknown> = Record
74
74
  * Controller to open the side dialog displaying entity forms
75
75
  * @group Hooks and utilities
76
76
  */
77
- export interface SideEntityController {
77
+ export interface SidePanelController {
78
78
  /**
79
79
  * Close the last panel
80
80
  */
@@ -84,14 +84,14 @@ export interface SideEntityController {
84
84
  * of the view is fetched from the collections you have specified in the
85
85
  * navigation.
86
86
  * At least you need to pass the path of the entity you would like
87
- * to edit. You can set an entityId if you would like to edit and existing one
87
+ * to edit. You can set a entityId if you would like to edit and existing one
88
88
  * (or a new one with that id).
89
89
  * @param props
90
90
  */
91
- open: <M extends Record<string, unknown> = Record<string, unknown>>(props: EntitySidePanelProps<M>) => void;
91
+ open: <M extends Record<string, unknown> = Record<string, unknown>>(props: SidePanelBindingProps<M>) => void;
92
92
  /**
93
93
  * Replace the last open entity panel with the given one.
94
94
  * @param props
95
95
  */
96
- replace: <M extends Record<string, unknown> = Record<string, unknown>>(props: EntitySidePanelProps<M>) => void;
96
+ replace: <M extends Record<string, unknown> = Record<string, unknown>>(props: SidePanelBindingProps<M>) => void;
97
97
  }
@@ -1,3 +1,20 @@
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 declare const PUBLIC_STORAGE_PREFIX = "public/";
10
+ /**
11
+ * True when a storage key/path points at a public object (lives under
12
+ * {@link PUBLIC_STORAGE_PREFIX}). The check is applied to the key *within the
13
+ * bucket* — strip any `bucket/` and `scheme://` prefixes first.
14
+ *
15
+ * @group Models
16
+ */
17
+ export declare function isPublicStoragePath(path: string | null | undefined): boolean;
1
18
  /**
2
19
  * @group Models
3
20
  */
@@ -6,6 +23,13 @@ export interface UploadFileProps {
6
23
  key: string;
7
24
  metadata?: Record<string, unknown>;
8
25
  bucket?: string;
26
+ /**
27
+ * Store this object as **public**: it is placed under
28
+ * {@link PUBLIC_STORAGE_PREFIX} and served via a stable, token-less,
29
+ * permanent URL (safe to persist in a database and cache on a CDN).
30
+ * Defaults to `false` (private, short-lived signed URLs).
31
+ */
32
+ public?: boolean;
9
33
  }
10
34
  /**
11
35
  * @group Models
@@ -67,6 +91,21 @@ export declare interface DownloadMetadata {
67
91
  */
68
92
  contentType: string;
69
93
  customMetadata: Record<string, unknown>;
94
+ /**
95
+ * Optional short-lived download token (for local/server-mediated storage).
96
+ * Absent for public objects, which need no token.
97
+ */
98
+ token?: string;
99
+ /**
100
+ * Optional remaining lifetime of the token, in seconds.
101
+ */
102
+ tokenExpiresIn?: number;
103
+ /**
104
+ * True when this object is public: it is served without a token via a
105
+ * stable, permanent, CDN-cacheable URL. When set, the client builds a
106
+ * token-less URL and caches it indefinitely.
107
+ */
108
+ public?: boolean;
70
109
  }
71
110
  /**
72
111
  * @group Models
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Structured initializer for {@link RebaseApiError}.
3
+ *
4
+ * @group Errors
5
+ */
6
+ export interface RebaseErrorInit {
7
+ /**
8
+ * HTTP status code, when the error originated from an HTTP response.
9
+ * Left `undefined` for realtime/WebSocket, network, and client-side
10
+ * logic errors that have no HTTP status.
11
+ */
12
+ status?: number;
13
+ /** Stable, machine-readable error code (e.g. `"NOT_FOUND"`, `"BAD_REQUEST"`). */
14
+ code?: string;
15
+ /** Structured error payload returned by the server, when present. */
16
+ details?: unknown;
17
+ /** The underlying error this one wraps, if any. */
18
+ cause?: unknown;
19
+ }
20
+ /**
21
+ * The single error type thrown across the entire Rebase client surface —
22
+ * HTTP data/control-plane calls, realtime/WebSocket operations, and
23
+ * client-side logic errors (e.g. an unknown collection accessor). A `catch`
24
+ * block only ever needs to check for this one class:
25
+ *
26
+ * ```ts
27
+ * import { RebaseApiError } from "@rebasepro/client"; // re-exported
28
+ *
29
+ * try {
30
+ * await client.data.products.update(id, { price: 9 });
31
+ * } catch (e) {
32
+ * if (e instanceof RebaseApiError) {
33
+ * if (e.status === 404) { ... } // HTTP failures carry a status
34
+ * console.error(e.code, e.details);
35
+ * }
36
+ * }
37
+ * ```
38
+ *
39
+ * `status` is present for HTTP failures and `undefined` otherwise, so its
40
+ * presence distinguishes transport-level errors from realtime/logic errors.
41
+ *
42
+ * @group Errors
43
+ */
44
+ export declare class RebaseApiError extends Error {
45
+ /** HTTP status code, or `undefined` for non-HTTP errors. */
46
+ readonly status?: number;
47
+ /** Stable machine-readable error code, when the server supplied one. */
48
+ readonly code?: string;
49
+ /** Structured error payload from the server, when present. */
50
+ readonly details?: unknown;
51
+ constructor(message: string, init?: RebaseErrorInit);
52
+ }
53
+ /**
54
+ * Client-side logic error — raised before any request is made (e.g. accessing
55
+ * an unknown collection accessor when a typed dictionary is configured).
56
+ *
57
+ * A subclass of {@link RebaseApiError} (with no `status`), so a single
58
+ * `catch (e) { if (e instanceof RebaseApiError) ... }` handles it too.
59
+ *
60
+ * @group Errors
61
+ */
62
+ export declare class RebaseClientError extends RebaseApiError {
63
+ constructor(message: string);
64
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./errors";
1
2
  export * from "./rebase_context";
2
3
  export * from "./types";
3
4
  export * from "./controllers";
package/dist/index.es.js CHANGED
@@ -1,6 +1,63 @@
1
+ //#region src/errors.ts
2
+ /**
3
+ * The single error type thrown across the entire Rebase client surface —
4
+ * HTTP data/control-plane calls, realtime/WebSocket operations, and
5
+ * client-side logic errors (e.g. an unknown collection accessor). A `catch`
6
+ * block only ever needs to check for this one class:
7
+ *
8
+ * ```ts
9
+ * import { RebaseApiError } from "@rebasepro/client"; // re-exported
10
+ *
11
+ * try {
12
+ * await client.data.products.update(id, { price: 9 });
13
+ * } catch (e) {
14
+ * if (e instanceof RebaseApiError) {
15
+ * if (e.status === 404) { ... } // HTTP failures carry a status
16
+ * console.error(e.code, e.details);
17
+ * }
18
+ * }
19
+ * ```
20
+ *
21
+ * `status` is present for HTTP failures and `undefined` otherwise, so its
22
+ * presence distinguishes transport-level errors from realtime/logic errors.
23
+ *
24
+ * @group Errors
25
+ */
26
+ var RebaseApiError = class extends Error {
27
+ /** HTTP status code, or `undefined` for non-HTTP errors. */
28
+ status;
29
+ /** Stable machine-readable error code, when the server supplied one. */
30
+ code;
31
+ /** Structured error payload from the server, when present. */
32
+ details;
33
+ constructor(message, init = {}) {
34
+ super(message);
35
+ this.name = "RebaseApiError";
36
+ this.status = init.status;
37
+ this.code = init.code;
38
+ this.details = init.details;
39
+ if (init.cause !== void 0) this.cause = init.cause;
40
+ }
41
+ };
42
+ /**
43
+ * Client-side logic error — raised before any request is made (e.g. accessing
44
+ * an unknown collection accessor when a typed dictionary is configured).
45
+ *
46
+ * A subclass of {@link RebaseApiError} (with no `status`), so a single
47
+ * `catch (e) { if (e instanceof RebaseApiError) ... }` handles it too.
48
+ *
49
+ * @group Errors
50
+ */
51
+ var RebaseClientError = class extends RebaseApiError {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = "RebaseClientError";
55
+ }
56
+ };
57
+ //#endregion
1
58
  //#region src/types/entities.ts
2
59
  /**
3
- * Class used to create a reference to an entity in a different path.
60
+ * Class used to create a reference to a entity in a different path.
4
61
  *
5
62
  * @example
6
63
  * // Simple reference (most common case - single driver, single db)
@@ -34,7 +91,7 @@ var EntityReference = class {
34
91
  */
35
92
  databaseId;
36
93
  /**
37
- * Create a reference to an entity.
94
+ * Create a reference to a entity.
38
95
  *
39
96
  * @example
40
97
  * // Simple reference (most common case)
@@ -68,7 +125,7 @@ var EntityReference = class {
68
125
  }
69
126
  };
70
127
  /**
71
- * Class used to create a reference to an entity in a different path
128
+ * Class used to create a reference to a entity in a different path
72
129
  */
73
130
  var EntityRelation = class {
74
131
  __type = "relation";
@@ -134,7 +191,13 @@ var CANONICAL_TO_REST = {
134
191
  "in": "in",
135
192
  "not-in": "nin",
136
193
  "array-contains": "cs",
137
- "array-contains-any": "csa"
194
+ "array-contains-any": "csa",
195
+ "like": "like",
196
+ "ilike": "ilike",
197
+ "not-like": "nlike",
198
+ "not-ilike": "nilike",
199
+ "is-null": "isnull",
200
+ "is-not-null": "notnull"
138
201
  };
139
202
  /** Maps REST short-code operators to their canonical equivalents. */
140
203
  var REST_TO_CANONICAL = {
@@ -147,10 +210,26 @@ var REST_TO_CANONICAL = {
147
210
  "in": "in",
148
211
  "nin": "not-in",
149
212
  "cs": "array-contains",
150
- "csa": "array-contains-any"
213
+ "csa": "array-contains-any",
214
+ "like": "like",
215
+ "ilike": "ilike",
216
+ "nlike": "not-like",
217
+ "nilike": "not-ilike",
218
+ "isnull": "is-null",
219
+ "notnull": "is-not-null"
151
220
  };
152
- /** All canonical operator strings for runtime validation. */
153
- var CANONICAL_OPS = new Set([
221
+ /**
222
+ * Operators that test for null/not-null and therefore ignore their value.
223
+ * Codecs normalize the value of these conditions to `null`.
224
+ */
225
+ var NULL_OPS = new Set(["is-null", "is-not-null"]);
226
+ /**
227
+ * Every canonical operator, in a stable order. Useful for engine capability
228
+ * declarations ({@link DataSourceCapabilities.filterOperators}) and for
229
+ * building operator subsets.
230
+ * @group Models
231
+ */
232
+ var ALL_WHERE_FILTER_OPS = [
154
233
  "<",
155
234
  "<=",
156
235
  "==",
@@ -160,8 +239,16 @@ var CANONICAL_OPS = new Set([
160
239
  "in",
161
240
  "not-in",
162
241
  "array-contains",
163
- "array-contains-any"
164
- ]);
242
+ "array-contains-any",
243
+ "like",
244
+ "ilike",
245
+ "not-like",
246
+ "not-ilike",
247
+ "is-null",
248
+ "is-not-null"
249
+ ];
250
+ /** All canonical operator strings for runtime validation. */
251
+ var CANONICAL_OPS = new Set(ALL_WHERE_FILTER_OPS);
165
252
  /**
166
253
  * Resolve any operator string (canonical or REST short-code) to its
167
254
  * canonical `WhereFilterOp` form. Returns `undefined` for unknown operators.
@@ -183,21 +270,21 @@ function toCanonicalOp(op) {
183
270
  * Returns true if the collection uses the Postgres engine (or the default engine).
184
271
  * @group Models
185
272
  */
186
- function isPostgresCollection(collection) {
273
+ function isPostgresCollectionConfig(collection) {
187
274
  return !collection.engine || collection.engine === "postgres";
188
275
  }
189
276
  /**
190
277
  * Type guard for Firebase / Firestore collections.
191
278
  * @group Models
192
279
  */
193
- function isFirebaseCollection(collection) {
280
+ function isFirebaseCollectionConfig(collection) {
194
281
  return collection.engine === "firestore";
195
282
  }
196
283
  /**
197
284
  * Type guard for MongoDB collections.
198
285
  * @group Models
199
286
  */
200
- function isMongoDBCollection(collection) {
287
+ function isMongoDBCollectionConfig(collection) {
201
288
  return collection.engine === "mongodb";
202
289
  }
203
290
  /**
@@ -206,8 +293,8 @@ function isMongoDBCollection(collection) {
206
293
  * otherwise falls back to `slug`.
207
294
  */
208
295
  function getCollectionDataPath(collection) {
209
- if (isFirebaseCollection(collection) && collection.path) return collection.path;
210
- if (isMongoDBCollection(collection) && collection.path) return collection.path;
296
+ if (isFirebaseCollectionConfig(collection) && collection.path) return collection.path;
297
+ if (isMongoDBCollectionConfig(collection) && collection.path) return collection.path;
211
298
  return collection.slug;
212
299
  }
213
300
  /**
@@ -225,6 +312,23 @@ function getDeclaredSubcollections(collection) {
225
312
  }
226
313
  //#endregion
227
314
  //#region src/types/policy.ts
315
+ /**
316
+ * The id a request without a logged-in user reports as `auth.uid()`.
317
+ *
318
+ * A user-context request always sets `app.user_id`: blank would read back as
319
+ * `NULL`, and `NULL` is how the trusted server context is recognised, so an
320
+ * anonymous visitor would be promoted to server privileges. The driver
321
+ * therefore substitutes this sentinel at the single chokepoint where the GUC
322
+ * is set.
323
+ *
324
+ * The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
325
+ * tautology on the user path** — it is true for anonymous visitors too. Use
326
+ * {@link policy.authenticated} (or `auth.uid() <> 'anonymous'`) to mean "signed
327
+ * in", and {@link policy.serverContext} to mean "the trusted server context".
328
+ *
329
+ * @group Models
330
+ */
331
+ var ANONYMOUS_USER_ID = "anonymous";
228
332
  /** @group Models */
229
333
  var policy = {
230
334
  true: () => ({ kind: "true" }),
@@ -256,6 +360,12 @@ var policy = {
256
360
  roles
257
361
  }),
258
362
  authenticated: () => ({ kind: "authenticated" }),
363
+ serverContext: () => ({ kind: "serverContext" }),
364
+ existsIn: (args) => ({
365
+ kind: "existsIn",
366
+ collection: args.collection,
367
+ where: args.where
368
+ }),
259
369
  raw: (sql) => ({
260
370
  kind: "raw",
261
371
  sql
@@ -264,6 +374,10 @@ var policy = {
264
374
  kind: "field",
265
375
  name
266
376
  }),
377
+ outerField: (name) => ({
378
+ kind: "outerField",
379
+ name
380
+ }),
267
381
  literal: (value) => ({
268
382
  kind: "literal",
269
383
  value
@@ -320,6 +434,7 @@ var POSTGRES_CAPABILITIES = {
320
434
  supportsReferences: false,
321
435
  supportsColumnTypes: true,
322
436
  supportsRealtime: true,
437
+ filterOperators: ALL_WHERE_FILTER_OPS,
323
438
  supportsSQLAdmin: true,
324
439
  supportsDocumentAdmin: false,
325
440
  supportsSchemaAdmin: true
@@ -334,6 +449,7 @@ var FIREBASE_CAPABILITIES = {
334
449
  supportsReferences: true,
335
450
  supportsColumnTypes: false,
336
451
  supportsRealtime: true,
452
+ filterOperators: ALL_WHERE_FILTER_OPS.filter((op) => op !== "like" && op !== "ilike" && op !== "not-like" && op !== "not-ilike"),
337
453
  supportsSQLAdmin: false,
338
454
  supportsDocumentAdmin: false,
339
455
  supportsSchemaAdmin: false
@@ -348,6 +464,7 @@ var MONGODB_CAPABILITIES = {
348
464
  supportsReferences: true,
349
465
  supportsColumnTypes: false,
350
466
  supportsRealtime: false,
467
+ filterOperators: ALL_WHERE_FILTER_OPS,
351
468
  supportsSQLAdmin: false,
352
469
  supportsDocumentAdmin: true,
353
470
  supportsSchemaAdmin: true
@@ -366,6 +483,7 @@ var DEFAULT_CAPABILITIES = {
366
483
  supportsReferences: true,
367
484
  supportsColumnTypes: true,
368
485
  supportsRealtime: true,
486
+ filterOperators: ALL_WHERE_FILTER_OPS,
369
487
  supportsSQLAdmin: true,
370
488
  supportsDocumentAdmin: true,
371
489
  supportsSchemaAdmin: true
@@ -423,6 +541,33 @@ function isLazyComponentRef(ref) {
423
541
  return typeof ref === "object" && ref !== null && "__rebaseLazy" in ref && ref.__rebaseLazy === true;
424
542
  }
425
543
  //#endregion
426
- export { CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_DATA_SOURCE_KEY, DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, MONGODB_CAPABILITIES, POSTGRES_CAPABILITIES, REST_TO_CANONICAL, Vector, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, isBranchAdmin, isDocumentAdmin, isFirebaseCollection, isLazyComponentRef, isMongoDBCollection, isPostgresCollection, isSQLAdmin, isSchemaAdmin, policy, registerDataSourceCapabilities, toCanonicalOp };
544
+ //#region src/controllers/storage.ts
545
+ /**
546
+ * Path prefix that marks an object as **public**. Files stored under this
547
+ * prefix are served without any auth token via a stable, permanent,
548
+ * CDN-cacheable URL (see {@link StorageSource.getSignedUrl}). Shared by the
549
+ * client SDK and the backend so both agree on which objects are public.
550
+ *
551
+ * @group Models
552
+ */
553
+ var PUBLIC_STORAGE_PREFIX = "public/";
554
+ /**
555
+ * True when a storage key/path points at a public object (lives under
556
+ * {@link PUBLIC_STORAGE_PREFIX}). The check is applied to the key *within the
557
+ * bucket* — strip any `bucket/` and `scheme://` prefixes first.
558
+ *
559
+ * @group Models
560
+ */
561
+ function isPublicStoragePath(path) {
562
+ if (!path) return false;
563
+ let p = path;
564
+ const scheme = p.indexOf("://");
565
+ if (scheme !== -1) p = p.substring(scheme + 3);
566
+ p = p.replace(/^\/+/, "");
567
+ if (p.split("/").some((seg) => seg === "..")) return false;
568
+ return p.startsWith("public/") || p.startsWith(`default/public/`);
569
+ }
570
+ //#endregion
571
+ export { ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_DATA_SOURCE_KEY, DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REST_TO_CANONICAL, RebaseApiError, RebaseClientError, Vector, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, isBranchAdmin, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isSQLAdmin, isSchemaAdmin, policy, registerDataSourceCapabilities, toCanonicalOp };
427
572
 
428
573
  //# sourceMappingURL=index.es.js.map