@firecms/core 3.4.0-canary.63041d0 → 3.4.0-canary.d20cc85

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 (32) hide show
  1. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +3 -1
  2. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +3 -1
  3. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +3 -1
  4. package/dist/components/ReferenceTable/ReferenceSelectionTable.d.ts +10 -1
  5. package/dist/form/EntityForm.d.ts +6 -1
  6. package/dist/hooks/data/useCollectionFetch.d.ts +7 -1
  7. package/dist/index.es.js +177 -112
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/index.umd.js +177 -112
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/types/datasource.d.ts +17 -4
  12. package/dist/types/entities.d.ts +21 -1
  13. package/dist/util/parent_references_from_path.d.ts +1 -0
  14. package/package.json +4 -4
  15. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +5 -1
  16. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +4 -0
  17. package/src/components/EntityCollectionView/EntityCollectionView.tsx +10 -2
  18. package/src/components/EntityCollectionView/useBoardDataController.tsx +11 -0
  19. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +11 -0
  20. package/src/components/common/useDataSourceTableController.tsx +8 -2
  21. package/src/core/EntityEditView.tsx +5 -2
  22. package/src/form/EntityForm.tsx +8 -2
  23. package/src/hooks/data/delete.ts +2 -0
  24. package/src/hooks/data/save.ts +1 -1
  25. package/src/hooks/data/useCollectionFetch.tsx +13 -0
  26. package/src/hooks/data/useEntityFetch.tsx +10 -1
  27. package/src/hooks/useResolvedNavigationFrom.tsx +2 -0
  28. package/src/internal/useBuildDataSource.ts +14 -4
  29. package/src/types/datasource.ts +17 -4
  30. package/src/types/entities.ts +24 -1
  31. package/src/util/entities.ts +3 -1
  32. package/src/util/parent_references_from_path.ts +10 -2
