@talkpilot/core-db 1.3.76 → 1.3.78

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 (88) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +3 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/municipal/index.d.ts +1 -0
  8. package/dist/municipal/index.d.ts.map +1 -1
  9. package/dist/municipal/index.js +1 -0
  10. package/dist/municipal/index.js.map +1 -1
  11. package/dist/municipal/residents/index.d.ts +5 -0
  12. package/dist/municipal/residents/index.d.ts.map +1 -0
  13. package/dist/{reconcile → municipal/residents}/index.js +7 -4
  14. package/dist/municipal/residents/index.js.map +1 -0
  15. package/dist/municipal/residents/residents.constants.d.ts +3 -0
  16. package/dist/municipal/residents/residents.constants.d.ts.map +1 -0
  17. package/dist/municipal/residents/residents.constants.js +6 -0
  18. package/dist/municipal/residents/residents.constants.js.map +1 -0
  19. package/dist/municipal/residents/residents.getters.d.ts +9 -0
  20. package/dist/municipal/residents/residents.getters.d.ts.map +1 -0
  21. package/dist/municipal/residents/residents.getters.js +32 -0
  22. package/dist/municipal/residents/residents.getters.js.map +1 -0
  23. package/dist/municipal/residents/residents.schema.d.ts +4 -0
  24. package/dist/municipal/residents/residents.schema.d.ts.map +1 -0
  25. package/dist/municipal/residents/residents.schema.js +29 -0
  26. package/dist/municipal/residents/residents.schema.js.map +1 -0
  27. package/dist/municipal/residents/residents.types.d.ts +15 -0
  28. package/dist/municipal/residents/residents.types.d.ts.map +1 -0
  29. package/dist/{reconcile/reconcile.types.js → municipal/residents/residents.types.js} +1 -1
  30. package/dist/municipal/residents/residents.types.js.map +1 -0
  31. package/dist/talkpilot/flows/flows.schema.d.ts +28 -0
  32. package/dist/talkpilot/flows/flows.schema.d.ts.map +1 -1
  33. package/dist/talkpilot/flows/flows.schema.js +16 -0
  34. package/dist/talkpilot/flows/flows.schema.js.map +1 -1
  35. package/dist/talkpilot/flows/flows.types.d.ts +8 -0
  36. package/dist/talkpilot/flows/flows.types.d.ts.map +1 -1
  37. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts +4 -0
  38. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts.map +1 -0
  39. package/dist/talkpilot/subscriptions/subscriptions.utils.js +20 -0
  40. package/dist/talkpilot/subscriptions/subscriptions.utils.js.map +1 -0
  41. package/dist/test-utils/factories/index.d.ts +1 -0
  42. package/dist/test-utils/factories/index.d.ts.map +1 -1
  43. package/dist/test-utils/factories/index.js +1 -0
  44. package/dist/test-utils/factories/index.js.map +1 -1
  45. package/dist/test-utils/factories/municipal/residents.d.ts +5 -0
  46. package/dist/test-utils/factories/municipal/residents.d.ts.map +1 -0
  47. package/dist/test-utils/factories/municipal/residents.js +22 -0
  48. package/dist/test-utils/factories/municipal/residents.js.map +1 -0
  49. package/package.json +1 -1
  50. package/src/index.ts +1 -0
  51. package/src/municipal/index.ts +1 -0
  52. package/src/municipal/residents/__tests__/residents.spec.ts +92 -0
  53. package/src/municipal/residents/index.ts +4 -0
  54. package/src/municipal/residents/residents.constants.ts +2 -0
  55. package/src/municipal/residents/residents.getters.ts +42 -0
  56. package/src/municipal/residents/residents.schema.ts +28 -0
  57. package/src/municipal/residents/residents.types.ts +17 -0
  58. package/src/talkpilot/flows/__tests__/flows.schema.spec.ts +28 -0
  59. package/src/talkpilot/flows/flows.schema.ts +16 -0
  60. package/src/talkpilot/flows/flows.types.ts +9 -0
  61. package/src/test-utils/factories/index.ts +1 -0
  62. package/src/test-utils/factories/municipal/residents.ts +20 -0
  63. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.d.ts +0 -10
  64. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.d.ts.map +0 -1
  65. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.js +0 -15
  66. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.js.map +0 -1
  67. package/dist/municipal/streets/streets.setters.d.ts +0 -10
  68. package/dist/municipal/streets/streets.setters.d.ts.map +0 -1
  69. package/dist/municipal/streets/streets.setters.js +0 -15
  70. package/dist/municipal/streets/streets.setters.js.map +0 -1
  71. package/dist/reconcile/index.d.ts +0 -5
  72. package/dist/reconcile/index.d.ts.map +0 -1
  73. package/dist/reconcile/index.js.map +0 -1
  74. package/dist/reconcile/reconcile.diff.d.ts +0 -4
  75. package/dist/reconcile/reconcile.diff.d.ts.map +0 -1
  76. package/dist/reconcile/reconcile.diff.js +0 -36
  77. package/dist/reconcile/reconcile.diff.js.map +0 -1
  78. package/dist/reconcile/reconcile.execute.d.ts +0 -7
  79. package/dist/reconcile/reconcile.execute.d.ts.map +0 -1
  80. package/dist/reconcile/reconcile.execute.js +0 -20
  81. package/dist/reconcile/reconcile.execute.js.map +0 -1
  82. package/dist/reconcile/reconcile.ops.d.ts +0 -12
  83. package/dist/reconcile/reconcile.ops.d.ts.map +0 -1
  84. package/dist/reconcile/reconcile.ops.js +0 -24
  85. package/dist/reconcile/reconcile.ops.js.map +0 -1
  86. package/dist/reconcile/reconcile.types.d.ts +0 -32
  87. package/dist/reconcile/reconcile.types.d.ts.map +0 -1
  88. package/dist/reconcile/reconcile.types.js.map +0 -1
