@rebasepro/common 0.5.0 → 0.6.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.
@@ -29,9 +29,13 @@ export declare function getRelationFrom<M extends Record<string, unknown>>(entit
29
29
  * Handles EntityRelation class instances, and plain objects
30
30
  * with `__type === "relation"` or an `isEntityRelation()` method.
31
31
  *
32
+ * When `propertyType` is `"relation"`, also accepts plain objects that
33
+ * have `id` and `path` fields — these are relation-shaped objects from
34
+ * edge cases in the data pipeline (REST fallback, stale cache, custom data source).
35
+ *
32
36
  * Returns null if the value cannot be coerced.
33
37
  */
34
- export declare function normalizeToEntityRelation(value: unknown): EntityRelation | null;
38
+ export declare function normalizeToEntityRelation(value: unknown, propertyType?: string): EntityRelation | null;
35
39
  export declare function traverseValuesProperties<M extends Record<string, unknown>>(inputValues: Partial<EntityValues<M>>, properties: Properties, operation: (value: unknown, property: Property) => unknown): EntityValues<M> | undefined;
36
40
  export declare function traverseValueProperty(inputValue: unknown, property: Property, operation: (value: unknown, property: Property) => unknown): unknown;
37
41
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/common",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.6.1",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -41,27 +41,27 @@
41
41
  "dependencies": {
42
42
  "fast-equals": "6.0.0",
43
43
  "json-logic-js": "^2.0.5",
44
- "@rebasepro/types": "0.5.0",
45
- "@rebasepro/utils": "0.5.0"
44
+ "@rebasepro/types": "0.6.1",
45
+ "@rebasepro/utils": "0.6.1"
46
46
  },
47
47
  "devDependencies": {
48
- "@jest/globals": "^29.7.0",
48
+ "@jest/globals": "^30.4.1",
49
49
  "@testing-library/react": "^16.3.2",
50
50
  "@testing-library/user-event": "^14.6.1",
51
- "@types/jest": "^29.5.14",
52
- "@types/node": "^20.19.41",
51
+ "@types/jest": "^30.0.0",
52
+ "@types/node": "^25.9.3",
53
53
  "@types/object-hash": "^3.0.6",
54
- "@types/react": "^19.2.15",
54
+ "@types/react": "^19.2.17",
55
55
  "@types/react-dom": "^19.2.3",
56
56
  "@types/react-measure": "^2.0.12",
57
- "@vitejs/plugin-react": "^4.7.0",
57
+ "@vitejs/plugin-react": "^6.0.2",
58
58
  "babel-plugin-react-compiler": "beta",
59
- "cross-env": "^7.0.3",
60
- "jest": "^29.7.0",
61
- "ts-jest": "^29.4.10",
62
- "tsd": "^0.31.2",
63
- "typescript": "^5.9.3",
64
- "vite": "^5.4.21"
59
+ "cross-env": "^10.1.0",
60
+ "jest": "^30.4.2",
61
+ "ts-jest": "^29.4.11",
62
+ "tsd": "^0.33.0",
63
+ "typescript": "^6.0.3",
64
+ "vite": "^8.0.16"
65
65
  },
66
66
  "files": [
67
67
  "dist",
@@ -258,7 +258,7 @@ export class CollectionRegistry {
258
258
  joinPath: relProp.joinPath ?? relProp.relation?.joinPath,
259
259
  onUpdate: relProp.onUpdate ?? relProp.relation?.onUpdate,
260
260
  onDelete: relProp.onDelete ?? relProp.relation?.onDelete,
261
- overrides: relProp.overrides ?? relProp.relation?.overrides,
261
+ overrides: relProp.overrides ?? relProp.relation?.overrides
262
262
  });
263
263
  }
