@rebasepro/types 0.6.1 → 0.8.0

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 (49) hide show
  1. package/dist/controllers/client.d.ts +69 -1
  2. package/dist/controllers/data.d.ts +19 -47
  3. package/dist/controllers/navigation.d.ts +14 -14
  4. package/dist/controllers/registry.d.ts +8 -4
  5. package/dist/index.es.js +164 -10
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +171 -9
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/types/api_keys.d.ts +57 -0
  10. package/dist/types/auth_adapter.d.ts +66 -4
  11. package/dist/types/backend.d.ts +5 -0
  12. package/dist/types/collections.d.ts +200 -90
  13. package/dist/types/data_source.d.ts +79 -3
  14. package/dist/types/entity_actions.d.ts +2 -2
  15. package/dist/types/entity_callbacks.d.ts +18 -6
  16. package/dist/types/entity_views.d.ts +1 -1
  17. package/dist/types/filter-operators.d.ts +108 -0
  18. package/dist/types/index.d.ts +4 -2
  19. package/dist/types/plugins.d.ts +1 -1
  20. package/dist/types/policy.d.ts +137 -0
  21. package/dist/types/properties.d.ts +122 -37
  22. package/dist/types/property_config.d.ts +1 -1
  23. package/dist/types/storage_source.d.ts +83 -0
  24. package/dist/types/translations.d.ts +8 -0
  25. package/package.json +1 -1
  26. package/src/controllers/client.ts +69 -1
  27. package/src/controllers/data.ts +20 -59
  28. package/src/controllers/navigation.ts +17 -16
  29. package/src/controllers/registry.ts +10 -4
  30. package/src/types/api_keys.ts +52 -0
  31. package/src/types/auth_adapter.ts +80 -4
  32. package/src/types/backend.ts +6 -1
  33. package/src/types/collections.ts +235 -113
  34. package/src/types/data_source.ts +89 -5
  35. package/src/types/entity_actions.tsx +2 -2
  36. package/src/types/entity_callbacks.ts +18 -7
  37. package/src/types/entity_views.tsx +1 -1
  38. package/src/types/filter-operators.ts +167 -0
  39. package/src/types/index.ts +5 -2
  40. package/src/types/plugins.tsx +1 -1
  41. package/src/types/policy.ts +173 -0
  42. package/src/types/properties.ts +132 -39
  43. package/src/types/property_config.tsx +0 -1
  44. package/src/types/storage_source.ts +90 -0
  45. package/src/types/translations.ts +8 -0
  46. package/dist/types/backend_hooks.d.ts +0 -109
  47. package/dist/types/entity_overrides.d.ts +0 -10
  48. package/src/types/backend_hooks.ts +0 -114
  49. package/src/types/entity_overrides.tsx +0 -11
