@rebasepro/common 0.0.1-canary.2 → 0.0.1-canary.4d4fb3e

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 (63) hide show
  1. package/README.md +1 -1
  2. package/dist/collections/CollectionRegistry.d.ts +2 -2
  3. package/dist/data/buildRebaseData.d.ts +14 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.es.js +398 -815
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +418 -835
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/util/builders.d.ts +6 -13
  10. package/dist/util/collections.d.ts +2 -2
  11. package/dist/util/entities.d.ts +16 -8
  12. package/dist/util/index.d.ts +1 -11
  13. package/dist/util/navigation_from_path.d.ts +10 -5
  14. package/dist/util/navigation_utils.d.ts +1 -12
  15. package/dist/util/permissions.d.ts +4 -4
  16. package/dist/util/references.d.ts +1 -1
  17. package/dist/util/relations.d.ts +4 -4
  18. package/dist/util/resolutions.d.ts +10 -12
  19. package/dist/util/storage.d.ts +4 -4
  20. package/package.json +11 -16
  21. package/src/collections/CollectionRegistry.ts +96 -33
  22. package/src/data/buildRebaseData.ts +221 -0
  23. package/src/index.ts +1 -0
  24. package/src/types/json-logic-js.d.ts +8 -0
  25. package/src/util/builders.ts +8 -18
  26. package/src/util/callbacks.ts +3 -4
  27. package/src/util/collections.ts +4 -4
  28. package/src/util/conditions.ts +4 -4
  29. package/src/util/entities.ts +37 -12
  30. package/src/util/index.ts +1 -11
  31. package/src/util/navigation_from_path.ts +8 -7
  32. package/src/util/navigation_utils.ts +4 -56
  33. package/src/util/parent_references_from_path.ts +1 -1
  34. package/src/util/permissions.test.ts +24 -28
  35. package/src/util/permissions.ts +14 -14
  36. package/src/util/references.ts +16 -2
  37. package/src/util/relations.ts +23 -19
  38. package/src/util/resolutions.ts +31 -62
  39. package/src/util/storage.ts +5 -5
  40. package/dist/util/arrays.d.ts +0 -1
  41. package/dist/util/dates.d.ts +0 -1
  42. package/dist/util/entity_actions.d.ts +0 -2
  43. package/dist/util/fields.d.ts +0 -2
  44. package/dist/util/flatten_object.d.ts +0 -5
  45. package/dist/util/hash.d.ts +0 -1
  46. package/dist/util/names.d.ts +0 -22
  47. package/dist/util/objects.d.ts +0 -26
  48. package/dist/util/os.d.ts +0 -2
  49. package/dist/util/plurals.d.ts +0 -16
  50. package/dist/util/regexp.d.ts +0 -7
  51. package/dist/util/strings.d.ts +0 -7
  52. package/src/util/arrays.ts +0 -3
  53. package/src/util/dates.ts +0 -1
  54. package/src/util/entity_actions.ts +0 -28
  55. package/src/util/fields.ts +0 -28
  56. package/src/util/flatten_object.ts +0 -45
  57. package/src/util/hash.ts +0 -11
  58. package/src/util/names.ts +0 -30
  59. package/src/util/objects.ts +0 -376
  60. package/src/util/os.ts +0 -13
  61. package/src/util/plurals.ts +0 -188
  62. package/src/util/regexp.ts +0 -32
  63. package/src/util/strings.ts +0 -84