264
264
  } else if (property.type === "map" && property.properties) {
@@ -11,6 +11,7 @@ export const defaultUsersCollection: PostgresCollection = {
11
11
  name: "Users",
12
12
  singularName: "User",
13
13
  slug: "users",
14
+ auth: true,
14
15
  table: "users",
15
16
  schema: "rebase",
16
17
  icon: "Users",
@@ -18,8 +19,10 @@ export const defaultUsersCollection: PostgresCollection = {
18
19
  openEntityMode: "dialog",
19
20
  disableDefaultActions: ["copy"],
20
21
  securityRules: [
21
- { operation: "select", roles: ["admin"] },
22
- { operations: ["insert", "update", "delete"], roles: ["admin"] }
22
+ { operation: "select",
23
+ roles: ["admin"] },
24
+ { operations: ["insert", "update", "delete"],
25
+ roles: ["admin"] }
23
26
  ],
24
27
  sort: ["createdAt", "desc"],
25
28
  properties: {
@@ -32,7 +35,8 @@ export const defaultUsersCollection: PostgresCollection = {
32
35
  email: {
33
36
  name: "Email",
34
37
  type: "string",
35
- validation: { required: true, unique: true }
38
+ validation: { required: true,
39
+ unique: true }
36
40
  },
37
41
  displayName: {
38
42
  name: "Name",
@@ -64,32 +68,39 @@ export const defaultUsersCollection: PostgresCollection = {
64
68
  name: "Password Hash",
65
69
  type: "string",
66
70
  columnName: "password_hash",
67
- ui: { hideFromCollection: true, disabled: { hidden: true } }
71
+ ui: { hideFromCollection: true,
72
+ disabled: { hidden: true } }
68
73
  },
69
74
  emailVerified: {
70
75
  name: "Email Verified",
71
76
  type: "boolean",
72
77
  columnName: "email_verified",
73
78
  defaultValue: false,
74
- ui: { hideFromCollection: true, disabled: { hidden: true } }
79
+ ui: { hideFromCollection: true,
80
+ disabled: { hidden: true } }
75
81
  },
76
82
  emailVerificationToken: {
77
83
  name: "Email Verification Token",
78
84
  type: "string",
79
85
  columnName: "email_verification_token",
80
- ui: { hideFromCollection: true, disabled: { hidden: true } }
86
+ ui: { hideFromCollection: true,
87
+ disabled: { hidden: true } }
81
88
  },
82
89
  emailVerificationSentAt: {
83
90
  name: "Email Verification Sent At",
84
91
  type: "date",
85
92
  columnName: "email_verification_sent_at",
86
- ui: { hideFromCollection: true, disabled: { hidden: true } }
93
+ ui: { hideFromCollection: true,
94
+ disabled: { hidden: true } }
87
95
  },
88
96
  metadata: {
89
97
  name: "Metadata",
90
98
  type: "map",
99
+ keyValue: true,
100
+ properties: {},
91
101
  defaultValue: {},
92
- ui: { hideFromCollection: true, disabled: { hidden: true } }
102
+ ui: { hideFromCollection: true,
103
+ disabled: { hidden: true } }
93
104
  },
94
105
  createdAt: {
95
106
  name: "Created At",
@@ -103,7 +114,8 @@ export const defaultUsersCollection: PostgresCollection = {
103
114
  type: "date",
104
115
  columnName: "updated_at",
105
116
  autoValue: "on_update",
106
- ui: { hideFromCollection: true, disabled: { hidden: true } }
117
+ ui: { hideFromCollection: true,
118
+ disabled: { hidden: true } }
107
119
  }
108
120
  },
109
121
  listProperties: ["displayName", "email", "roles", "createdAt"],
@@ -1,15 +1,19 @@
1
1
  import { FindParams, Entity, FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator, LogicalCondition, WhereValue, FilterCondition } from "@rebasepro/types";
2
2
 
3
3
  export function or(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition {
4
- return { type: "or", conditions };
4
+ return { type: "or",
5
+ conditions };
5
6
  }
6
7
 
7
8
  export function and(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition {
8
- return { type: "and", conditions };
9
+ return { type: "and",
10
+ conditions };
9
11
  }
10
12
 
11
13
  export function cond(column: string, operator: FilterOperator, value: unknown): FilterCondition {
12
- return { column, operator, value };
14
+ return { column,
15
+ operator,
16
+ value };
13
17
  }
14
18
 
15
19
  export class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements QueryBuilderInterface<M> {
@@ -156,9 +156,13 @@ export function getRelationFrom<M extends Record<string, unknown>>(entity: Entit
156
156
  * Handles EntityRelation class instances, and plain objects
157
157
  * with `__type === "relation"` or an `isEntityRelation()` method.
158
158
  *
159
+ * When `propertyType` is `"relation"`, also accepts plain objects that
160
+ * have `id` and `path` fields — these are relation-shaped objects from
161
+ * edge cases in the data pipeline (REST fallback, stale cache, custom data source).
162
+ *
159
163
  * Returns null if the value cannot be coerced.
160
164
  */
161
- export function normalizeToEntityRelation(value: unknown): EntityRelation | null {
165
+ export function normalizeToEntityRelation(value: unknown, propertyType?: string): EntityRelation | null {
162
166
  if (value instanceof EntityRelation) return value;
163
167
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
164
168
 
@@ -167,7 +171,8 @@ export function normalizeToEntityRelation(value: unknown): EntityRelation | null
167
171
  obj.__type === "relation" ||
168
172
  obj.__type === "reference" ||
169
173
  (typeof obj.isEntityRelation === "function" && (obj.isEntityRelation as () => boolean)()) ||
170
- (typeof obj.isEntityReference === "function" && (obj.isEntityReference as () => boolean)());
174
+ (typeof obj.isEntityReference === "function" && (obj.isEntityReference as () => boolean)()) ||
175
+ (propertyType === "relation" && typeof obj.id !== "undefined" && typeof obj.path === "string");
171
176
 
172
177
  if (!isRelationLike) return null;
173
178
 
@@ -263,7 +268,9 @@ export interface RelationRefWithData extends RelationRef {
263
268
  * Replaces inline `{ id, path, __type: "relation" }` object literals.
264
269
  */
265
270
  export function createRelationRef(id: string | number, path: string): RelationRef {
266
- return { id, path, __type: "relation" };
271
+ return { id,
272
+ path,
273
+ __type: "relation" };
267
274
  }
268
275
 
269
276
  /**
@@ -271,5 +278,8 @@ export function createRelationRef(id: string | number, path: string): RelationRe
271
278
  * Used when entity data has been pre-fetched (e.g., via batch loading or JOINs).
272
279
  */
273
280
  export function createRelationRefWithData(id: string | number, path: string, data: Entity): RelationRefWithData {
274
- return { id, path, __type: "relation", data };
281
+ return { id,
282
+ path,
283
+ __type: "relation",
284
+ data };
275
285
  }
@@ -19,7 +19,8 @@ export function sanitizeRelation(
19
19
  targetCollection = resolveCollection(rawTarget);
20
20
  }
21
21
  if (!targetCollection) {
22
- targetCollection = { slug: rawTarget, name: rawTarget } as EntityCollection;
22
+ targetCollection = { slug: rawTarget,
23
+ name: rawTarget } as EntityCollection;
23
24
  }
24
25
  } else if (typeof rawTarget === "function") {
25
26
  const evaluated = rawTarget();
@@ -28,7 +29,8 @@ export function sanitizeRelation(
28
29
  targetCollection = resolveCollection(evaluated);
29
30
  }
30
31
  if (!targetCollection) {
31
- targetCollection = { slug: evaluated, name: evaluated } as EntityCollection;
32
+ targetCollection = { slug: evaluated,
33
+ name: evaluated } as EntityCollection;
32
34
  }
33
35
  } else {
34
36
  targetCollection = evaluated;
@@ -295,7 +297,7 @@ export function resolvePropertyRelation({
295
297
  joinPath: relProp.joinPath,
296
298
  onUpdate: relProp.onUpdate,
297
299
  onDelete: relProp.onDelete,
298
- overrides: relProp.overrides,
300
+ overrides: relProp.overrides
299
301
  } as Relation;
300
302
  }
301
303
 
@@ -354,7 +354,7 @@ export function getSubcollections<M extends Record<string, unknown> = Record<str
354
354
  if (getDataSourceCapabilities(collection.driver).supportsRelations) {
355
355
  const resolvedRelations = resolveCollectionRelations(collection);
356
356
  const manyRelations = Object.values(resolvedRelations).filter((r: Relation) => r.cardinality === "many");
357
-
357
+
358
358
  return manyRelations.map((r: Relation) => {
359
359
  const target = r.target();
360
360
  if (!target) return undefined;
@@ -377,7 +377,8 @@ export function getSubcollections<M extends Record<string, unknown> = Record<str
377
377
  baseOverrides.singularName = customName;
378
378
  }
379
379
 
380
- const targetWithOverrides = { ...target, ...baseOverrides };
380
+ const targetWithOverrides = { ...target,
381
+ ...baseOverrides };
381
382
  return (r.overrides ? mergeDeep(targetWithOverrides, r.overrides) : targetWithOverrides) as EntityCollection<Record<string, unknown>>;
382
383
  }).filter((c: EntityCollection<Record<string, unknown>> | undefined): c is EntityCollection<Record<string, unknown>> => Boolean(c));
383
384
  }