@@ -0,0 +1,92 @@
1
+ import { ObjectId } from "mongodb";
2
+ import {
3
+ findResidentsByCityAndPhone,
4
+ getResidentByCityAndIdNumber,
5
+ getResidentByCityPhoneAndIdNumber,
6
+ getResidentById,
7
+ getResidentsCollection,
8
+ } from "../residents.getters";
9
+ import { createResident } from "../../../test-utils/factories/municipal/residents";
10
+
11
+ const CITY = "tests" as const;
12
+ const OTHER_CITY = "eilat" as const;
13
+
14
+ describe("residents getters", () => {
15
+ it("getResidentById returns the document, or null for a missing / invalid id", async () => {
16
+ const resident = createResident({ cityName: CITY });
17
+ await getResidentsCollection().insertOne(resident);
18
+
19
+ const found = await getResidentById(resident._id.toHexString());
20
+ expect(found?._id.equals(resident._id)).toBe(true);
21
+ expect(found?.idNumber).toBe(resident.idNumber);
22
+
23
+ expect(await getResidentById("not-an-id")).toBeNull();
24
+ expect(await getResidentById(new ObjectId().toHexString())).toBeNull();
25
+ });
26
+
27
+ it("findResidentsByCityAndPhone returns only matching city + phone", async () => {
28
+ const phone = "+972501111111";
29
+ const match = createResident({ cityName: CITY, phoneNumber: phone });
30
+ const samePhoneOtherCity = createResident({
31
+ cityName: OTHER_CITY,
32
+ phoneNumber: phone,
33
+ });
34
+ const sameCityOtherPhone = createResident({
35
+ cityName: CITY,
36
+ phoneNumber: "+972502222222",
37
+ });
38
+ await getResidentsCollection().insertMany([
39
+ match,
40
+ samePhoneOtherCity,
41
+ sameCityOtherPhone,
42
+ ]);
43
+
44
+ const found = await findResidentsByCityAndPhone(CITY, phone);
45
+ expect(found).toHaveLength(1);
46
+ expect(found[0]._id.equals(match._id)).toBe(true);
47
+ });
48
+
49
+ it("allows a document with only _id", async () => {
50
+ const resident = { _id: new ObjectId() };
51
+ await getResidentsCollection().insertOne(resident);
52
+
53
+ const found = await getResidentById(resident._id.toHexString());
54
+ expect(found?._id.equals(resident._id)).toBe(true);
55
+ expect(found?.firstName).toBeUndefined();
56
+ });
57
+
58
+ it("getResidentByCityAndIdNumber is scoped to the city", async () => {
59
+ const idNumber = "123456789";
60
+ const match = createResident({ cityName: CITY, idNumber });
61
+ const otherCity = createResident({ cityName: OTHER_CITY, idNumber: "987654321" });
62
+ await getResidentsCollection().insertMany([match, otherCity]);
63
+
64
+ const found = await getResidentByCityAndIdNumber(CITY, idNumber);
65
+ expect(found?._id.equals(match._id)).toBe(true);
66
+
67
+ expect(await getResidentByCityAndIdNumber(OTHER_CITY, idNumber)).toBeNull();
68
+ expect(await getResidentByCityAndIdNumber(CITY, "000000000")).toBeNull();
69
+ });
70
+
71
+ it("getResidentByCityPhoneAndIdNumber requires both phone and id in that city", async () => {
72
+ const phone = "+972501111111";
73
+ const idNumber = "201111111";
74
+ const match = createResident({ cityName: CITY, phoneNumber: phone, idNumber });
75
+ const samePhoneWrongId = createResident({
76
+ cityName: CITY,
77
+ phoneNumber: phone,
78
+ idNumber: "209999999",
79
+ });
80
+ await getResidentsCollection().insertMany([match, samePhoneWrongId]);
81
+
82
+ const found = await getResidentByCityPhoneAndIdNumber(CITY, phone, idNumber);
83
+ expect(found?._id.equals(match._id)).toBe(true);
84
+
85
+ expect(
86
+ await getResidentByCityPhoneAndIdNumber(CITY, phone, "000000000"),
87
+ ).toBeNull();
88
+ expect(
89
+ await getResidentByCityPhoneAndIdNumber(OTHER_CITY, phone, idNumber),
90
+ ).toBeNull();
91
+ });
92
+ });
@@ -0,0 +1,4 @@
1
+ export * from "./residents.getters";
2
+ export { RESIDENTS_COLLECTION } from "./residents.constants";
3
+ export { residentsJsonSchema, residentsIndexes } from "./residents.schema";
4
+ export type { Resident, ResidentDoc } from "./residents.types";
@@ -0,0 +1,2 @@
1
+ /** Mongo collection name for municipal resident records. */
2
+ export const RESIDENTS_COLLECTION = "residents";
@@ -0,0 +1,42 @@
1
+ import { Collection, Filter } from "mongodb";
2
+ import { CityName, getDb, ObjectId, Resident } from "../index";
3
+ import { RESIDENTS_COLLECTION } from "./residents.constants";
4
+
5
+ export const getResidentsCollection = (): Collection<Resident> => {
6
+ return getDb().collection<Resident>(RESIDENTS_COLLECTION);
7
+ };
8
+
9
+ export const findResidents = async (
10
+ filter: Filter<Resident> = {},
11
+ ): Promise<Resident[]> => {
12
+ return getResidentsCollection().find(filter).toArray();
13
+ };
14
+
15
+ export const getResidentById = async (
16
+ residentId: string,
17
+ ): Promise<Resident | null> => {
18
+ if (!ObjectId.isValid(residentId)) return null;
19
+ return getResidentsCollection().findOne({ _id: new ObjectId(residentId) });
20
+ };
21
+
22
+ export const findResidentsByCityAndPhone = async (
23
+ cityName: CityName,
24
+ phoneNumber: string,
25
+ ): Promise<Resident[]> => {
26
+ return getResidentsCollection().find({ cityName, phoneNumber }).toArray();
27
+ };
28
+
29
+ export const getResidentByCityAndIdNumber = async (
30
+ cityName: CityName,
31
+ idNumber: string,
32
+ ): Promise<Resident | null> => {
33
+ return getResidentsCollection().findOne({ cityName, idNumber });
34
+ };
35
+
36
+ export const getResidentByCityPhoneAndIdNumber = async (
37
+ cityName: CityName,
38
+ phoneNumber: string,
39
+ idNumber: string,
40
+ ): Promise<Resident | null> => {
41
+ return getResidentsCollection().findOne({ cityName, phoneNumber, idNumber });
42
+ };
@@ -0,0 +1,28 @@
1
+ import type { Document, IndexDescription } from "mongodb";
2
+
3
+ export const residentsJsonSchema: Document = {
4
+ bsonType: "object",
5
+ properties: {
6
+ cityName: { bsonType: "string" },
7
+ firstName: { bsonType: "string" },
8
+ lastName: { bsonType: "string" },
9
+ idNumber: { bsonType: "string" },
10
+ phoneNumber: { bsonType: "string" },
11
+ address: { bsonType: "string" },
12
+ createdAt: { bsonType: "date" },
13
+ updatedAt: { bsonType: "date" },
14
+ },
15
+ };
16
+
17
+ export const residentsIndexes: IndexDescription[] = [
18
+ { key: { cityName: 1, phoneNumber: 1 }, name: "cityName_1_phoneNumber_1" },
19
+ {
20
+ key: { cityName: 1, idNumber: 1 },
21
+ name: "cityName_1_idNumber_unique",
22
+ unique: true,
23
+ partialFilterExpression: {
24
+ cityName: { $type: "string" },
25
+ idNumber: { $type: "string" },
26
+ },
27
+ },
28
+ ];
@@ -0,0 +1,17 @@
1
+ import { ObjectId, WithId } from "mongodb";
2
+
3
+ import { CityName } from "../utils/types";
4
+
5
+ export type Resident = {
6
+ _id: ObjectId;
7
+ createdAt?: Date;
8
+ updatedAt?: Date;
9
+ cityName?: CityName;
10
+ firstName?: string;
11
+ lastName?: string;
12
+ idNumber?: string;
13
+ phoneNumber?: string;
14
+ address?: string;
15
+ };
16
+
17
+ export type ResidentDoc = WithId<Resident>;
@@ -121,4 +121,32 @@ describe("flowMongoSchema", () => {
121
121
  "null",
122
122
  ]);
