@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
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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":"
|
|
1
|
+
{"version":3,"file":"schema-accounts.d.ts","sourceRoot":"","sources":["../src/schema-accounts.ts"],"names":[],"mappings":"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"}
|
package/dist/schema-accounts.js
CHANGED
|
@@ -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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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":"
|
|
1
|
+
{"version":3,"file":"accounts-shared.d.ts","sourceRoot":"","sources":["../../src/service/accounts-shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,KAAK,EACV,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAC/E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAC9E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAC9E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAClE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAClE,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAC9E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AACpE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AACpE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAC1E,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAEpE,eAAO,MAAM,sBAAsB,iBAAiB,CAAA;AACpD,eAAO,MAAM,gBAAgB,WAAW,CAAA;AACxC,eAAO,MAAM,wBAAwB,oBAAoB,CAAA;AAEzD,KAAK,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;AAEjF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAUD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuB3E;AAoCD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,mBAAmB,iBA0D1B;AAED,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,iBAUlF;AAED,wBAAsB,aAAa,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAC1D,EAAE,EAAE,kBAAkB,EACtB,IAAI,EAAE,CAAC,EAAE,GACR,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAiB1C"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { identityContactPoints } from "@voyantjs/identity/schema";
|
|
2
1
|
import { identityService } from "@voyantjs/identity/service";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
51
|
+
const rows = await db
|
|
88
52
|
.select()
|
|
89
|
-
.from(
|
|
90
|
-
.where(inArray(
|
|
53
|
+
.from(personDirectoryView)
|
|
54
|
+
.where(inArray(personDirectoryView.personId, ids));
|
|
91
55
|
const map = new Map();
|
|
92
|
-
for (const
|
|
93
|
-
map.set(
|
|
94
|
-
email:
|
|
95
|
-
phone:
|
|
96
|
-
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
|
|
128
|
+
const directoryMap = await loadPersonDirectoryMap(db, ids);
|
|
181
129
|
return rows.map((row) => {
|
|
182
130
|
return {
|
|
183
131
|
...row,
|
|
184
|
-
...(
|
|
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.
|
|
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.
|
|
38
|
-
"@voyantjs/db": "0.26.
|
|
39
|
-
"@voyantjs/hono": "0.26.
|
|
40
|
-
"@voyantjs/identity": "0.26.
|
|
41
|
-
"@voyantjs/utils": "0.26.
|
|
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",
|