@@ -39,6 +39,82 @@ export interface DataSourceCapabilities {
39
39
  * @group Models
40
40
  */
41
41
  export type DataSourceFeatures = Omit<DataSourceCapabilities, "key" | "label">;
42
+ /**
43
+ * The default data-source key, used when a collection does not name a
44
+ * `dataSource`. Shared by the frontend router and the backend driver
45
+ * registry so both agree on "the default database".
46
+ * @group Models
47
+ */
48
+ export declare const DEFAULT_DATA_SOURCE_KEY = "(default)";
49
+ /**
50
+ * How the *frontend* reaches a data source.
51
+ *
52
+ * - `"server"` — through the Rebase backend (the `RebaseClient`). The backend
53
+ * holds the actual database adapter and routes by data-source key. This is
54
+ * the default and covers Postgres, MongoDB, and any other server-mediated
55
+ * engine.
56
+ * - `"direct"` — straight from the client to the external backend via its own
57
+ * SDK driver (e.g. Firestore). The Rebase backend is not in the data path.
58
+ * - `"custom"` — a developer-supplied {@link DataDriver}, transport unspecified.
59
+ *
60
+ * @group Models
61
+ */
62
+ export type DataSourceTransport = "server" | "direct" | "custom";
63
+ /**
64
+ * Declarative definition of a data source — a named place data lives.
65
+ *
66
+ * Declared once and shared front and back: the frontend uses it to decide
67
+ * transport (client vs direct driver), the backend uses the same `key` to
68
+ * resolve a database adapter, and the editor derives capabilities from
69
+ * `engine`. Collections reference a definition by its `key` via
70
+ * `collection.dataSource`.
71
+ *
72
+ * @group Models
73
+ */
74
+ export interface DataSourceDefinition {
75
+ /**
76
+ * Unique identifier for this data source. Collections point at it via
77
+ * `dataSource`. Defaults to {@link DEFAULT_DATA_SOURCE_KEY}.
78
+ */
79
+ key: string;
80
+ /**
81
+ * The engine backing this data source (e.g. `"postgres"`, `"mongodb"`,
82
+ * `"firestore"`, or a custom id). Determines the
83
+ * {@link DataSourceCapabilities} surfaced in the editor.
84
+ */
85
+ engine: string;
86
+ /**
87
+ * How the frontend reaches this source. Defaults to `"server"`.
88
+ */
89
+ transport: DataSourceTransport;
90
+ /**
91
+ * The physical database/schema/Firestore-database within the engine.
92
+ * Threaded to drivers/adapters as the existing `databaseId` runtime
93
+ * parameter. Defaults to the engine's own default.
94
+ */
95
+ databaseId?: string;
96
+ /** Human-readable label for the UI. */
97
+ label?: string;
98
+ }
99
+ /**
100
+ * The resolved data source for a collection: the single source of truth that
101
+ * the frontend router, backend registry, and editor all derive from.
102
+ * Produced by `resolveDataSource(collection, registry)`.
103
+ *
104
+ * @group Models
105
+ */
106
+ export interface ResolvedDataSource {
107
+ /** Data-source key (routing key, shared front + back). */
108
+ key: string;
109
+ /** Engine backing the source (drives capabilities). */
110
+ engine: string;
111
+ /** Frontend transport. */
112
+ transport: DataSourceTransport;
113
+ /** Within-engine instance, if any (the `databaseId` runtime param). */
114
+ databaseId?: string;
115
+ /** Capabilities derived from {@link engine}. */
116
+ capabilities: DataSourceCapabilities;
117
+ }
42
118
  /** @group Models */
43
119
  export declare const POSTGRES_CAPABILITIES: DataSourceCapabilities;
44
120
  /** @group Models */
@@ -52,11 +128,11 @@ export declare const MONGODB_CAPABILITIES: DataSourceCapabilities;
52
128
  */
53
129
  export declare const DEFAULT_CAPABILITIES: DataSourceCapabilities;
54
130
  /**
55
- * Look up capabilities for a given driver key.
56
- * If `driver` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
131
+ * Look up capabilities for a given engine key.
132
+ * If `engine` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
57
133
  * @group Models
58
134
  */
59
- export declare function getDataSourceCapabilities(driver?: string): DataSourceCapabilities;
135
+ export declare function getDataSourceCapabilities(engine?: string): DataSourceCapabilities;
60
136
  /**
61
137
  * Register custom capabilities for a third-party driver.
62
138
  * @group Models
@@ -59,7 +59,7 @@ export interface EntityAction<M extends Record<string, unknown> = Record<string,
59
59
  }
60
60
  export type EntityActionClickProps<M extends Record<string, unknown>, USER extends User = User> = {
61
61
  entity?: Entity<M>;
62
- context: RebaseContext<USER>;
62
+ context?: RebaseContext<USER>;
63
63
  path?: string;
64
64
  collection?: EntityCollection<M>;
65
65
  /**
@@ -78,7 +78,7 @@ export type EntityActionClickProps<M extends Record<string, unknown>, USER exten
78
78
  /**
79
79
  * If the action is rendered in the form, is it open in a side panel or full screen?
80
80
  */
81
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
81
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
82
82
  /**
83
83
  * Optional selection controller, present if the action is being called from a collection view
84
84
  */
@@ -3,14 +3,24 @@ import type { Entity, EntityStatus, EntityValues } from "./entities";
3
3
  import type { User } from "../users";
4
4
  import type { RebaseCallContext } from "../rebase_context";
5
5
  /**
6
- * This interface defines all the callbacks that can be used when an entity
7
- * is being created, updated or deleted.
8
- * Useful for adding your own logic or blocking the execution of the operation.
6
+ * Lifecycle callbacks for entity CRUD operations.
7
+ *
8
+ * Register per-collection on the collection's `callbacks` field, or globally
9
+ * via `initBackend({ callbacks })`. Fires on **every** data path — REST API,
10
+ * WebSocket / realtime subscriptions, and server-side `rebase.data`.
11
+ *
12
+ * When both global and per-collection callbacks are registered, execution
13
+ * order is: **global → collection → property callbacks**.
14
+ *
9
15
  * @group Models
10
16
  */
11
17
  export type EntityCallbacks<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {
12
18
  /**
13
- * Callback used after fetching data
19
+ * Callback used after fetching data.
20
+ *
21
+ * Fires on every read path. Use this for security-critical redaction
22
+ * (PII masking, row filtering) — no read path bypasses it.
23
+ *
14
24
  * @param props
15
25
  */
16
26
  afterRead?(props: EntityAfterReadProps<M, USER>): Promise<Entity<M>> | Entity<M>;
@@ -19,11 +29,13 @@ export type EntityCallbacks<M extends Record<string, unknown> = Record<string, u
19
29
  * saved. If you throw an error in this method the process stops, and an
20
30
  * error snackbar gets displayed.
21
31
  * This runs after schema validation.
32
+ *
22
33
  * @param props
23
34
  */
24
35
  beforeSave?(props: EntityBeforeSaveProps<M, USER>): Promise<Partial<EntityValues<M>>> | Partial<EntityValues<M>>;
25
36
  /**
26
- * Callback used when save is successful
37
+ * Callback used when save is successful.
38
+ *
27
39
  * @param props
28
40
  */
29
41
  afterSave?(props: EntityAfterSaveProps<M, USER>): Promise<void> | void;
@@ -45,7 +57,7 @@ export type EntityCallbacks<M extends Record<string, unknown> = Record<string, u
45
57
  *
46
58
  * @param props
47
59
  */
48
- afterDelete?(props: EntityAfterDeleteProps<M, USER>): void;
60
+ afterDelete?(props: EntityAfterDeleteProps<M, USER>): Promise<void> | void;
49
61
  };
50
62
  /**
51
63
  * Parameters passed to hooks when an entity is fetched
@@ -43,7 +43,7 @@ export interface FormContext<M extends Record<string, unknown> = Record<string,
43
43
  status: "new" | "existing" | "copy";
44
44
  entity?: Entity<M>;
45
45
  savingError?: Error;
46
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
46
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
47
47
  /**
48
48
  * The underlying formex controller that powers the form.
49
49
  */
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Canonical filter operators and REST wire-format mappings.
3
+ *
4
+ * `WhereFilterOp` is THE operator type used at every layer — from React
5
+ * components through the SDK, server, and down to the database driver.
6
+ *
7
+ * PostgREST short-codes (`eq`, `gt`, `cs`, …) exist **only** at the
8
+ * HTTP wire boundary, handled by `serializeFilter` / `deserializeFilter`
9
+ * in `@rebasepro/common`.
10
+ *
11
+ * ┌──────────────────┬───────────────┬──────────────────────────┐
12
+ * │ Canonical │ REST short │ Meaning │
13
+ * ├──────────────────┼───────────────┼──────────────────────────┤
14
+ * │ "==" │ "eq" │ Equal │
15
+ * │ "!=" │ "neq" │ Not equal │
16
+ * │ ">" │ "gt" │ Greater than │
17
+ * │ ">=" │ "gte" │ Greater than or equal │
18
+ * │ "<" │ "lt" │ Less than │
19
+ * │ "<=" │ "lte" │ Less than or equal │
20
+ * │ "in" │ "in" │ Value in list │
21
+ * │ "not-in" │ "nin" │ Value not in list │
22
+ * │ "array-contains" │ "cs" │ Array contains element │
23
+ * │ "array-contains-any" │ "csa" │ Array contains any of │
24
+ * └──────────────────┴───────────────┴──────────────────────────┘
25
+ *
26
+ * @module
27
+ */
28
+ /**
29
+ * Canonical filter operators supported across all database backends.
30
+ * Each DB driver translates these to its native query format.
31
+ *
32
+ * @group Models
33
+ */
34
+ export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
35
+ /**
36
+ * Used to define filters applied in collections.
37
+ *
38
+ * A single condition is a tuple `[operator, value]`.
39
+ * Multiple conditions on the same field use an array of tuples.
40
+ *
41
+ * @example
42
+ * // Single condition per field
43
+ * { status: ["==", "active"], price: [">=", 9.99] }
44
+ *
45
+ * // Multiple conditions on one field
46
+ * { age: [[">=", 18], ["<", 65]] }
47
+ *
48
+ * // Array operators
49
+ * { role: ["in", ["admin", "editor"]] }
50
+ * { tags: ["array-contains", "featured"] }
51
+ *
52
+ * @group Models
53
+ */
54
+ export type FilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;
55
+ /**
56
+ * Relaxed filter type that also accepts pre-serialized PostgREST strings.
57
+ * **Internal only** — used at the wire-format boundary
58
+ * (`serializeFilter` / `deserializeFilter` in `@rebasepro/common`).
59
+ *
60
+ * Application code, UI components, and SDK consumers should use
61
+ * {@link FilterValues} instead.
62
+ *
63
+ * @internal
64
+ */
65
+ export type WireFilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][] | string>>;
66
+ /**
67
+ * A pre-defined filter preset for quick access in the collection toolbar.
68
+ * Users can select a preset to instantly apply a set of filters and
69
+ * optionally a sort order.
70
+ *
71
+ * @group Models
72
+ */
73
+ export interface FilterPreset<Key extends string = string> {
74
+ /**
75
+ * Display label shown in the preset menu.
76
+ * If omitted, a summary is auto-generated from the filter keys.
77
+ */
78
+ label?: string;
79
+ /**
80
+ * The filter values to apply when this preset is selected.
81
+ */
82
+ filterValues: FilterValues<Key>;
83
+ /**
84
+ * Optional sort override to apply alongside the filter values.
85
+ */
86
+ sort?: [Key, "asc" | "desc"];
87
+ }
88
+ /**
89
+ * PostgREST short-code operators. Wire format only — these never appear
90
+ * in application code. Used by `serializeFilter`/`deserializeFilter`
91
+ * in `@rebasepro/common`.
92
+ */
93
+ export type RestFilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "cs" | "csa";
94
+ /** Maps canonical operators to their REST short-code equivalents. */
95
+ export declare const CANONICAL_TO_REST: Readonly<Record<WhereFilterOp, RestFilterOp>>;
96
+ /** Maps REST short-code operators to their canonical equivalents. */
97
+ export declare const REST_TO_CANONICAL: Readonly<Record<RestFilterOp, WhereFilterOp>>;
98
+ /**
99
+ * Resolve any operator string (canonical or REST short-code) to its
100
+ * canonical `WhereFilterOp` form. Returns `undefined` for unknown operators.
101
+ *
102
+ * @example
103
+ * toCanonicalOp("==") // "=="
104
+ * toCanonicalOp("eq") // "=="
105
+ * toCanonicalOp("cs") // "array-contains"
106
+ * toCanonicalOp("xyz") // undefined
107
+ */
108
+ export declare function toCanonicalOp(op: string): WhereFilterOp | undefined;
@@ -1,13 +1,14 @@
1
1
  export * from "./entities";
