@rebasepro/common 0.0.1-canary.eae7889 → 0.1.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/common",
3
3
  "type": "module",
4
- "version": "0.0.1-canary.eae7889",
4
+ "version": "0.1.0",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -39,10 +39,10 @@
39
39
  "./package.json": "./package.json"
40
40
  },
41
41
  "dependencies": {
42
- "fast-equals": "5.3.0",
42
+ "fast-equals": "6.0.0",
43
43
  "json-logic-js": "^2.0.5",
44
- "@rebasepro/utils": "0.0.1-canary.eae7889",
45
- "@rebasepro/types": "0.0.1-canary.eae7889"
44
+ "@rebasepro/types": "0.1.0",
45
+ "@rebasepro/utils": "0.1.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@jest/globals": "^29.7.0",
@@ -62,7 +62,6 @@
62
62
  "jest": "^29.7.0",
63
63
  "npm-run-all": "^4.1.5",
64
64
  "ts-jest": "^29.3.1",
65
- "ts-node": "^10.9.2",
66
65
  "tsd": "^0.31.2",
67
66
  "typescript": "^5.8.3",
68
67
  "vite": "^5.4.17"
@@ -165,7 +165,7 @@ export class CollectionRegistry {
165
165
 
166
166
  // 2. Merge with manual relations[] (manual entries win on name conflict)
167
167
  const relResult = result as CollectionWithRelations;
168
- const manualRelations = getDataSourceCapabilities(result.driver).supportsRelations ? (relResult.relations ?? []) : [];
168
+ const manualRelations = getDataSourceCapabilities(result.driver).supportsRelations ? ((relResult as any).relations ?? []) : [];
169
169
  const mergedRelationsRaw = [...extractedRelations];
170
170
  for (const manual of manualRelations) {
171
171
  const name = manual.relationName;
@@ -192,7 +192,7 @@ export class CollectionRegistry {
192
192
  });
193
193
 
194
194
  // 3. Set the merged relations on the result copy
195
- relResult.relations = mergedRelations;
195
+ (relResult as any).relations = mergedRelations;
196
196
  }
197
197
 
198
198
  // 4. Normalize properties (which stamps relation on each property)
@@ -203,8 +203,8 @@ export class CollectionRegistry {
203
203
  if (!result.childCollections) {
204
204
  if (getDataSourceCapabilities(result.driver).supportsSubcollections && (result as CollectionWithSubcollections).subcollections) {
205
205
  result.childCollections = (result as CollectionWithSubcollections).subcollections;
206
- } else if (getDataSourceCapabilities(result.driver).supportsRelations && relResult.relations) {
207
- const manyRelations = relResult.relations.filter((r: Relation) => r.cardinality === "many");
206
+ } else if (getDataSourceCapabilities(result.driver).supportsRelations && (relResult as any).relations) {
207
+ const manyRelations = (relResult as any).relations.filter((r: Relation) => r.cardinality === "many");
208
208
  if (manyRelations.length > 0) {
209
209
  result.childCollections = () => manyRelations.map((r: Relation) => {
210
210
  const target = r.target();
@@ -375,7 +375,10 @@ export class CollectionRegistry {
375
375
  }
376
376
 
377
377
  // Move to the target collection
378
- currentCollection = relation.target();
378
+ const target = relation.target();
379
+ const targetRelationKey = relation.relationName || target.slug;
380
+ const targetSlug = relation.overrides?.slug ?? targetRelationKey;
381
+ currentCollection = this.get(targetSlug) || this.normalizeCollection(target);
379
382
 
380
383
  // If there are more segments, continue navigation
381
384
  if (i + 1 < pathSegments.length) {
@@ -447,7 +450,7 @@ export class CollectionRegistry {
447
450
  if (!subcollection) {
448
451
  throw new Error(`Subcollection '${subcollectionSlug}' not found in ${currentCollection.slug}`);
449
452
  }
450
- currentCollection = subcollection;
453
+ currentCollection = this.get(subcollection.slug) || this.normalizeCollection(subcollection);
451
454
  collections.push(currentCollection);
452
455
  }
453
456
  }
@@ -482,8 +485,8 @@ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
482
485
  // Remove subcollections/relations from comparison objects (already handled above)
483
486
  delete restA.subcollections;
484
487
  delete restB.subcollections;
485
- delete restA.relations;
486
- delete restB.relations;
488
+ delete (restA as any).relations;
489
+ delete (restB as any).relations;
487
490
  if (!areCollectionListsEqual(subcollectionsA, subcollectionsB)) {
488
491
  return false;
489
492
  }
@@ -178,7 +178,8 @@ export function applyPropertyConditions(
178
178
  if (conditions.disabled) {
179
179
  const isDisabled = evaluateCondition(conditions.disabled, context);
180
180
  if (isDisabled) {
181
- result.disabled = {
181
+ result.ui = result.ui || {};
182
+ result.ui.disabled = {
182
183
  clearOnDisabled: conditions.clearOnDisabled ?? false,
183
184
  disabledMessage: conditions.disabledMessage,
184
185
  hidden: false
@@ -190,8 +191,9 @@ export function applyPropertyConditions(
190
191
  if (conditions.hidden) {
191
192
  const isHidden = evaluateCondition(conditions.hidden, context);
192
193
  if (isHidden) {
193
- result.disabled = {
194
- ...(typeof result.disabled === "object" ? result.disabled : {}),
194
+ result.ui = result.ui || {};
195
+ result.ui.disabled = {
196
+ ...(typeof result.ui?.disabled === "object" ? result.ui.disabled : {}),
195
197
  hidden: true,
196
198
  clearOnDisabled: conditions.clearOnDisabled ?? false
197
199
  };
@@ -202,7 +204,8 @@ export function applyPropertyConditions(
202
204
  if (conditions.readOnly) {
203
205
  const isReadOnly = evaluateCondition(conditions.readOnly, context);
204
206
  if (isReadOnly) {
205
- result.readOnly = true;
207
+ result.ui = result.ui || {};
208
+ result.ui.readOnly = true;
206
209
  }
207
210
  }
208
211
 
@@ -250,7 +253,7 @@ export function applyPropertyConditions(
250
253
  (result as ReferenceProperty).path = evaluateCondition(conditions.referencePath, context) as string;
251
254
  }
252
255
  if (conditions.referenceFilter) {
253
- (result as ReferenceProperty).forceFilter = evaluateCondition(conditions.referenceFilter, context) as ReferenceProperty["forceFilter"];
256
+ (result as ReferenceProperty).fixedFilter = evaluateCondition(conditions.referenceFilter, context) as ReferenceProperty["fixedFilter"];
254
257
  }
255
258
  }
256
259
 
@@ -12,20 +12,20 @@ import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "./common";
12
12
  import { mergeDeep } from "@rebasepro/utils";
13
13
 
14
14
  export function isReadOnly(property: Property): boolean {
15
- if (property.readOnly)
15
+ if (property.ui?.readOnly)
16
16
  return true;
17
17
  if (property.type === "date") {
18
18
  if (property.autoValue)
19
19
  return true;
20
20
  }
21
21
  if (property.type === "reference") {
22
- return !property.path && !("Field" in property && property.Field);
22
+ return !property.path && !("Field" in (property.ui || {}) && property.ui?.Field);
23
23
  }
24
24
  return false;
25
25
  }
26
26
 
27
27
  export function isHidden(property: Property): boolean {
28
- return typeof property.disabled === "object" && Boolean(property.disabled.hidden);
28
+ return typeof property.ui?.disabled === "object" && Boolean(property.ui?.disabled.hidden);
29
29
  }
30
30
 
31
31
  export function isPropertyBuilder(property?: Property) {
@@ -19,7 +19,7 @@ export function getEntityImagePreviewPropertyKey<M extends Record<string, unknow
19
19
  // also check for URL properties with image preview type
20
20
  for (const key in collection.properties) {
21
21
  const property = collection.properties[key];
22
- if (property.type === "string" && property.url === "image") {
22
+ if (property.type === "string" && property.ui?.url === "image") {
23
23
  return key;
24
24
  }
25
25
  }
@@ -41,7 +41,7 @@ export function sanitizeRelation(relation: Partial<Relation>, sourceCollection:
41
41
 
42
42
  try {
43
43
  // Look for an owning relation on the target that points back to this collection
44
- const targetRelations = getDataSourceCapabilities(targetCollection.driver).supportsRelations ? ((targetCollection as CollectionWithRelations).relations || []) : [];
44
+ const targetRelations = getDataSourceCapabilities(targetCollection.driver).supportsRelations ? (((targetCollection as any).relations) || []) : [];
45
45
  for (const targetRel of targetRelations) {
46
46
  if (targetRel.direction === "owning" &&
47
47
  targetRel.cardinality === "one" &&
@@ -85,7 +85,7 @@ export function sanitizeRelation(relation: Partial<Relation>, sourceCollection:
85
85
  // Note: we intentionally do NOT require `through` here because the raw (unsanitized)
86
86
  // relations won't have `through` populated yet — sanitizeRelation fills it in later.
87
87
  // `cardinality: "many" + direction: "owning"` is sufficient to identify owning M2M.
88
- const targetRelations = getDataSourceCapabilities(targetCollection.driver).supportsRelations ? ((targetCollection as CollectionWithRelations).relations || []) : [];
88
+ const targetRelations = getDataSourceCapabilities(targetCollection.driver).supportsRelations ? (((targetCollection as any).relations) || []) : [];
89
89
  for (const targetRel of targetRelations) {
90
90
  if (targetRel.cardinality === "many" &&
91
91
  (targetRel.direction === "owning" || !targetRel.direction) &&
@@ -152,8 +152,8 @@ export function resolveCollectionRelations(
152
152
 
153
153
  // 1. Process explicit relations from the `relations` field.
154
154
  // Each relation is stored once under its canonical relationName key.
155
- if (relCollection.relations) {
156
- relCollection.relations.forEach((relation: Relation) => {
155
+ if ((relCollection as any).relations) {
156
+ (relCollection as any).relations.forEach((relation: Relation) => {
157
157
  const normalizedRelation = sanitizeRelation(relation, collection);
158
158
  const relationKey = normalizedRelation.relationName;
159
159
  if (relationKey) {
@@ -232,7 +232,7 @@ export function resolvePropertyRelation({
232
232
  }
233
233
 
234
234
  // 2. Fall back to lookup from collection.relations[] (backward compat)
235
- const relation = ((sourceCollection as CollectionWithRelations).relations ?? []).find((rel: Relation) => rel.relationName === relProp.relationName)
235
+ const relation = (((sourceCollection as any).relations) ?? []).find((rel: Relation) => rel.relationName === relProp.relationName)
236
236
  if (!relation) {
237
237
  console.warn(`Unrecognized relation format for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
238
238
  return undefined;
@@ -280,7 +280,7 @@ export function resolveArrayProperties<M>({
280
280
  }).filter(e => Boolean(e)) as Property[]
281
281
  : [];
282
282
  return resolvedProperties;
283
- } else if (!("Field" in property && property.Field)) {
283
+ } else if (!("Field" in (property.ui || {}) && property.ui?.Field)) {
284
284
  throw Error(`The array property (${propertyKey}) needs to declare an 'of' or a 'oneOf' property, or provide a custom \`Field\` component`);
285
285
  } else {
286
286
  return [];
@@ -350,8 +350,8 @@ export function getSubcollections<M extends Record<string, unknown> = Record<str
350
350
  return (collection as CollectionWithSubcollections).subcollections!() ?? [];
351
351
  }
352
352
 
353
- if (getDataSourceCapabilities(collection.driver).supportsRelations && (collection as CollectionWithRelations).relations) {
354
- const manyRelations = (collection as CollectionWithRelations).relations!.filter((r: Relation) => r.cardinality === "many");
353
+ if (getDataSourceCapabilities(collection.driver).supportsRelations && ((collection as any).relations)) {
354
+ const manyRelations = ((collection as any).relations)!.filter((r: Relation) => r.cardinality === "many");
355
355
  return manyRelations.map((r: Relation) => {
356
356
  const target = r.target();
357
357
  if (!target) return undefined;
@@ -376,7 +376,7 @@ export function getSubcollections<M extends Record<string, unknown> = Record<str
376
376
 
377
377
  const targetWithOverrides = { ...target, ...baseOverrides };
378
378
  return (r.overrides ? mergeDeep(targetWithOverrides, r.overrides) : targetWithOverrides) as EntityCollection<Record<string, unknown>>;
379
- }).filter((c): c is EntityCollection<Record<string, unknown>> => Boolean(c));
379
+ }).filter((c: any): c is EntityCollection<Record<string, unknown>> => Boolean(c));
380
380
  }
381
381
 
382
382
  return [];