123
123
  });
124
+
125
+ it("defines beforeCallEvent as an optional object with url, and afterCallEvent as optional string or null", () => {
126
+ const schema: any = flowMongoSchema;
127
+
128
+ expect(schema.properties).toHaveProperty("beforeCallEvent");
129
+ expect(schema.properties.beforeCallEvent.bsonType).toEqual(["object", "null"]);
130
+ expect(schema.properties.beforeCallEvent.required).toEqual(["url"]);
131
+ expect(schema.properties.beforeCallEvent.properties).toEqual(
132
+ expect.objectContaining({
133
+ url: { bsonType: "string" },
134
+ timeoutMs: { bsonType: ["number", "null"] },
135
+ sendUserAuthToken: { bsonType: ["bool", "null"] },
136
+ wait: { bsonType: ["bool", "null"] },
137
+ })
138
+ );
139
+ expect(schema.properties.beforeCallEvent.properties.allowedKeys).toEqual({
140
+ bsonType: ["array", "null"],
141
+ items: { bsonType: "string" },
142
+ });
143
+ expect(schema.required).not.toContain("beforeCallEvent");
144
+
145
+ expect(schema.properties).toHaveProperty("afterCallEvent");
146
+ expect(schema.properties.afterCallEvent.bsonType).toEqual([
147
+ "string",
148
+ "null",
149
+ ]);
150
+ expect(schema.required).not.toContain("afterCallEvent");
151
+ });
124
152
  });