2
+ export * from "./filter-operators";
2
3
  export * from "./chips";
3
4
  export * from "./properties";
4
5
  export * from "./collections";
5
6
  export * from "./relations";
7
+ export * from "./policy";
6
8
  export * from "./locales";
7
9
  export * from "./entity_link_builder";
8
10
  export * from "./user_management_delegate";
9
11
  export * from "./entity_callbacks";
10
- export * from "./entity_overrides";
11
12
  export * from "./export_import";
12
13
  export * from "./modify_collections";
13
14
  export * from "./formex";
@@ -21,10 +22,11 @@ export * from "./entity_actions";
21
22
  export * from "./property_config";
22
23
  export * from "./entity_views";
23
24
  export * from "./data_source";
25
+ export * from "./storage_source";
24
26
  export * from "./cron";
25
- export * from "./backend_hooks";
26
27
  export * from "./component_ref";
27
28
  export * from "./auth_adapter";
28
29
  export * from "./database_adapter";
29
30
  export * from "./breadcrumbs";
30
31
  export * from "./component_overrides";
32
+ export * from "./api_keys";
@@ -245,7 +245,7 @@ export interface PluginFormActionProps<USER extends User = User, EC extends Enti
245
245
  disabled: boolean;
246
246
  formContext?: FormContext;
