@voyantjs/crm 0.26.4 → 0.26.5

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.
@@ -786,97 +786,88 @@ export declare const people: import("drizzle-orm/pg-core").PgTableWithColumns<{
786
786
  };
787
787
  dialect: "pg";
788
788
  }>;
789
- export declare const personDirectoryProjections: import("drizzle-orm/pg-core").PgTableWithColumns<{
790
- name: "person_directory_projections";
791
- schema: undefined;
792
- columns: {
793
- personId: import("drizzle-orm/pg-core").PgColumn<{
794
- name: string;
795
- tableName: "person_directory_projections";
796
- dataType: "string";
797
- columnType: "PgText";
798
- data: string;
799
- driverParam: string;
800
- notNull: true;
801
- hasDefault: false;
802
- isPrimaryKey: false;
803
- isAutoincrement: false;
804
- hasRuntimeDefault: false;
805
- enumValues: [string, ...string[]];
806
- baseColumn: never;
807
- identity: undefined;
808
- generated: undefined;
809
- }, {}, {}>;
810
- email: import("drizzle-orm/pg-core").PgColumn<{
811
- name: "email";
812
- tableName: "person_directory_projections";
813
- dataType: "string";
814
- columnType: "PgText";
815
- data: string;
816
- driverParam: string;
817
- notNull: false;
818
- hasDefault: false;
819
- isPrimaryKey: false;
820
- isAutoincrement: false;
821
- hasRuntimeDefault: false;
822
- enumValues: [string, ...string[]];
823
- baseColumn: never;
824
- identity: undefined;
825
- generated: undefined;
826
- }, {}, {}>;
827
- phone: import("drizzle-orm/pg-core").PgColumn<{
828
- name: "phone";
829
- tableName: "person_directory_projections";
830
- dataType: "string";
831
- columnType: "PgText";
832
- data: string;
833
- driverParam: string;
834
- notNull: false;
835
- hasDefault: false;
836
- isPrimaryKey: false;
837
- isAutoincrement: false;
838
- hasRuntimeDefault: false;
839
- enumValues: [string, ...string[]];
840
- baseColumn: never;
841
- identity: undefined;
842
- generated: undefined;
843
- }, {}, {}>;
844
- website: import("drizzle-orm/pg-core").PgColumn<{
845
- name: "website";
846
- tableName: "person_directory_projections";
847
- dataType: "string";
848
- columnType: "PgText";
849
- data: string;
850
- driverParam: string;
851
- notNull: false;
852
- hasDefault: false;
853
- isPrimaryKey: false;
854
- isAutoincrement: false;
855
- hasRuntimeDefault: false;
856
- enumValues: [string, ...string[]];
857
- baseColumn: never;
858
- identity: undefined;
859
- generated: undefined;
860
- }, {}, {}>;
861
- updatedAt: import("drizzle-orm/pg-core").PgColumn<{
862
- name: "updated_at";
863
- tableName: "person_directory_projections";
864
- dataType: "date";
865
- columnType: "PgTimestamp";
866
- data: Date;
867
- driverParam: string;
868
- notNull: true;
869
- hasDefault: true;
870
- isPrimaryKey: false;
871
- isAutoincrement: false;
872
- hasRuntimeDefault: false;
873
- enumValues: undefined;
874
- baseColumn: never;
875
- identity: undefined;
876
- generated: undefined;
877
- }, {}, {}>;
878
- };
879
- dialect: "pg";
789
+ /**
790
+ * `person_directory` is a Postgres VIEW (not a table) that exposes
791
+ * each person's primary email / phone / website by `LATERAL` lookup
792
+ * against `identity_contact_points`. The view is created in the
793
+ * 0028 migration; this binding gives Drizzle a typed read surface.
794
+ *
795
+ * The previous `person_directory_projections` table was a denormalized
796
+ * cache that had to be rebuilt on every contact-point change — see
797
+ * #446 for the discussion of why we replaced it. Indexed lateral
798
+ * joins (`idx_identity_contact_points_entity_kind_primary_created`
799
+ * already exists) keep view reads sub-millisecond at realistic CRM
800
+ * volumes.
801
+ */
802
+ export declare const personDirectoryView: import("drizzle-orm/pg-core").PgViewWithSelection<"person_directory", true, {
803
+ personId: import("drizzle-orm/pg-core").PgColumn<{
804
+ name: string;
805
+ tableName: "person_directory";
806
+ dataType: "string";
807
+ columnType: "PgText";
808
+ data: string;
809
+ driverParam: string;
810
+ notNull: true;
811
+ hasDefault: false;
812
+ isPrimaryKey: false;
813
+ isAutoincrement: false;
814
+ hasRuntimeDefault: false;
815
+ enumValues: [string, ...string[]];
816
+ baseColumn: never;
817
+ identity: undefined;
818
+ generated: undefined;
819
+ }, {}, {}>;
820
+ email: import("drizzle-orm/pg-core").PgColumn<{
821
+ name: "email";
822
+ tableName: "person_directory";
823
+ dataType: "string";
824
+ columnType: "PgText";
825
+ data: string;
826
+ driverParam: string;
827
+ notNull: false;
828
+ hasDefault: false;
829
+ isPrimaryKey: false;
830
+ isAutoincrement: false;
831
+ hasRuntimeDefault: false;
832
+ enumValues: [string, ...string[]];
833
+ baseColumn: never;
834
+ identity: undefined;
835
+ generated: undefined;
836
+ }, {}, {}>;
837
+ phone: import("drizzle-orm/pg-core").PgColumn<{
838
+ name: "phone";
839
+ tableName: "person_directory";
840
+ dataType: "string";
841
+ columnType: "PgText";
842
+ data: string;
843
+ driverParam: string;
844
+ notNull: false;
845
+ hasDefault: false;
846
+ isPrimaryKey: false;
847
+ isAutoincrement: false;
848
+ hasRuntimeDefault: false;
849
+ enumValues: [string, ...string[]];
850
+ baseColumn: never;
851
+ identity: undefined;
852
+ generated: undefined;
853
+ }, {}, {}>;
854
+ website: import("drizzle-orm/pg-core").PgColumn<{
855
+ name: "website";
856
+ tableName: "person_directory";
857
+ dataType: "string";
858
+ columnType: "PgText";
859
+ data: string;
860
+ driverParam: string;
861
+ notNull: false;
862
+ hasDefault: false;
863
+ isPrimaryKey: false;
864
+ isAutoincrement: false;
865
+ hasRuntimeDefault: false;
866
+ enumValues: [string, ...string[]];
867
+ baseColumn: never;
868
+ identity: undefined;
869
+ generated: undefined;
870
+ }, {}, {}>;
880
871
  }>;
881
872
  export declare const personNotes: import("drizzle-orm/pg-core").PgTableWithColumns<{
882
873
  name: "person_notes";
@@ -2105,6 +2096,4 @@ export type Organization = typeof organizations.$inferSelect;
2105
2096
  export type NewOrganization = typeof organizations.$inferInsert;
2106
2097
  export type Person = typeof people.$inferSelect;
2107
2098
  export type NewPerson = typeof people.$inferInsert;
2108
- export type PersonDirectoryProjection = typeof personDirectoryProjections.$inferSelect;
2109
- export type NewPersonDirectoryProjection = typeof personDirectoryProjections.$inferInsert;
2110
2099
  //# sourceMappingURL=schema-accounts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-accounts.d.ts","sourceRoot":"","sources":["../src/schema-accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema-accounts.d.ts","sourceRoot":"","sources":["../src/schema-accounts.ts"],"names":[],"mappings":"AAyBA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,kGAMjC,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,2KAYrC,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCzB,CAAA;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmDlB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKnB,CAAA;AAEb,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,CAAC,YAAY,CAAA;AACxD,MAAM,MAAM,aAAa,GAAG,OAAO,WAAW,CAAC,YAAY,CAAA;AAE3D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,eAAe,CAAC,YAAY,CAAA;AAChE,MAAM,MAAM,iBAAiB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAA;AAEnE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoC/B,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA;AACxE,MAAM,MAAM,qBAAqB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA;AAE3E;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBhC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,oBAAoB,CAAC,YAAY,CAAA;AAC1E,MAAM,MAAM,sBAAsB,GAAG,OAAO,oBAAoB,CAAC,YAAY,CAAA;AAE7E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAe7B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAA;AACpE,MAAM,MAAM,mBAAmB,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAA;AAEvE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC5B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAA;AACxE,MAAM,MAAM,wBAAwB,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAA;AAE3E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWpB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,OAAO,QAAQ,CAAC,YAAY,CAAA;AAClD,MAAM,MAAM,UAAU,GAAG,OAAO,QAAQ,CAAC,YAAY,CAAA;AAErD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB1B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,cAAc,CAAC,YAAY,CAAA;AAC9D,MAAM,MAAM,gBAAgB,GAAG,OAAO,cAAc,CAAC,YAAY,CAAA;AAEjE,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAC5D,MAAM,MAAM,eAAe,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAC/D,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA;AAC/C,MAAM,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { typeId, typeIdRef } from "@voyantjs/db/lib/typeid-column";
2
2
  import { sql } from "drizzle-orm";
3
- import { boolean, check, date, index, integer, jsonb, pgEnum, pgTable, text, timestamp, uniqueIndex, } from "drizzle-orm/pg-core";
3
+ import { boolean, check, date, index, integer, jsonb, pgEnum, pgTable, pgView, text, timestamp, uniqueIndex, } from "drizzle-orm/pg-core";
4
4
  import { communicationChannelEnum, communicationDirectionEnum, recordStatusEnum, relationTypeEnum, } from "./schema-shared.js";
5
5
  /**
6
6
  * Identity-document types stored on `person_documents`. Open-ended via
@@ -112,15 +112,25 @@ export const people = pgTable("people", {
112
112
  index("idx_people_relation_updated").on(table.relation, table.updatedAt),
113
113
  index("idx_people_status_updated").on(table.status, table.updatedAt),
114
114
  ]);
115
- export const personDirectoryProjections = pgTable("person_directory_projections", {
116
- personId: typeIdRef("person_id")
117
- .notNull()
118
- .references(() => people.id, { onDelete: "cascade" }),
115
+ /**
116
+ * `person_directory` is a Postgres VIEW (not a table) that exposes
117
+ * each person's primary email / phone / website by `LATERAL` lookup
118
+ * against `identity_contact_points`. The view is created in the
119
+ * 0028 migration; this binding gives Drizzle a typed read surface.
120
+ *
121
+ * The previous `person_directory_projections` table was a denormalized
122
+ * cache that had to be rebuilt on every contact-point change — see
123
+ * #446 for the discussion of why we replaced it. Indexed lateral
124
+ * joins (`idx_identity_contact_points_entity_kind_primary_created`
125
+ * already exists) keep view reads sub-millisecond at realistic CRM
126
+ * volumes.
127
+ */
128
+ export const personDirectoryView = pgView("person_directory", {
129
+ personId: typeIdRef("person_id").notNull(),
119
130
  email: text("email"),
120
131
  phone: text("phone"),
121
132
  website: text("website"),
122
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
123
- }, (table) => [uniqueIndex("uq_person_directory_projections_person").on(table.personId)]);
133
+ }).existing();
124
134
  export const personNotes = pgTable("person_notes", {
125
135
  id: typeId("person_notes"),
126
136
  personId: typeIdRef("person_id")
@@ -56,8 +56,6 @@ export declare function personBaseFields(data: CreatePersonInput | UpdatePersonI
56
56
  enc: string;
57
57
  } | null | undefined;
58
58
  };
59
- export declare function rebuildPersonDirectoryProjection(db: PostgresJsDatabase, personId: string): Promise<void>;
60
- export declare function rebuildPersonDirectoryProjections(db: PostgresJsDatabase, personIds: string[]): Promise<void>;
61
59
  export declare function syncPersonIdentity(db: PostgresJsDatabase, personId: string, data: PersonIdentityInput): Promise<void>;
62
60
  export declare function deletePersonIdentity(db: PostgresJsDatabase, personId: string): Promise<void>;
63
61
  export declare function hydratePeople<T extends {
@@ -1 +1 @@
1
- {"version":3,"file":"accounts-shared.d.ts","sourceRoot":"","sources":["../../src/service/accounts-shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accounts-shared.d.ts","sourceRoot":"","sources":["../../src/service/accounts-shared.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import { identityContactPoints } from "@voyantjs/identity/schema";
2
1
  import { identityService } from "@voyantjs/identity/service";
3
- import { and, eq, inArray } from "drizzle-orm";
4
- import { personDirectoryProjections } from "../schema.js";
2
+ import { inArray } from "drizzle-orm";
3
+ import { personDirectoryView } from "../schema.js";
5
4
  import { isManagedBySource, normalizeContactValue, toNullableTrimmed } from "./helpers.js";
6
5
  export const organizationEntityType = "organization";
7
6
  export const personEntityType = "person";
@@ -37,80 +36,30 @@ export function personBaseFields(data) {
37
36
  insuranceEncrypted: data.insuranceEncrypted,
38
37
  };
39
38
  }
40
- async function buildPersonDirectoryProjectionRows(db, personIds) {
41
- if (personIds.length === 0) {
42
- return [];
43
- }
44
- const ids = [...new Set(personIds)];
45
- const contactPoints = await db
46
- .select()
47
- .from(identityContactPoints)
48
- .where(and(eq(identityContactPoints.entityType, personEntityType), inArray(identityContactPoints.entityId, ids)));
49
- const contactPointMap = new Map();
50
- for (const point of contactPoints) {
51
- const bucket = contactPointMap.get(point.entityId) ?? [];
52
- bucket.push(point);
53
- contactPointMap.set(point.entityId, bucket);
54
- }
55
- return ids.map((personId) => {
56
- const entityContactPoints = contactPointMap.get(personId) ?? [];
57
- const findPrimaryContactPoint = (kind) => entityContactPoints.find((point) => point.kind === kind && point.isPrimary)?.value ??
58
- entityContactPoints.find((point) => point.kind === kind)?.value ??
59
- null;
60
- return {
61
- personId,
62
- email: findPrimaryContactPoint("email"),
63
- phone: findPrimaryContactPoint("phone"),
64
- website: findPrimaryContactPoint("website"),
65
- };
66
- });
67
- }
68
- export async function rebuildPersonDirectoryProjection(db, personId) {
69
- return rebuildPersonDirectoryProjections(db, [personId]);
70
- }
71
- export async function rebuildPersonDirectoryProjections(db, personIds) {
72
- const ids = [...new Set(personIds)];
73
- if (ids.length === 0) {
74
- return;
75
- }
76
- const rows = await buildPersonDirectoryProjectionRows(db, ids);
77
- await db
78
- .delete(personDirectoryProjections)
79
- .where(inArray(personDirectoryProjections.personId, ids));
80
- await db.insert(personDirectoryProjections).values(rows);
81
- }
82
- async function ensurePersonDirectoryProjectionMap(db, personIds) {
39
+ /**
40
+ * Reads the per-person `(email, phone, website)` triple from the
41
+ * `person_directory` view (replaces the old projection cache —
42
+ * see #446). The view is computed via indexed `LATERAL` joins on
43
+ * `identity_contact_points`, so callers no longer need a rebuild
44
+ * step after contact-point edits.
45
+ */
46
+ async function loadPersonDirectoryMap(db, personIds) {
83
47
  const ids = [...new Set(personIds)];
84
48
  if (ids.length === 0) {
85
49
  return new Map();
86
50
  }
87
- const existing = await db
51
+ const rows = await db
88
52
  .select()
89
- .from(personDirectoryProjections)
90
- .where(inArray(personDirectoryProjections.personId, ids));
53
+ .from(personDirectoryView)
54
+ .where(inArray(personDirectoryView.personId, ids));
91
55
  const map = new Map();
92
- for (const projection of existing) {
93
- map.set(projection.personId, {
94
- email: projection.email,
95
- phone: projection.phone,
96
- website: projection.website,
56
+ for (const row of rows) {
57
+ map.set(row.personId, {
58
+ email: row.email,
59
+ phone: row.phone,
60
+ website: row.website,
97
61
  });
98
62
  }
99
- const missingIds = ids.filter((id) => !map.has(id));
100
- if (missingIds.length > 0) {
101
- await rebuildPersonDirectoryProjections(db, missingIds);
102
- const rebuilt = await db
103
- .select()
104
- .from(personDirectoryProjections)
105
- .where(inArray(personDirectoryProjections.personId, missingIds));
106
- for (const projection of rebuilt) {
107
- map.set(projection.personId, {
108
- email: projection.email,
109
- phone: projection.phone,
110
- website: projection.website,
111
- });
112
- }
113
- }
114
63
  for (const id of ids) {
115
64
  if (!map.has(id)) {
116
65
  map.set(id, emptyPersonHydratedFields());
@@ -157,7 +106,6 @@ export async function syncPersonIdentity(db, personId, data) {
157
106
  if (managedAddress) {
158
107
  await identityService.deleteAddress(db, managedAddress.id);
159
108
  }
160
- await rebuildPersonDirectoryProjection(db, personId);
161
109
  }
162
110
  export async function deletePersonIdentity(db, personId) {
163
111
  const [contactPoints, addresses] = await Promise.all([
@@ -177,11 +125,11 @@ export async function hydratePeople(db, rows) {
177
125
  }));
178
126
  }
179
127
  const ids = rows.map((row) => row.id);
180
- const projectionMap = await ensurePersonDirectoryProjectionMap(db, ids);
128
+ const directoryMap = await loadPersonDirectoryMap(db, ids);
181
129
  return rows.map((row) => {
182
130
  return {
183
131
  ...row,
184
- ...(projectionMap.get(row.id) ?? emptyPersonHydratedFields()),
132
+ ...(directoryMap.get(row.id) ?? emptyPersonHydratedFields()),
185
133
  };
186
134
  });
187
135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/crm",
3
- "version": "0.26.4",
3
+ "version": "0.26.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -34,11 +34,11 @@
34
34
  "drizzle-orm": "^0.45.2",
35
35
  "hono": "^4.12.10",
36
36
  "zod": "^4.3.6",
37
- "@voyantjs/core": "0.26.4",
38
- "@voyantjs/db": "0.26.4",
39
- "@voyantjs/hono": "0.26.4",
40
- "@voyantjs/identity": "0.26.4",
41
- "@voyantjs/utils": "0.26.4"
37
+ "@voyantjs/core": "0.26.5",
38
+ "@voyantjs/db": "0.26.5",
39
+ "@voyantjs/hono": "0.26.5",
40
+ "@voyantjs/identity": "0.26.5",
41
+ "@voyantjs/utils": "0.26.5"
42
42
  },
43
43
  "devDependencies": {
44
44
  "typescript": "^6.0.2",