@@ -175,6 +175,22 @@ export const flowMongoSchema = {
175
175
  additionalProperties: false,
176
176
  },
177
177
  },
178
+ beforeCallEvent: {
179
+ bsonType: ["object", "null"],
180
+ required: ["url"],
181
+ properties: {
182
+ url: { bsonType: "string" },
183
+ timeoutMs: { bsonType: ["number", "null"] },
184
+ sendUserAuthToken: { bsonType: ["bool", "null"] },
185
+ allowedKeys: {
186
+ bsonType: ["array", "null"],
187
+ items: { bsonType: "string" },
188
+ },
189
+ wait: { bsonType: ["bool", "null"] },
190
+ },
191
+ additionalProperties: false,
192
+ },
193
+ afterCallEvent: { bsonType: ["string", "null"] },
178
194
  },
179
195
  additionalProperties: false,
180
196
  } as const;
@@ -167,6 +167,14 @@ export type InternalToolConfig = {
167
167
  params?: Record<string, InternalToolParamConfig>;
168
168
  };
169
169
 
170
+ export type BeforeCallEvent = {
171
+ url: string;
172
+ timeoutMs?: number;
173
+ sendUserAuthToken?: boolean;
174
+ allowedKeys?: string[];
175
+ wait?: boolean;
176
+ };
177
+
170
178
  /* ---------- The Flow object ---------- */
171
179
 