247
247
  context: RebaseContext<USER>;
248
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
248
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
249
249
  }
250
250
  /**
251
251
  * Parameters passed to the field builder wrap function.
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Structured, engine-agnostic policy expressions.
3
+ *
4
+ * A {@link PolicyExpression} is the single source of truth for a row-level
5
+ * security condition. It is compiled to Postgres `USING`/`WITH CHECK` SQL
6
+ * (authoritative enforcement) and independently evaluated in JavaScript (to
7
+ * drive the admin UI, and — in future — to enforce on engines without native
8
+ * RLS such as MongoDB). Because both the SQL and the JS decision derive from
9
+ * the *same* expression, the UI matches database enforcement by construction —
10
+ * no drift between two hand-written implementations.
11
+ *
12
+ * The only escape hatch that cannot be evaluated client-side is the
13
+ * {@link RawPolicyExpression} node (`{ kind: "raw" }`): it preserves full
14
+ * PostgreSQL power but, being arbitrary SQL, is treated as *unknown* by the
15
+ * JavaScript evaluator (never silently allowed) and reflected exactly in the UI
16
+ * via server-computed capability flags.
17
+ *
18
+ * @group Models
19
+ */
20
+ export type PolicyExpression = TruePolicyExpression | FalsePolicyExpression | AndPolicyExpression | OrPolicyExpression | NotPolicyExpression | ComparePolicyExpression | RolesOverlapPolicyExpression | RolesContainPolicyExpression | AuthenticatedPolicyExpression | RawPolicyExpression;
21
+ /** Always allows. Compiles to `true`. @group Models */
22
+ export interface TruePolicyExpression {
23
+ kind: "true";
24
+ }
25
+ /** Always denies. Compiles to `false`. @group Models */
26
+ export interface FalsePolicyExpression {
27
+ kind: "false";
28
+ }
29
+ /** Logical AND — every operand must pass. @group Models */
30
+ export interface AndPolicyExpression {
31
+ kind: "and";
32
+ operands: PolicyExpression[];
33
+ }
34
+ /** Logical OR — at least one operand must pass. @group Models */
35
+ export interface OrPolicyExpression {
36
+ kind: "or";
37
+ operands: PolicyExpression[];
38
+ }
39
+ /** Logical negation. @group Models */
40
+ export interface NotPolicyExpression {
41
+ kind: "not";
42
+ operand: PolicyExpression;
43
+ }
44
+ /** Comparison operators available to {@link ComparePolicyExpression}. @group Models */
45
+ export type PolicyCompareOperator = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
46
+ /**
47
+ * Compares two operands, e.g. `owner_id = auth.uid()`.
48
+ * @group Models
49
+ */
50
+ export interface ComparePolicyExpression {
51
+ kind: "compare";
52
+ op: PolicyCompareOperator;
53
+ left: PolicyOperand;
54
+ right: PolicyOperand;
55
+ }
56
+ /**
57
+ * True when the user holds *at least one* of the given application roles.
58
+ * Compiles to `string_to_array(auth.roles(), ',') && ARRAY[...]`.
59
+ * @group Models
60
+ */
61
+ export interface RolesOverlapPolicyExpression {
62
+ kind: "rolesOverlap";
63
+ roles: string[];
64
+ }
65
+ /**
66
+ * True when the user holds *all* of the given application roles.
67
+ * Compiles to `string_to_array(auth.roles(), ',') @> ARRAY[...]`.
68
+ * @group Models
69
+ */
70
+ export interface RolesContainPolicyExpression {
71
+ kind: "rolesContain";
72
+ roles: string[];
73
+ }
74
+ /**
75
+ * True when there is an authenticated user (`auth.uid() IS NOT NULL`).
76
+ * @group Models
77
+ */
78
+ export interface AuthenticatedPolicyExpression {
79
+ kind: "authenticated";
80
+ }
81
+ /**
82
+ * A raw PostgreSQL boolean expression — the full-power escape hatch.
83
+ *
84
+ * Columns can be referenced as `{column_name}`. This is Postgres-only and
85
+ * **server-authoritative**: the JavaScript evaluator cannot evaluate arbitrary
86
+ * SQL, so it treats this node as *unknown* rather than guessing.
87
+ * @group Models
88
+ */
89
+ export interface RawPolicyExpression {
90
+ kind: "raw";
91
+ sql: string;
92
+ }
93
+ /**
94
+ * An operand referenced by a {@link ComparePolicyExpression}.
95
+ * @group Models
96
+ */
97
+ export type PolicyOperand = FieldPolicyOperand | LiteralPolicyOperand | AuthUidPolicyOperand | AuthRolesPolicyOperand;
98
+ /** A column value on the row being evaluated. @group Models */
99
+ export interface FieldPolicyOperand {
100
+ kind: "field";
101
+ /** The property/column name (resolved to its DB column when compiled). */
102
+ name: string;
103
+ }
104
+ /** A constant value. @group Models */
105
+ export interface LiteralPolicyOperand {
106
+ kind: "literal";
107
+ value: string | number | boolean | null;
108
+ }
109
+ /** The current user's id — compiles to `auth.uid()`. @group Models */
110
+ export interface AuthUidPolicyOperand {
111
+ kind: "authUid";
112
+ }
113
+ /**
114
+ * The current user's roles as an array — compiles to
115
+ * `string_to_array(auth.roles(), ',')`.
116
+ * @group Models
117
+ */
118
+ export interface AuthRolesPolicyOperand {
119
+ kind: "authRoles";
120
+ }
121
+ /** @group Models */
122
+ export declare const policy: {
123
+ true: () => TruePolicyExpression;
124
+ false: () => FalsePolicyExpression;
125
+ and: (...operands: PolicyExpression[]) => AndPolicyExpression;
126
+ or: (...operands: PolicyExpression[]) => OrPolicyExpression;
127
+ not: (operand: PolicyExpression) => NotPolicyExpression;
128
+ compare: (left: PolicyOperand, op: PolicyCompareOperator, right: PolicyOperand) => ComparePolicyExpression;
129
+ rolesOverlap: (roles: string[]) => RolesOverlapPolicyExpression;
130
+ rolesContain: (roles: string[]) => RolesContainPolicyExpression;
131
+ authenticated: () => AuthenticatedPolicyExpression;
132
+ raw: (sql: string) => RawPolicyExpression;
133
+ field: (name: string) => FieldPolicyOperand;
134
+ literal: (value: string | number | boolean | null) => LiteralPolicyOperand;
135
+ authUid: () => AuthUidPolicyOperand;
136
+ authRoles: () => AuthRolesPolicyOperand;
137
+ };