@@ -106,6 +106,11 @@ export interface SaveEntityProps<M extends Record<string, any> = any> {
106
106
  */
107
107
  export interface DeleteEntityProps<M extends Record<string, any> = any> {
108
108
  entity: Entity<M>;
109
+ /**
110
+ * `entity.path` split at its real segment boundaries, when the caller knows them.
111
+ * Never derived from `entity.path` — see `pathSegments` on FetchCollectionProps.
112
+ */
113
+ pathSegments?: string[];
109
114
  collection?: EntityCollection<M> | ResolvedEntityCollection<M>;
110
115
  }
111
116
 
@@ -245,13 +250,19 @@ export interface DataSource {
245
250
  name: string,
246
251
  value: any,
247
252
  entityId?: string,
248
- collection?: EntityCollection
253
+ collection?: EntityCollection,
254
+ /**
255
+ * Appended last, and optional, so existing implementations and callers keep
256
+ * working unchanged — a function declaring fewer parameters stays assignable.
257
+ * See `pathSegments` on FetchCollectionProps.
258
+ */
259
+ pathSegments?: string[]
249
260
  ): Promise<boolean>;
250
261
 
251
262
  /**
252
263
  * Generate an id for a new entity
253
264
  */
254
- generateEntityId(path: string, collection: EntityCollection): string;
265
+ generateEntityId(path: string, collection: EntityCollection, pathSegments?: string[]): string;
255
266
 
256
267
  /**
257
268
  * Count the number of entities in a collection
@@ -279,6 +290,8 @@ export interface DataSource {
279
290
  }
280
291
 
281
292
  export type FilterCombinationValidProps = {
293
+ /** `path` split at its real segment boundaries — see `pathSegments` on FetchCollectionProps. */
294
+ pathSegments?: string[];
282
295
  path: string;
283
296
  collection: EntityCollection<any>;
284
297
  filterValues: FilterValues<any>;
@@ -408,12 +421,12 @@ export interface DataSourceDelegate {
408
421
  * @param collection
409
422
  * @return `true` if there are no other fields besides the given entity
410
423
  */
411
- checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean>;
424
+ checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection, pathSegments?: string[]): Promise<boolean>;
412
425
 
413
426
  /**
414
427
  * Generate an id for a new entity
415
428
  */
416
- generateEntityId(path: string, collection?: EntityCollection): string;
429
+ generateEntityId(path: string, collection?: EntityCollection, pathSegments?: string[]): string;
417
430
 
418
431
  /**
419
432
  * Count the number of entities in a collection
@@ -21,6 +21,17 @@ export interface Entity<M extends object = any> {
21
21
  */
22
22
  path: string;
23
23
 
24
+ /**
25
+ * `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
26
+ *
27
+ * `path` is a single flattened string, so a parent entity id containing "/" cannot be
28
+ * recovered from it. This keeps each segment whole.
29
+ *
30
+ * Optional, and never derived by splitting `path` — a guess would be wrong in exactly
31
+ * the case the field exists for. Absent means "not known here", not "no slashes".
32
+ */
33
+ pathSegments?: string[];
34
+
24
35
  /**
25
36
  * Current values
26
37
  */
@@ -55,10 +66,22 @@ export class EntityReference {
55
66
  */
56
67
  readonly databaseId?: string;
57
68
 
58
- constructor(id: string, path: string, databaseId?: string) {
69
+ /**
70
+ * `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
71
+ *
72
+ * `path` is a single flattened string, so a parent entity id containing "/" cannot be
73
+ * recovered from it. This keeps each segment whole.
74
+ *
75
+ * Optional, and never derived by splitting `path` — a guess would be wrong in exactly
76
+ * the case the field exists for. Absent means "not known here", not "no slashes".
77
+ */
78
+ readonly pathSegments?: string[];
79
+
80
+ constructor(id: string, path: string, databaseId?: string, pathSegments?: string[]) {
59
81
  this.id = id;
60
82
  this.path = path;
61
83
  this.databaseId = databaseId;
84
+ this.pathSegments = pathSegments;
62
85
  }
63
86
 
64
87
  get pathWithId() {
@@ -142,7 +142,9 @@ export function getReferenceFrom<M extends Record<string, any>>(entity: Entity<M
142
142
  if (!entity) {
143
143
  throw new Error("getReferenceFrom: entity is null or undefined");
144
144
  }
145
- return new EntityReference(entity.id, entity.path, entity.databaseId);
145
+ // Carry the segments the entity was loaded with, so a reference to an entity under a
146
+ // slash-bearing parent stays resolvable. Undefined when the entity does not have them.
147
+ return new EntityReference(entity.id, entity.path, entity.databaseId, entity.pathSegments);
146
148
  }
147
149
 
148
150
  export function traverseValuesProperties<M extends Record<string, any>>(
@@ -5,12 +5,14 @@ export function getParentReferencesFromPath(props: {
5
5
  path: string,
6
6
  collections: EntityCollection[] | undefined,
7
7
  currentFullPath?: string,
8
+ currentPathSegments?: string[],
8
9
  }): EntityReference [] {
9
10
 
10
11
  const {
11
12
  path,
12
13
  collections = [],
13
14
  currentFullPath,
15
+ currentPathSegments = [],
14
16
  } = props;
15
17
 
16
18
  const subpaths = removeInitialAndTrailingSlashes(path).split("/");
@@ -27,6 +29,9 @@ export function getParentReferencesFromPath(props: {
27
29
  const collectionPath = currentFullPath && currentFullPath.length > 0
28
30
  ? (currentFullPath + "/" + collection.path)
29
31
  : collection.path;
32
+ // A collection's own path may span several segments, and those are
33
+ // unambiguous, so they are spread rather than kept whole.
34
+ const collectionSegments = [...currentPathSegments, ...collection.path.split("/")];
30
35
 
31
36
  const restOfThePath = removeInitialAndTrailingSlashes(removeInitialAndTrailingSlashes(path).replace(subpathCombination, ""));
32
37
  const nextSegments = restOfThePath.length > 0 ? restOfThePath.split("/") : [];
@@ -35,7 +40,9 @@ export function getParentReferencesFromPath(props: {
35
40
  // datasource-facing, so they carry the raw id.
36
41
  const entityId = decodeEntityId(nextSegments[0]);
37
42
  const fullPath = collectionPath + "/" + entityId;
38
- result.push(new EntityReference(entityId, collectionPath));
43
+ // The id is ONE segment however many slashes it contains.
44
+ const entitySegments = [...collectionSegments, entityId];
45
+ result.push(new EntityReference(entityId, collectionPath, undefined, collectionSegments));
39
46
  if (nextSegments.length > 1) {
40
47
  const newPath = nextSegments.slice(1).join("/");
41
48
  if (!collection) {
@@ -45,7 +52,8 @@ export function getParentReferencesFromPath(props: {
45
52
  result.push(...getParentReferencesFromPath({
46
53
  path: newPath,
47
54
  collections: collection.subcollections,
48
- currentFullPath: fullPath
55
+ currentFullPath: fullPath,
56
+ currentPathSegments: entitySegments
49
57
  }));
50
58
  }
51
59
  }