172
180
  export type Flow = {
@@ -191,6 +199,7 @@ export type Flow = {
191
199
  metaKeys?: MetaKey[] | null;
192
200
  userProperties?: UserProperty[] | null;
193
201
  tools?: FlowTool[];
202
+ beforeCallEvent?: BeforeCallEvent;
194
203
  afterCallEvent?: string;
195
204
 
196
205
  products?: string[];
@@ -10,6 +10,7 @@ export * from "./talkpilot/sessions";
10
10
  export * from "./municipal/cities";
11
11
  export * from "./municipal/departmentsSubjects";
12
12
  export * from "./municipal/muniIssues";
13
+ export * from "./municipal/residents";
13
14
  export * from "./municipal/streets";
14
15
  export * from "./municipal/tickets";
15
16
  export * from "./websitalk/scans";
@@ -0,0 +1,20 @@
1
+ import { Factory } from "fishery";
2
+ import { ObjectId } from "mongodb";
3
+ import { faker } from "@faker-js/faker";
4
+ import type { Resident } from "../../../municipal";
5
+
6
+ export const residentFactory = Factory.define<Resident>(() => ({
7
+ _id: new ObjectId(),
8
+ createdAt: new Date(),
9
+ updatedAt: new Date(),
10
+ cityName: faker.location.city(),
11
+ firstName: faker.person.firstName(),
12
+ lastName: faker.person.lastName(),
13
+ idNumber: faker.string.numeric(9),
14
+ phoneNumber: `+97250${faker.string.numeric(7)}`,
15
+ address: faker.location.streetAddress(),
16
+ }));
17
+
18
+ export function createResident(overrides?: Partial<Resident>): Resident {
19
+ return residentFactory.build(overrides);
20
+ }
@@ -1,10 +0,0 @@
1
- import { AnyBulkWriteOperation, BulkWriteOptions, BulkWriteResult } from "mongodb";
2
- import { DepartmentSubject } from "./departmentsSubjects.types";
3
- /**
4
- * Generic batch write for the departmentsSubjects collection — a thin passthrough to the
5
- * driver's bulkWrite, with no diffing/key-building/business logic. `operations` must be
6
- * non-empty (the driver throws on an empty batch). Errors (including partial failures under
7
- * `{ ordered: false }`) propagate unchanged, so callers can still catch `MongoBulkWriteError`.
8
- */
9
- export declare const bulkWriteDepartmentsSubjects: (operations: AnyBulkWriteOperation<DepartmentSubject>[], options?: BulkWriteOptions) => Promise<BulkWriteResult>;
10
- //# sourceMappingURL=departmentsSubjects.setters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"departmentsSubjects.setters.d.ts","sourceRoot":"","sources":["../../../src/municipal/departmentsSubjects/departmentsSubjects.setters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GACvC,YAAY,qBAAqB,CAAC,iBAAiB,CAAC,EAAE,EACtD,UAAU,gBAAgB,KACzB,OAAO,CAAC,eAAe,CAEzB,CAAC"}
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bulkWriteDepartmentsSubjects = void 0;
4
- const departmentsSubjects_getters_1 = require("./departmentsSubjects.getters");
5
- /**
6
- * Generic batch write for the departmentsSubjects collection — a thin passthrough to the
7
- * driver's bulkWrite, with no diffing/key-building/business logic. `operations` must be
8
- * non-empty (the driver throws on an empty batch). Errors (including partial failures under
9
- * `{ ordered: false }`) propagate unchanged, so callers can still catch `MongoBulkWriteError`.
10
- */
11
- const bulkWriteDepartmentsSubjects = async (operations, options) => {
12
- return (0, departmentsSubjects_getters_1.getDepartmentsSubjectsCollection)().bulkWrite(operations, options);
13
- };
14
- exports.bulkWriteDepartmentsSubjects = bulkWriteDepartmentsSubjects;
15
- //# sourceMappingURL=departmentsSubjects.setters.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"departmentsSubjects.setters.js","sourceRoot":"","sources":["../../../src/municipal/departmentsSubjects/departmentsSubjects.setters.ts"],"names":[],"mappings":";;;AAEA,+EAAiF;AAEjF;;;;;GAKG;AACI,MAAM,4BAA4B,GAAG,KAAK,EAC/C,UAAsD,EACtD,OAA0B,EACA,EAAE;IAC5B,OAAO,IAAA,8DAAgC,GAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC3E,CAAC,CAAC;AALW,QAAA,4BAA4B,gCAKvC"}
@@ -1,10 +0,0 @@
1
- import { AnyBulkWriteOperation, BulkWriteOptions, BulkWriteResult } from "mongodb";
2
- import { Street } from "./streets.types";
3
- /**
4
- * Generic batch write for the streets collection — a thin passthrough to the driver's
5
- * bulkWrite, with no diffing/key-building/business logic. `operations` must be non-empty
6
- * (the driver throws on an empty batch). Errors (including partial failures under
7
- * `{ ordered: false }`) propagate unchanged, so callers can still catch `MongoBulkWriteError`.
8
- */
9
- export declare const bulkWriteStreets: (operations: AnyBulkWriteOperation<Street>[], options?: BulkWriteOptions) => Promise<BulkWriteResult>;
10
- //# sourceMappingURL=streets.setters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"streets.setters.d.ts","sourceRoot":"","sources":["../../../src/municipal/streets/streets.setters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAGzC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,YAAY,qBAAqB,CAAC,MAAM,CAAC,EAAE,EAC3C,UAAU,gBAAgB,KACzB,OAAO,CAAC,eAAe,CAEzB,CAAC"}
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bulkWriteStreets = void 0;
4
- const streets_getters_1 = require("./streets.getters");
5
- /**
6
- * Generic batch write for the streets collection — a thin passthrough to the driver's
7
- * bulkWrite, with no diffing/key-building/business logic. `operations` must be non-empty
8
- * (the driver throws on an empty batch). Errors (including partial failures under
9
- * `{ ordered: false }`) propagate unchanged, so callers can still catch `MongoBulkWriteError`.
10
- */
11
- const bulkWriteStreets = async (operations, options) => {
12
- return (0, streets_getters_1.getStreetsCollection)().bulkWrite(operations, options);
13
- };
14
- exports.bulkWriteStreets = bulkWriteStreets;
15
- //# sourceMappingURL=streets.setters.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"streets.setters.js","sourceRoot":"","sources":["../../../src/municipal/streets/streets.setters.ts"],"names":[],"mappings":";;;AAEA,uDAAyD;AAEzD;;;;;GAKG;AACI,MAAM,gBAAgB,GAAG,KAAK,EACnC,UAA2C,EAC3C,OAA0B,EACA,EAAE;IAC5B,OAAO,IAAA,sCAAoB,GAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC,CAAC;AALW,QAAA,gBAAgB,oBAK3B"}
@@ -1,5 +0,0 @@
1
- export * from "./reconcile.types";
2
- export * from "./reconcile.ops";
3
- export * from "./reconcile.diff";
4
- export * from "./reconcile.execute";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reconcile/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reconcile/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,kDAAgC;AAChC,mDAAiC;AACjC,sDAAoC"}
@@ -1,4 +0,0 @@
1
- import { Document } from "mongodb";
2
- import { ReconcileConfig, ReconcileDiffResult } from "./reconcile.types";
3
- export declare function computeReconcileDiff<TSource, TDb extends Document, TKey extends string | number>(config: ReconcileConfig<TSource, TDb, TKey>, now?: Date): ReconcileDiffResult<TDb>;
4
- //# sourceMappingURL=reconcile.diff.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.diff.d.ts","sourceRoot":"","sources":["../../src/reconcile/reconcile.diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEzE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,GAAG,SAAS,QAAQ,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM,EAC9F,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAC3C,GAAG,GAAE,IAAiB,GACrB,mBAAmB,CAAC,GAAG,CAAC,CA8C1B"}
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.computeReconcileDiff = computeReconcileDiff;
4
- function computeReconcileDiff(config, now = new Date()) {
5
- const { source, dbRecords, getSourceKey, getDbKey, buildInsertOp, buildUpdateOp, buildDeactivateOp, shouldDeactivate = () => true, } = config;
6
- const dbByKey = new Map(dbRecords.map((dbRecord) => [getDbKey(dbRecord), dbRecord]));
7
- const sourceKeys = new Set();
8
- const bulkOps = [];
9
- const counts = { inserted: 0, updated: 0, deactivated: 0, exists: 0 };
10
- for (const sourceRecord of source) {
11
- const key = getSourceKey(sourceRecord);
12
- sourceKeys.add(key);
13
- const dbRecord = dbByKey.get(key);
14
- if (!dbRecord) {
15
- bulkOps.push(buildInsertOp(sourceRecord, now));
16
- counts.inserted++;
17
- continue;
18
- }
19
- const updateOp = buildUpdateOp(sourceRecord, dbRecord, now);
20
- if (updateOp) {
21
- bulkOps.push(updateOp);
22
- counts.updated++;
23
- }
24
- else {
25
- counts.exists++;
26
- }
27
- }
28
- for (const dbRecord of dbRecords) {
29
- if (!sourceKeys.has(getDbKey(dbRecord)) && shouldDeactivate(dbRecord)) {
30
- bulkOps.push(buildDeactivateOp(dbRecord, now));
31
- counts.deactivated++;
32
- }
33
- }
34
- return { bulkOps, counts };
35
- }
36
- //# sourceMappingURL=reconcile.diff.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.diff.js","sourceRoot":"","sources":["../../src/reconcile/reconcile.diff.ts"],"names":[],"mappings":";;AAGA,oDAiDC;AAjDD,SAAgB,oBAAoB,CAClC,MAA2C,EAC3C,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,EACJ,MAAM,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GAAG,GAAG,EAAE,CAAC,IAAI,GAC9B,GAAG,MAAM,CAAC;IAEX,MAAM,OAAO,GAAG,IAAI,GAAG,CAAY,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,UAAU,GAAG,IAAI,GAAG,EAAQ,CAAC;IAEnC,MAAM,OAAO,GAAwC,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAEtE,KAAK,MAAM,YAAY,IAAI,MAAM,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QACvC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClB,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC5D,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"}
@@ -1,7 +0,0 @@
1
- import { BulkWriteOptions, Collection, Document } from "mongodb";
2
- import { BulkWriteOp } from "./reconcile.types";
3
- export interface ExecuteReconcileBulkWriteResult {
4
- errors: string[];
5
- }
6
- export declare function executeReconcileBulkWrite<TDb extends Document>(collection: Collection<TDb>, bulkOps: BulkWriteOp<TDb>[], options?: BulkWriteOptions): Promise<ExecuteReconcileBulkWriteResult>;
7
- //# sourceMappingURL=reconcile.execute.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.execute.d.ts","sourceRoot":"","sources":["../../src/reconcile/reconcile.execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAuB,MAAM,SAAS,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,yBAAyB,CAAC,GAAG,SAAS,QAAQ,EAClE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,EAC3B,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,EAC3B,OAAO,GAAE,gBAAqC,GAC7C,OAAO,CAAC,+BAA+B,CAAC,CAa1C"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeReconcileBulkWrite = executeReconcileBulkWrite;
4
- const mongodb_1 = require("mongodb");
5
- async function executeReconcileBulkWrite(collection, bulkOps, options = { ordered: false }) {
6
- if (bulkOps.length === 0)
7
- return { errors: [] };
8
- try {
9
- await collection.bulkWrite(bulkOps, options);
10
- return { errors: [] };
11
- }
12
- catch (err) {
13
- if (err instanceof mongodb_1.MongoBulkWriteError) {
14
- const writeErrors = [err.writeErrors].flat();
15
- return { errors: writeErrors.map((writeError) => `Write error: ${writeError.errmsg}`) };
16
- }
17
- return { errors: [err instanceof Error ? err.message : String(err)] };
18
- }
19
- }
20
- //# sourceMappingURL=reconcile.execute.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.execute.js","sourceRoot":"","sources":["../../src/reconcile/reconcile.execute.ts"],"names":[],"mappings":";;AAOA,8DAiBC;AAxBD,qCAAsF;AAO/E,KAAK,UAAU,yBAAyB,CAC7C,UAA2B,EAC3B,OAA2B,EAC3B,UAA4B,EAAE,OAAO,EAAE,KAAK,EAAE;IAE9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAEhD,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,6BAAmB,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,gBAAgB,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -1,12 +0,0 @@
1
- import { Document, Filter } from "mongodb";
2
- import { BulkWriteOp } from "./reconcile.types";
3
- /**
4
- * updateOne with a plain $set — e.g. a deactivation:
5
- * buildSetOp({ _id }, { isActive: false, updatedAt: now })
6
- */
7
- export declare function buildSetOp<T extends Document>(filter: Filter<T>, setFields: Partial<T>): BulkWriteOp<T>;
8
- /**
9
- * updateOne with $set + $setOnInsert + upsert:true.
10
- */
11
- export declare function buildUpsertOp<T extends Document>(filter: Filter<T>, setFields: Partial<T>, setOnInsertFields?: Partial<T>): BulkWriteOp<T>;
12
- //# sourceMappingURL=reconcile.ops.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.ops.d.ts","sourceRoot":"","sources":["../../src/reconcile/reconcile.ops.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAEvG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,QAAQ,EAC9C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EACrB,iBAAiB,GAAE,OAAO,CAAC,CAAC,CAAM,GACjC,WAAW,CAAC,CAAC,CAAC,CAQhB"}
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildSetOp = buildSetOp;
4
- exports.buildUpsertOp = buildUpsertOp;
5
- /**
6
- * updateOne with a plain $set — e.g. a deactivation:
7
- * buildSetOp({ _id }, { isActive: false, updatedAt: now })
8
- */
9
- function buildSetOp(filter, setFields) {
10
- return { updateOne: { filter, update: { $set: setFields } } };
11
- }
12
- /**
13
- * updateOne with $set + $setOnInsert + upsert:true.
14
- */
15
- function buildUpsertOp(filter, setFields, setOnInsertFields = {}) {
16
- return {
17
- updateOne: {
18
- filter,
19
- update: { $set: setFields, $setOnInsert: setOnInsertFields },
20
- upsert: true,
21
- },
22
- };
23
- }
24
- //# sourceMappingURL=reconcile.ops.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.ops.js","sourceRoot":"","sources":["../../src/reconcile/reconcile.ops.ts"],"names":[],"mappings":";;AAOA,gCAEC;AAKD,sCAYC;AAvBD;;;GAGG;AACH,SAAgB,UAAU,CAAqB,MAAiB,EAAE,SAAqB;IACrF,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAC3B,MAAiB,EACjB,SAAqB,EACrB,oBAAgC,EAAE;IAElC,OAAO;QACL,SAAS,EAAE;YACT,MAAM;YACN,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE;YAC5D,MAAM,EAAE,IAAI;SACb;KACF,CAAC;AACJ,CAAC"}
@@ -1,32 +0,0 @@
1
- import { AnyBulkWriteOperation, Document } from "mongodb";
2
- export type BulkWriteOp<T extends Document> = AnyBulkWriteOperation<T>;
3
- export interface ReconcileCounts {
4
- inserted: number;
5
- updated: number;
6
- deactivated: number;
7
- exists: number;
8
- }
9
- export interface ReconcileDiffResult<TDb extends Document> {
10
- bulkOps: BulkWriteOp<TDb>[];
11
- counts: ReconcileCounts;
12
- }
13
- export interface ReconcileConfig<TSource, TDb extends Document, TKey extends string | number> {
14
- source: TSource[];
15
- dbRecords: TDb[];
16
- getSourceKey: (source: TSource) => TKey;
17
- getDbKey: (dbRecord: TDb) => TKey;
18
- buildInsertOp: (source: TSource, now: Date) => BulkWriteOp<TDb>;
19
- /** Return null when unchanged — counted as `exists`, no op emitted. */
20
- buildUpdateOp: (source: TSource, existing: TDb, now: Date) => BulkWriteOp<TDb> | null;
21
- /**
22
- * Called for every dbRecord missing from source (and passing shouldDeactivate).
23
- * The caller decides the op shape entirely — typically via buildSetOp.
24
- */
25
- buildDeactivateOp: (dbRecord: TDb, now: Date) => BulkWriteOp<TDb>;
26
- /**
27
- * Whether a missing dbRecord should even be considered for deactivation.
28
- * Defaults to always true — core-db has no opinion on what "already inactive" means.
29
- */
30
- shouldDeactivate?: (dbRecord: TDb) => boolean;
31
- }
32
- //# sourceMappingURL=reconcile.types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.types.d.ts","sourceRoot":"","sources":["../../src/reconcile/reconcile.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE1D,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,QAAQ,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB,CAAC,GAAG,SAAS,QAAQ;IACvD,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,OAAO,EAAE,GAAG,SAAS,QAAQ,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM;IAC1F,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,SAAS,EAAE,GAAG,EAAE,CAAC;IACjB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAClC,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,WAAW,CAAC,GAAG,CAAC,CAAC;IAChE,uEAAuE;IACvE,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,KAAK,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACtF;;;OAGG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,KAAK,WAAW,CAAC,GAAG,CAAC,CAAC;IAClE;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;CAC/C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.types.js","sourceRoot":"","sources":["../../src/reconcile/reconcile.types.ts"],"names":[],"mappings":""}