@rebasepro/common 0.28.1 → 0.29.0-canary.g0e3a0e7

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.
@@ -45,6 +45,18 @@ export interface EntityDataOptions {
45
45
  */
46
46
  resolveAccessor?: (property: string) => string;
47
47
  }
48
+ /**
49
+ * A row as the server sends it, in the admin's view model of its collection:
50
+ * the `values` `buildRebaseData` and `wrapAsEntityData` give an `Entity` of
51
+ * that collection — a date as a `Date`, a relation as an `EntityRelation`,
52
+ * also under its property's key where the row carries only the foreign key —
53
+ * and a `reference` property's id as an `EntityReference`. A collection the
54
+ * resolver does not know leaves the row as it is.
55
+ *
56
+ * For code that holds a flat row and hands it to what expects the admin's
57
+ * values, such as a collection's `browserCallbacks` or a preview.
58
+ */
59
+ export declare function rowToViewModel(row: Record<string, unknown>, slug: string, resolveCollection: NonNullable<EntityDataOptions["resolveCollection"]>): Record<string, unknown>;
48
60
  export declare function buildRebaseData(driver: DataDriver, options?: EntityDataOptions): RebaseData;
49
61
  /**
50
62
  * Wrap a flat {@link RebaseSdkData} into a Entity-shaped {@link RebaseData}.
@@ -1,5 +1,5 @@
1
1
  import { buildCompositeId, resolvePrimaryKeys } from "../util/identity.es.js";
2
- import { resolveCollectionRelations } from "../util/relations.es.js";
2
+ import { fieldKeyForColumn, resolveCollectionRelations } from "../util/relations.es.js";
3
3
  import { cursorToStartAfter, decodeCursor, reconcileCursorOrder } from "./cursor.es.js";
4
4
  import { normalizeOrderBy } from "./sort-dialect.es.js";
5
5
  import { mergeIncludeSpecs } from "./include-spec.es.js";
@@ -7,7 +7,7 @@ import { etagOf } from "./row-etag.es.js";
7
7
  import { QueryBuilder } from "./query_builder.es.js";
8
8
  import { collectAllPages, paginateFind, resolveFindWindow } from "./paginate.es.js";
9
9
  import { deserializeFilter } from "./filter-dialect.es.js";
10
- import { DEFAULT_VECTOR_LIST_LIMIT, EntityRelation, RebaseApiError, RebaseClientError, isUnsupported, sortKeyToString, unsupportedMethod } from "@rebasepro/types";
10
+ import { DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, RebaseApiError, RebaseClientError, isUnsupported, sortKeyToString, unsupportedMethod } from "@rebasepro/types";
11
11
  import { toSnakeCase, toWireKey } from "@rebasepro/utils";
12
12
  //#region src/data/buildRebaseData.ts
13
13
  /**
@@ -109,7 +109,7 @@ function toViewModelValues(values, properties, collection, resolveCollection) {
109
109
  if (!(key in values)) {
110
110
  const fkRelation = relations[key];
111
111
  const column = fkRelation && "localKey" in fkRelation ? fkRelation.localKey : void 0;
112
- const fk = column !== void 0 ? values[column] ?? values[toWireKey(column)] : void 0;
112
+ const fk = column !== void 0 ? values[fieldKeyForColumn(collection, column)] ?? values[column] ?? values[toWireKey(column)] : void 0;
113
113
  const fkTarget = fkRelation?.targetSlug;
114
114
  if (fkTarget && (typeof fk === "string" || typeof fk === "number")) write(key, new EntityRelation(fk, fkTarget));
115
115
  continue;
@@ -497,6 +497,69 @@ function createViewModelConverter(options) {
497
497
  };
498
498
  };
499
499
  }
500
+ /**
501
+ * A row as the server sends it, in the admin's view model of its collection:
502
+ * the `values` `buildRebaseData` and `wrapAsEntityData` give an `Entity` of
503
+ * that collection — a date as a `Date`, a relation as an `EntityRelation`,
504
+ * also under its property's key where the row carries only the foreign key —
505
+ * and a `reference` property's id as an `EntityReference`. A collection the
506
+ * resolver does not know leaves the row as it is.
507
+ *
508
+ * For code that holds a flat row and hands it to what expects the admin's
509
+ * values, such as a collection's `browserCallbacks` or a preview.
510
+ */
511
+ function rowToViewModel(row, slug, resolveCollection) {
512
+ const collection = resolveCollection(slug);
513
+ if (!collection) return row;
514
+ return withReferences(toViewModelValues(row, collection.properties, collection, resolveCollection), collection.properties);
515
+ }
516
+ /**
517
+ * Each `reference` property's value — the referenced id, or `{ id, path }` —
518
+ * as the `EntityReference` the admin's reference field and preview read; an
519
+ * array of references item by item.
520
+ */
521
+ function withReferences(values, properties) {
522
+ if (!properties) return values;
523
+ let out;
524
+ for (const [key, property] of Object.entries(properties)) {
525
+ if (!(key in values)) continue;
526
+ const value = values[key];
527
+ const path = referencePath(property);
528
+ const arrayPath = isPlainRecord(property) && property.type === "array" ? referencePath(property.of) : void 0;
529
+ if (path !== void 0) {
530
+ out = out ?? { ...values };
531
+ out[key] = toReference(value, path);
532
+ } else if (arrayPath !== void 0 && Array.isArray(value)) {
533
+ out = out ?? { ...values };
534
+ out[key] = value.map((item) => toReference(item, arrayPath));
535
+ }
536
+ }
537
+ return out ?? values;
538
+ }
539
+ /** The target path of a `reference` property; `undefined` for any other. */
540
+ function referencePath(property) {
541
+ if (!isPlainRecord(property) || property.type !== "reference") return void 0;
542
+ return typeof property.path === "string" ? property.path : "";
543
+ }
544
+ function toReference(value, path) {
545
+ if (value === null || value === void 0 || value === "") return null;
546
+ if (value instanceof EntityReference) return value;
547
+ if ((typeof value === "string" || typeof value === "number") && path) return new EntityReference({
548
+ id: String(value),
549
+ path
550
+ });
551
+ if (isPlainRecord(value) && (typeof value.id === "string" || typeof value.id === "number")) {
552
+ const target = typeof value.path === "string" ? value.path : path;
553
+ if (target) return new EntityReference({
554
+ id: String(value.id),
555
+ path: target
556
+ });
557
+ }
558
+ return value;
559
+ }
560
+ function isPlainRecord(value) {
561
+ return typeof value === "object" && value !== null && !Array.isArray(value);
562
+ }
500
563
  function buildRebaseData(driver, options) {
501
564
  const cache = /* @__PURE__ */ new Map();
502
565
  const primaryKeysFor = createPrimaryKeyResolver(options);
@@ -1033,6 +1096,6 @@ function buildSdkData(driver, options) {
1033
1096
  return wrapAsSdkData(buildRebaseData(driver), options);
1034
1097
  }
1035
1098
  //#endregion
1036
- export { aggregateAlias, buildRebaseData, buildSdkData, wrapAsEntityData, wrapAsSdkData };
1099
+ export { aggregateAlias, buildRebaseData, buildSdkData, rowToViewModel, wrapAsEntityData, wrapAsSdkData };
1037
1100
 
1038
1101
  //# sourceMappingURL=buildRebaseData.es.js.map