@@ -0,0 +1,221 @@
1
+ import {
2
+ DataDriver,
3
+ RebaseData,
4
+ CollectionAccessor,
5
+ FindParams,
6
+ FindResponse,
7
+ Entity,
8
+ EntityValues,
9
+ FilterValues,
10
+ WhereFilterOp
11
+ } from "@rebasepro/types";
12
+
13
+ /**
14
+ * Convert PostgREST-style filter object to the internal DataDriver FilterValues format.
15
+ *
16
+ * PostgREST: { status: "eq.published", age: "gte.18" }
17
+ * Internal: { status: ["==", "published"], age: [">=", 18] }
18
+ */
19
+ function convertWhereToFilter(where?: Record<string, string>): FilterValues<string> | undefined {
20
+ if (!where) return undefined;
21
+
22
+ const operatorMap: Record<string, WhereFilterOp> = {
23
+ "eq": "==",
24
+ "neq": "!=",
25
+ "gt": ">",
26
+ "gte": ">=",
27
+ "lt": "<",
28
+ "lte": "<=",
29
+ "in": "in",
30
+ "nin": "not-in",
31
+ "cs": "array-contains",
32
+ "csa": "array-contains-any",
33
+ };
34
+
35
+ const filter: FilterValues<string> = {};
36
+
37
+ for (const [field, rawValue] of Object.entries(where)) {
38
+ const dotIndex = rawValue.indexOf(".");
39
+ if (dotIndex === -1) continue;
40
+
41
+ const op = rawValue.substring(0, dotIndex);
42
+ let value: unknown = rawValue.substring(dotIndex + 1);
43
+
44
+ // Parse list values like "(admin,editor)"
45
+ if (typeof value === "string" && value.startsWith("(") && value.endsWith(")")) {
46
+ value = value.slice(1, -1).split(",").map((v: string) => v.trim());
47
+ }
48
+
49
+ // Try to parse numbers
50
+ if (typeof value === "string" && !isNaN(Number(value)) && value.trim() !== "") {
51
+ value = Number(value);
52
+ }
53
+
54
+ const mappedOp = operatorMap[op];
55
+ if (mappedOp) {
56
+ filter[field] = [mappedOp, value];
57
+ }
58
+ }
59
+
60
+ return Object.keys(filter).length > 0 ? filter : undefined;
61
+ }
62
+
63
+ /**
64
+ * Parse an orderBy string like "created_at:desc" into [field, direction].
65
+ */
66
+ function parseOrderBy(orderBy?: string): [string, "asc" | "desc"] | undefined {
67
+ if (!orderBy) return undefined;
68
+ const parts = orderBy.split(":");
69
+ const field = parts[0];
70
+ const direction = (parts[1] as "asc" | "desc") || "asc";
71
+ return [field, direction];
72
+ }
73
+
74
+ /**
75
+ * Create a CollectionAccessor that delegates to a DataDriver for a given collection slug.
76
+ */
77
+ function createDriverAccessor<M extends Record<string, unknown> = Record<string, unknown>>(
78
+ driver: DataDriver,
79
+ slug: string
80
+ ): CollectionAccessor<M> {
81
+ return {
82
+ async find(params?: FindParams): Promise<FindResponse<M>> {
83
+ const orderParsed = parseOrderBy(params?.orderBy);
84
+ const entities = await driver.fetchCollection<M>({
85
+ path: slug,
86
+ limit: params?.limit,
87
+ startAfter: params?.offset,
88
+ filter: convertWhereToFilter(params?.where),
89
+ orderBy: orderParsed?.[0],
90
+ order: orderParsed?.[1],
91
+ searchString: params?.searchString,
92
+ });
93
+ const limit = params?.limit ?? 20;
94
+ const offset = params?.offset ?? 0;
95
+ return {
96
+ data: entities,
97
+ meta: {
98
+ total: entities.length,
99
+ limit,
100
+ offset,
101
+ hasMore: entities.length >= limit
102
+ }
103
+ };
104
+ },
105
+
106
+ async findById(id: string | number): Promise<Entity<M> | undefined> {
107
+ return driver.fetchEntity<M>({ path: slug, entityId: id });
108
+ },
109
+
110
+ async create(data: Partial<EntityValues<M>>, id?: string | number): Promise<Entity<M>> {
111
+ return driver.saveEntity<M>({
112
+ path: slug,
113
+ values: data,
114
+ entityId: id,
115
+ status: "new"
116
+ });
117
+ },
118
+
119
+ async update(id: string | number, data: Partial<EntityValues<M>>): Promise<Entity<M>> {
120
+ return driver.saveEntity<M>({
121
+ path: slug,
122
+ values: data,
123
+ entityId: id,
124
+ status: "existing"
125
+ });
126
+ },
127
+
128
+ async delete(id: string | number): Promise<void> {
129
+ return driver.deleteEntity({
130
+ entity: { id, path: slug, values: {} as Record<string, unknown> }
131
+ });
132
+ },
133
+
134
+ count: driver.countEntities
135
+ ? async (params?: FindParams): Promise<number> => {
136
+ return driver.countEntities!({
137
+ path: slug,
138
+ filter: convertWhereToFilter(params?.where),
139
+ });
140
+ }
141
+ : undefined,
142
+
143
+ listen: driver.listenCollection
144
+ ? (params: FindParams | undefined, onUpdate: (response: FindResponse<M>) => void, onError?: (error: Error) => void) => {
145
+ const orderParsed = parseOrderBy(params?.orderBy);
146
+ const limit = params?.limit ?? 20;
147
+ const offset = params?.offset ?? 0;
148
+ return driver.listenCollection!<M>({
149
+ path: slug,
150
+ limit: params?.limit,
151
+ startAfter: params?.offset,
152
+ filter: convertWhereToFilter(params?.where),
153
+ orderBy: orderParsed?.[0],
154
+ order: orderParsed?.[1],
155
+ searchString: params?.searchString,
156
+ onUpdate: (entities) => {
157
+ onUpdate({
158
+ data: entities,
159
+ meta: {
160
+ total: entities.length,
161
+ limit,
162
+ offset,
163
+ hasMore: entities.length >= limit
164
+ }
165
+ });
166
+ },
167
+ onError
168
+ });
169
+ } : undefined,
170
+
171
+ listenById: driver.listenEntity
172
+ ? (id: string | number, onUpdate: (entity: Entity<M> | undefined) => void, onError?: (error: Error) => void) => {
173
+ return driver.listenEntity!<M>({
174
+ path: slug,
175
+ entityId: id,
176
+ onUpdate: (entity) => onUpdate(entity ?? undefined),
177
+ onError
178
+ });
179
+ } : undefined
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Build a `RebaseData` object from a `DataDriver` using JavaScript Proxy.
185
+ *
186
+ * This is the key bridge: any property access like `data.products` returns
187
+ * a `CollectionAccessor` backed by the underlying DataDriver, without
188
+ * needing per-collection code generation.
189
+ *
190
+ * @example
191
+ * const data = buildRebaseData(driver);
192
+ * await data.products.create({ name: "Camera", price: 299 });
193
+ * const { data: items } = await data.products.find({ where: { status: "eq.published" } });
194
+ */
195
+ export function buildRebaseData(driver: DataDriver): RebaseData {
196
+ const cache = new Map<string, CollectionAccessor>();
197
+
198
+ function getAccessor(slug: string): CollectionAccessor {
199
+ let accessor = cache.get(slug);
200
+ if (!accessor) {
201
+ accessor = createDriverAccessor(driver, slug);
202
+ cache.set(slug, accessor);
203
+ }
204
+ return accessor;
205
+ }
206
+
207
+ const target = {
208
+ collection: getAccessor
209
+ } as RebaseData;
210
+
211
+ return new Proxy(target, {
212
+ get(_target, prop: string | symbol) {
213
+ if (prop === "collection") return getAccessor;
214
+ // Ignore Symbol properties (e.g. Symbol.toPrimitive, Symbol.iterator)
215
+ if (typeof prop === "symbol") return undefined;
216
+ // Ignore internal JS properties
217
+ if (prop === "then" || prop === "toJSON" || prop === "$$typeof") return undefined;
218
+ return getAccessor(prop);
219
+ }
220
+ });
221
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./util";
2
2
  export * from "./collections";
3
+ export * from "./data/buildRebaseData";
@@ -0,0 +1,8 @@
1
+ declare module "json-logic-js" {
2
+ interface JsonLogic {
3
+ apply(logic: unknown, data?: unknown): unknown;
4
+ add_operation<T extends any[]>(name: string, fn: (...args: T) => unknown): void;
5
+ }
6
+ const jsonLogic: JsonLogic;
7
+ export default jsonLogic;
8
+ }
@@ -11,12 +11,12 @@ import {
11
11
  MapProperty,
12
12
  NumberProperty, Properties,
13
13
  Property,
14
- PropertyConfig,
15
14
  ReferenceProperty,
16
15
  StringProperty,
17
16
  User
18
17
  } from "@rebasepro/types";
19
18
 
19
+
20
20
  /**
21
21
  * Identity function we use to defeat the type system of Typescript and build
22
22
  * collection views with all its properties
@@ -24,7 +24,7 @@ import {
24
24
  * @group Builder
25
25
  */
26
26
  export function buildCollection<
27
- M extends Record<string, any> = any,
27
+ M extends Record<string, unknown> = Record<string, unknown>,
28
28
  USER extends User = User>
29
29
  (
30
30
  collection: EntityCollection<M, USER>
@@ -50,7 +50,7 @@ export function buildProperty<T, P extends Property = Property>(
50
50
  P extends ArrayProperty ? ArrayProperty :
51
51
  P extends MapProperty ? MapProperty : never {
52
52
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
- return property as any;
53
+ return property as unknown as ReturnType<typeof buildProperty<T, P>>;
54
54
  }
55
55
 
56
56
  /**
@@ -59,7 +59,7 @@ export function buildProperty<T, P extends Property = Property>(
59
59
  * @param properties
60
60
  * @group Builder
61
61
  */
62
- export function buildProperties<M extends Record<string, any>>(
62
+ export function buildProperties<M extends Record<string, unknown>>(
63
63
  properties: Properties
64
64
  ): Properties {
65
65
  return properties;
@@ -71,7 +71,7 @@ export function buildProperties<M extends Record<string, any>>(
71
71
  * @param propertiesOrBuilder
72
72
  * @group Builder
73
73
  */
74
- export function buildPropertiesOrBuilder<M extends Record<string, any>>(
74
+ export function buildPropertiesOrBuilder<M extends Record<string, unknown>>(
75
75
  propertiesOrBuilder: Properties
76
76
  ): Properties {
77
77
  return propertiesOrBuilder;
@@ -107,7 +107,7 @@ export function buildEnumValueConfig(
107
107
  * @param callbacks
108
108
  * @group Builder
109
109
  */
110
- export function buildEntityCallbacks<M extends Record<string, any> = any>(
110
+ export function buildEntityCallbacks<M extends Record<string, unknown> = Record<string, unknown>>(
111
111
  callbacks: EntityCallbacks<M>
112
112
  ): EntityCallbacks<M> {
113
113
  return callbacks;
@@ -119,20 +119,10 @@ export function buildEntityCallbacks<M extends Record<string, any> = any>(
119
119
  * @param additionalFieldDelegate
120
120
  * @group Builder
121
121
  */
122
- export function buildAdditionalFieldDelegate<M extends Record<string, any>, USER extends User = User>(
122
+ export function buildAdditionalFieldDelegate<M extends Record<string, unknown>, USER extends User = User>(
123
123
  additionalFieldDelegate: AdditionalFieldDelegate<M, USER>
124
124
  ): AdditionalFieldDelegate<M, USER> {
125
125
  return additionalFieldDelegate;
126
126
  }
127
127
 
128
- /**
129
- * Identity function we use to defeat the type system of Typescript and build
130
- * additional field delegates views with all its properties
131
- * @param propertyConfig
132
- * @group Builder
133
- */
134
- export function buildFieldConfig(
135
- propertyConfig: PropertyConfig
136
- ): PropertyConfig {
137
- return propertyConfig;
138
- }
128
+
@@ -1,5 +1,4 @@
1
1
  import { EntityCallbacks, Properties } from "@rebasepro/types";
2
- import { mergeDeep } from "./objects";
3
2
 
4
3
  /**
5
4
  * Helper function to recursively check if there are any callbacks in the properties.
@@ -33,13 +32,13 @@ async function processProperties(
33
32
  ): Promise<Record<string, unknown>> {
34
33
  if (!values || typeof values !== "object") return values;
35
34
 
36
- let result = { ...values };
35
+ const result = { ...values };
37
36
 
38
37
  for (const [key, property] of Object.entries(properties)) {
39
38
  if (result[key] === undefined) continue;
40
39
 
41
40
  let currentValue = result[key];
42
- let previousValue = previousValues?.[key];
41
+ const previousValue = previousValues?.[key];
43
42
 
44
43
  // 1. Array Property
45
44
  if (property.type === "array" && Array.isArray(currentValue)) {
@@ -66,7 +65,7 @@ async function processProperties(
66
65
  ...(propsContext as Record<string, unknown>),
67
66
  value: currentValue,
68
67
  previousValue
69
- } as any));
68
+ } as never));
70
69
  if (cbRes !== undefined) {
71
70
  currentValue = cbRes;
72
71
  }
@@ -7,7 +7,7 @@ import {
7
7
  } from "@rebasepro/types";
8
8
  import { isPropertyBuilder } from "./entities";
9
9
 
10
- export function sortProperties<M extends Record<string, any>>(properties: Properties, propertiesOrder?: string[]): Properties {
10
+ export function sortProperties<M extends Record<string, unknown>>(properties: Properties, propertiesOrder?: string[]): Properties {
11
11
  try {
12
12
  const propertiesKeys = Object.keys(properties);
13
13
  // If no propertiesOrder, just use the original keys order
@@ -54,7 +54,7 @@ export function sortProperties<M extends Record<string, any>>(properties: Proper
54
54
  return ({ [key]: property });
55
55
  }
56
56
  })
57
- .reduce((a: any, b: any) => ({ ...a, ...b }), {}) as Properties;
57
+ .reduce((a: Properties, b: Properties) => ({ ...a, ...b }), {}) as Properties;
58
58
 
59
59
  // Append any properties that were NOT in propertiesOrder (so they don't disappear!)
60
60
  const missingProperties = propertiesKeys
@@ -72,7 +72,7 @@ export function sortProperties<M extends Record<string, any>>(properties: Proper
72
72
  return ({ [key]: property });
73
73
  }
74
74
  })
75
- .reduce((a: any, b: any) => ({ ...a, ...b }), {}) as Properties;
75
+ .reduce((a: Properties, b: Properties) => ({ ...a, ...b }), {}) as Properties;
76
76
 
77
77
  return { ...orderedResult, ...missingProperties };
78
78
  } catch (e) {
@@ -110,7 +110,7 @@ export function getLocalChangesBackup(collection: EntityCollection) {
110
110
  * Fallbacks to `["id"]` if no properties are marked as `isId: true`.
111
111
  * @param collection
112
112
  */
113
- export function getPrimaryKeys<M extends Record<string, any>>(collection: EntityCollection<M>): Extract<keyof M, string>[] {
113
+ export function getPrimaryKeys<M extends Record<string, unknown>>(collection: EntityCollection<M>): Extract<keyof M, string>[] {
114
114
  const properties = collection.properties;
115
115
  if (!properties) {
116
116
  return ["id"] as Extract<keyof M, string>[];
@@ -152,7 +152,7 @@ export function buildConditionContext(params: {
152
152
  email: user?.email ?? null,
153
153
  displayName: user?.displayName ?? null,
154
154
  photoURL: user?.photoURL ?? null,
155
- roles: user?.roles ?? []
155
+ roles: (user?.roles ?? []).map((r: unknown) => typeof r === "string" ? r : (r as { id: string }).id)
156
156
  },
157
157
  now: Date.now()
158
158
  };
@@ -233,9 +233,9 @@ export function applyPropertyConditions(
233
233
  // ENUM CONDITIONS
234
234
  // ═══════════════════════════════════════════════════════════════════════
235
235
 
236
- if ("enumValues" in result && result.enumValues && (conditions.enumConditions || conditions.allowedEnumValues || conditions.excludedEnumValues)) {
237
- (result as Record<string, unknown>).enumValues = applyEnumConditions(
238
- result.enumValues as EnumValueConfig[],
236
+ if ("enum" in result && result.enum && (conditions.enumConditions || conditions.allowedEnumValues || conditions.excludedEnumValues)) {
237
+ (result as Record<string, unknown>).enum = applyEnumConditions(
238
+ result.enum as EnumValueConfig[],
239
239
  conditions,
240
240
  context
241
241
  );
@@ -9,7 +9,7 @@ import {
9
9
  Property,
10
10
  } from "@rebasepro/types";
11
11
  import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "./common";
12
- import { mergeDeep } from "./objects";
12
+ import { mergeDeep } from "@rebasepro/utils";
13
13
 
14
14
  export function isReadOnly(property: Property): boolean {
15
15
  if (property.readOnly)
@@ -19,7 +19,7 @@ export function isReadOnly(property: Property): boolean {
19
19
  return true;
20
20
  }
21
21
  if (property.type === "reference") {
22
- return !property.path && !property.Field;
22
+ return !property.path && !("Field" in property && property.Field);
23
23
  }
24
24
  return false;
25
25
  }
@@ -32,7 +32,7 @@ export function isPropertyBuilder(property?: Property) {
32
32
  return typeof property?.dynamicProps === "function";
33
33
  }
34
34
 
35
- export function getDefaultValuesFor<M extends Record<string, any>>(properties: Properties): Partial<EntityValues<M>> {
35
+ export function getDefaultValuesFor<M extends Record<string, unknown>>(properties: Properties): Partial<EntityValues<M>> {
36
36
  if (!properties) return {};
37
37
  return Object.entries(properties)
38
38
  .map(([key, property]) => {
@@ -77,9 +77,9 @@ export function getDefaultValueFortype(type: DataType) {
77
77
 
78
78
  /**
79
79
  * Update the automatic values in an entity before save
80
- * @group Datasource
80
+ * @group Driver
81
81
  */
82
- export function updateDateAutoValues<M extends Record<string, any>>({
82
+ export function updateDateAutoValues<M extends Record<string, unknown>>({
83
83
  inputValues,
84
84
  properties,
85
85
  status,
@@ -115,9 +115,9 @@ export function updateDateAutoValues<M extends Record<string, any>>({
115
115
  * Add missing required fields, expected in the collection, to the values of an entity
116
116
  * @param values
117
117
  * @param properties
118
- * @group Datasource
118
+ * @group Driver
119
119
  */
120
- export function sanitizeData<M extends Record<string, any>>
120
+ export function sanitizeData<M extends Record<string, unknown>>
121
121
  (
122
122
  values: EntityValues<M>,
123
123
  properties: Properties
@@ -131,22 +131,47 @@ export function sanitizeData<M extends Record<string, any>>
131
131
  return result;
132
132
  }
133
133
 
134
- export function getReferenceFrom<M extends Record<string, any>>(entity: Entity<M>): EntityReference {
134
+ export function getReferenceFrom<M extends Record<string, unknown>>(entity: Entity<M>): EntityReference {
135
135
  if (typeof entity.id !== "string")
136
136
  throw new Error("Only string IDs are supported in references");
137
137
  return new EntityReference({
138
138
  id: entity.id,
139
139
  path: entity.path,
140
- datasource: entity.datasource,
140
+ driver: entity.driver,
141
141
  databaseId: entity.databaseId
142
142
  });
143
143
  }
144
144
 
145
- export function getRelationFrom<M extends Record<string, any>>(entity: Entity<M>): EntityRelation {
146
- return new EntityRelation(entity.id, entity.path);
145
+ export function getRelationFrom<M extends Record<string, unknown>>(entity: Entity<M>): EntityRelation {
146
+ return new EntityRelation(entity.id, entity.path, entity);
147
147
  }
148
148
 
149
- export function traverseValuesProperties<M extends Record<string, any>>(
149
+ /**
150
+ * Normalize a value into a proper EntityRelation instance.
151
+ * Handles EntityRelation class instances, and plain objects
152
+ * with `__type === "relation"` or an `isEntityRelation()` method.
153
+ *
154
+ * Returns null if the value cannot be coerced.
155
+ */
156
+ export function normalizeToEntityRelation(value: unknown): EntityRelation | null {
157
+ if (value instanceof EntityRelation) return value;
158
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
159
+
160
+ const obj = value as Record<string, unknown>;
161
+ const isRelationLike =
162
+ obj.__type === "relation" ||
163
+ (typeof obj.isEntityRelation === "function" && (obj.isEntityRelation as () => boolean)());
164
+
165
+ if (!isRelationLike) return null;
166
+
167
+ return new EntityRelation(
168
+ obj.id as string | number,
169
+ obj.path as string,
170
+ obj.data as Entity | undefined
171
+ );
172
+ }
173
+
174
+ export function traverseValuesProperties<M extends Record<string, unknown>>(
150
175
  inputValues: Partial<EntityValues<M>>,
151
176
  properties: Properties,
152
177
  operation: (value: unknown, property: Property) => unknown
package/src/util/index.ts CHANGED
@@ -1,26 +1,16 @@
1
1
  export * from "./collections";
2
2
  export * from "./common";
3
3
  export * from "./entities";
4
- export * from "./strings";
5
- export * from "./dates";
6
4
  export * from "./enums";
7
- export * from "./objects";
8
5
  export * from "./paths";
9
- export * from "./regexp";
10
- export * from "./navigation_utils";
11
- export * from "./entity_actions";
12
- export * from "./fields";
13
6
  export * from "./resolutions";
14
7
  export * from "./permissions";
15
- export * from "./plurals";
16
8
  export * from "./references";
17
- export * from "./flatten_object";
18
9
  export * from "./navigation_from_path";
19
10
  export * from "./parent_references_from_path";
20
11
  export * from "./builders";
21
12
  export * from "./storage";
22
- export * from "./arrays";
23
13
  export * from "./callbacks";
24
- export * from "./hash";
25
14
  export * from "./relations";
26
15
  export * from "./conditions";
16
+ export * from "./navigation_utils";
@@ -1,13 +1,14 @@
1
- import { EntityCollection, EntityCustomView } from "@rebasepro/types";
1
+ import { EntityCollection } from "@rebasepro/types";
2
+ type EntityCustomView<M extends Record<string, unknown> = Record<string, unknown>> = { key: string; [key: string]: unknown };
2
3
  import { getCollectionPathsCombinations, removeInitialAndTrailingSlashes } from "./navigation_utils";
3
4
  import { getSubcollections } from "./resolutions";
4
5
 
5
- export type NavigationViewInternal<M extends Record<string, any> = any> =
6
+ export type NavigationViewInternal<M extends Record<string, unknown> = Record<string, unknown>> =
6
7
  | NavigationViewEntityInternal<M>
7
8
  | NavigationViewCollectionInternal<M>
8
9
  | NavigationViewEntityCustomInternal<M>;
9
10
 
10
- export interface NavigationViewEntityInternal<M extends Record<string, any>> {
11
+ export interface NavigationViewEntityInternal<M extends Record<string, unknown>> {
11
12
  type: "entity";
12
13
  entityId: string | number;
13
14
  slug: string;
@@ -15,7 +16,7 @@ export interface NavigationViewEntityInternal<M extends Record<string, any>> {
15
16
  parentCollection: EntityCollection<M>;
16
17
  }
17
18
 
18
- export interface NavigationViewCollectionInternal<M extends Record<string, any>> {
19
+ export interface NavigationViewCollectionInternal<M extends Record<string, unknown>> {
19
20
  type: "collection";
20
21
  id: string;
21
22
  slug: string;
@@ -23,7 +24,7 @@ export interface NavigationViewCollectionInternal<M extends Record<string, any>>
23
24
  collection: EntityCollection<M>;
24
25
  }
25
26
 
26
- export interface NavigationViewEntityCustomInternal<M extends Record<string, any>> {
27
+ export interface NavigationViewEntityCustomInternal<M extends Record<string, unknown>> {
27
28
  type: "custom_view";
28
29
  slug: string;
29
30
  path: string;
@@ -84,8 +85,8 @@ export function getNavigationEntriesFromPath(props: {
84
85
  const entityViews = collection.entityViews;
85
86
  const customView = entityViews && entityViews
86
87
  .map((entry) => resolveEntityView(entry, props.contextEntityViews))
87
- .filter(Boolean)
88
- .find((entry) => entry!.key === newPath);
88
+ .filter((v): v is EntityCustomView => v != null)
89
+ .find((entry) => entry.key === newPath);
89
90
  const subcollections = getSubcollections(collection);
90
91
  if (customView) {
91
92
  result.push({
@@ -1,4 +1,5 @@
1
- import { EntityCollection, CMSUrlController, SideEntityController } from "@rebasepro/types";
1
+ import { EntityCollection } from "@rebasepro/types";
2
+
2
3
  import { getSubcollections } from "./resolutions";
3
4
 
4
5
  export function removeInitialAndTrailingSlashes(s: string): string {
@@ -66,7 +67,7 @@ export function resolveCollectionPathIds(path: string, allCollections: EntityCol
66
67
  match: matchString
67
68
  } = potentialMatches[0];
68
69
 
69
- resolvedPathParts.push(foundCollection.dbPath); // Use the defined path
70
+ resolvedPathParts.push(foundCollection.slug); // Use the defined path
70
71
  remainingPath = removeInitialSlash(remainingPath.substring(matchString.length));
71
72
 
72
73
  // Check if we are at the end of the path
@@ -141,7 +142,7 @@ export function getCollectionBySlugWithin(slugOrPath: string, collections: Entit
141
142
 
142
143
  if (subpathCombination === slugOrPath) {
143
144
  result = navigationEntry;
144
- } else if (navigationEntry.subcollections) {
145
+ } else if (getSubcollections(navigationEntry).length > 0) {
145
146
  const newPath = slugOrPath.replace(subpathCombination, "").split("/").slice(2).join("/");
146
147
  if (newPath.length > 0)
147
148
  result = getCollectionBySlugWithin(newPath, getSubcollections(navigationEntry));
@@ -166,57 +167,4 @@ export function getCollectionPathsCombinations(subpaths: string[]): string[] {
166
167
  result.push(entries.slice(0, i).join("/"));
167
168
  }
168
169
  return result;
169
-
170
- }
171
-
172
- export function navigateToEntity({
173
- openEntityMode,
174
- collection,
175
- entityId,
176
- copy,
177
- path,
178
- selectedTab,
179
- sideEntityController,
180
- onClose,
181
- navigation
182
- }:
183
-
184
- {
185
- openEntityMode: "side_panel" | "full_screen";
186
- collection?: EntityCollection;
187
- entityId?: string | number;
188
- selectedTab?: string;
189
- copy?: boolean;
190
- path: string;
191
- sideEntityController: SideEntityController;
192
- onClose?: () => void;
193
- navigation: CMSUrlController
194
- }) {
195
-
196
- if (openEntityMode === "side_panel") {
197
-
198
- sideEntityController.open({
199
- entityId,
200
- path: path,
201
- copy,
202
- selectedTab,
203
- collection,
204
- updateUrl: true,
205
- onClose
206
- });
207
-
208
- } else {
209
- let to = navigation.buildUrlCollectionPath(entityId ? `${path ?? path}/${entityId}` : path ?? path);
210
- if (entityId && selectedTab) {
211
- to += `/${selectedTab}`;
212
- }
213
- if (!entityId) {
214
- to += "#new";
215
- }
216
- if (copy) {
217
- to += "#copy";
218
- }
219
- navigation.navigate(to);
220
- }
221
-
222
170
  }
@@ -40,7 +40,7 @@ export function getParentReferencesFromPath(props: {
40
40
  if (!collection) {
41
41
  throw Error("collection not found resolving path: " + collection);
42
42
  }
43
- if (collection.subcollections) {
43
+ if (getSubcollections(collection).length > 0) {
44
44
  result.push(...getParentReferencesFromPath({
45
45
  path: newPath,
46
46
  collections: getSubcollections(collection),