@talkpilot/core-db 1.1.7 → 1.1.9

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 (23) hide show
  1. package/README.md +7 -0
  2. package/dist/talkpilot/phone_numbers/index.d.ts +2 -2
  3. package/dist/talkpilot/phone_numbers/index.d.ts.map +1 -1
  4. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +5 -2
  5. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -1
  6. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +44 -5
  7. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -1
  8. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts +11 -2
  9. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts.map +1 -1
  10. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js +12 -9
  11. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js.map +1 -1
  12. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts +16 -3
  13. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts.map +1 -1
  14. package/package.json +1 -1
  15. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +100 -11
  16. package/src/talkpilot/phone_numbers/index.ts +2 -2
  17. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +61 -7
  18. package/src/talkpilot/phone_numbers/phone_numbers.schema.ts +12 -9
  19. package/src/talkpilot/phone_numbers/phone_numbers.types.ts +18 -3
  20. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts +0 -4
  21. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts.map +0 -1
  22. package/dist/talkpilot/subscriptions/subscriptions.utils.js +0 -20
  23. package/dist/talkpilot/subscriptions/subscriptions.utils.js.map +0 -1
package/README.md CHANGED
@@ -138,6 +138,13 @@ MIT
138
138
 
139
139
  ## Release Notes
140
140
 
141
+ ### 1.1.9
142
+
143
+ - `getPhoneNumbersForFlows(clientId)` — lists each phone number linked to a flow for that client (newest first), with `flowId`, `phoneNumber`, and `isPrimary`.
144
+ ### 1.1.5
145
+
146
+ - `createPurchasedPhoneNumber` for API-bought numbers (Twilio/Telnyx metadata); optional `flowId` until linked to a flow. Types/schema updated accordingly.
147
+
141
148
  ### 1.0.16
142
149
 
143
150
  - Fixed critical issues present in version 1.0.15.
@@ -1,3 +1,3 @@
1
- export * from "./phone_numbers.getter";
2
- export type { PhoneNumber } from "./phone_numbers.types";
1
+ export * from './phone_numbers.getter';
2
+ export type * from './phone_numbers.types';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,mBAAmB,uBAAuB,CAAC"}
@@ -1,11 +1,14 @@
1
1
  import type { Collection } from "mongodb";
2
- import { Client } from "../index";
3
- import { PhoneNumber, PhoneNumberWithFlow } from "./phone_numbers.types";
2
+ import { Client } from '../index';
3
+ import { ClientPhoneNumberForFlow, PhoneNumber, PhoneNumberWithFlow, PurchasedPhoneProviderPayload } from "./phone_numbers.types";
4
4
  export declare const getPhoneNumbersCollection: () => Collection<PhoneNumber>;
5
5
  export declare const getPhoneDataByPhoneNumber: (phoneNumber: string) => Promise<PhoneNumberWithFlow | null>;
6
6
  export declare const getClientPrimaryPhoneNumber: (clientId: string) => Promise<string | null>;
7
7
  export declare const getClientPhoneNumber: (clientId: string) => Promise<string | null>;
8
8
  export declare const getClientPhoneData: (clientId: string, isPrimary?: boolean) => Promise<PhoneNumber | null>;
9
+ export declare const getPhoneNumbersForFlows: (clientId: string) => Promise<ClientPhoneNumberForFlow[]>;
9
10
  export declare const createPhoneNumberEntity: (phoneNumber: string, flowId: string, clientId: string) => Promise<PhoneNumber>;
11
+ /** API-purchased number; `flowId` may be omitted until the number is bound to a flow. */
12
+ export declare const createPurchasedPhoneNumber: (phoneNumber: string, providerPayload: PurchasedPhoneProviderPayload, clientId: string, flowId?: string | null) => Promise<PhoneNumber>;
10
13
  export declare const findClientByPhoneNumber: (phoneNumber: string) => Promise<Client>;
11
14
  //# sourceMappingURL=phone_numbers.getter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phone_numbers.getter.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.getter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,MAAM,EAMP,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,eAAO,MAAM,yBAAyB,QAAO,UAAU,CAAC,WAAW,CACjB,CAAC;AAEnD,eAAO,MAAM,yBAAyB,GACpC,aAAa,MAAM,KAClB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAwBpC,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CASvB,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAZrB,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAWuC,CAAC;AAEhE,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,YAAY,OAAO,KAClB,OAAO,CAAC,WAAW,GAAG,IAAI,CAK5B,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,UAAU,MAAM,KACf,OAAO,CAAC,WAAW,CAerB,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,KAClB,OAAO,CAAC,MAAM,CAShB,CAAC"}
1
+ {"version":3,"file":"phone_numbers.getter.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.getter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,MAAM,EAMP,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,wBAAwB,EACxB,WAAW,EACX,mBAAmB,EACnB,6BAA6B,EAC9B,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,yBAAyB,QAAO,UAAU,CAAC,WAAW,CACjB,CAAC;AAEnD,eAAO,MAAM,yBAAyB,GACpC,aAAa,MAAM,KAClB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAwBpC,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CASvB,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAZrB,MAAM,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAWuC,CAAC;AAEhE,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,YAAY,OAAO,KAClB,OAAO,CAAC,WAAW,GAAG,IAAI,CAK5B,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,UAAU,MAAM,KACf,OAAO,CAAC,wBAAwB,EAAE,CAepC,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,UAAU,MAAM,KACf,OAAO,CAAC,WAAW,CAerB,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,0BAA0B,GACrC,aAAa,MAAM,EACnB,iBAAiB,6BAA6B,EAC9C,UAAU,MAAM,EAChB,SAAS,MAAM,GAAG,IAAI,KACrB,OAAO,CAAC,WAAW,CA0BrB,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAOjF,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findClientByPhoneNumber = exports.createPhoneNumberEntity = exports.getClientPhoneData = exports.getClientPhoneNumber = exports.getClientPrimaryPhoneNumber = exports.getPhoneDataByPhoneNumber = exports.getPhoneNumbersCollection = void 0;
3
+ exports.findClientByPhoneNumber = exports.createPurchasedPhoneNumber = exports.createPhoneNumberEntity = exports.getPhoneNumbersForFlows = exports.getClientPhoneData = exports.getClientPhoneNumber = exports.getClientPrimaryPhoneNumber = exports.getPhoneDataByPhoneNumber = exports.getPhoneNumbersCollection = void 0;
4
4
  const index_1 = require("../index");
5
5
  const getPhoneNumbersCollection = () => (0, index_1.getDb)().collection("phone_numbers");
6
6
  exports.getPhoneNumbersCollection = getPhoneNumbersCollection;
@@ -42,6 +42,22 @@ const getClientPhoneData = async (clientId, isPrimary) => {
42
42
  return (0, exports.getPhoneNumbersCollection)().findOne(filter, options);
43
43
  };
44
44
  exports.getClientPhoneData = getClientPhoneData;
45
+ const getPhoneNumbersForFlows = async (clientId) => {
46
+ const docs = await (0, exports.getPhoneNumbersCollection)()
47
+ .find({
48
+ client_id: clientId,
49
+ flow_id: { $exists: true, $type: "objectId" },
50
+ })
51
+ .project({ _id: 0, flow_id: 1, phone_number: 1, is_primary: 1 })
52
+ .sort({ createdAt: -1 })
53
+ .toArray();
54
+ return docs.map((doc) => ({
55
+ flowId: String(doc.flow_id),
56
+ phoneNumber: doc.phone_number,
57
+ isPrimary: doc.is_primary,
58
+ }));
59
+ };
60
+ exports.getPhoneNumbersForFlows = getPhoneNumbersForFlows;
45
61
  const createPhoneNumberEntity = async (phoneNumber, flowId, clientId) => {
46
62
  const existing = await (0, exports.getClientPhoneData)(clientId);
47
63
  const isPrimary = !existing;
@@ -59,12 +75,35 @@ const createPhoneNumberEntity = async (phoneNumber, flowId, clientId) => {
59
75
  return phoneNumberData;
60
76
  };
61
77
  exports.createPhoneNumberEntity = createPhoneNumberEntity;
62
- const findClientByPhoneNumber = async (phoneNumber) => {
63
- const phoneData = await (0, exports.getPhoneNumbersCollection)().findOne({
78
+ /** API-purchased number; `flowId` may be omitted until the number is bound to a flow. */
79
+ const createPurchasedPhoneNumber = async (phoneNumber, providerPayload, clientId, flowId) => {
80
+ const existingPhoneForClient = await (0, exports.getClientPhoneData)(clientId);
81
+ const isPrimary = !existingPhoneForClient;
82
+ const now = new Date();
83
+ const trimmedFlowId = flowId?.trim();
84
+ const flowObjectId = trimmedFlowId ? new index_1.ObjectId(trimmedFlowId) : undefined;
85
+ const doc = {
64
86
  phone_number: phoneNumber,
65
- });
87
+ client_id: clientId,
88
+ is_primary: isPrimary,
89
+ ...providerPayload,
90
+ createdAt: now,
91
+ updatedAt: now,
92
+ };
93
+ if (flowObjectId) {
94
+ doc.flow_id = flowObjectId;
95
+ }
96
+ await (0, exports.getPhoneNumbersCollection)().insertOne(doc);
97
+ const created = await (0, exports.getClientPhoneData)(clientId, isPrimary);
98
+ if (!created)
99
+ throw new Error('Failed to create phoneNumber');
100
+ return created;
101
+ };
102
+ exports.createPurchasedPhoneNumber = createPurchasedPhoneNumber;
103
+ const findClientByPhoneNumber = async (phoneNumber) => {
104
+ const phoneData = await (0, exports.getPhoneNumbersCollection)().findOne({ phone_number: phoneNumber });
66
105
  if (!phoneData)
67
- throw new Error("Failed to get phone data");
106
+ throw new Error('Failed to get phone data');
68
107
  const clientId = phoneData.client_id;
69
108
  const client = await (0, index_1.getClientsCollection)().findOne({ clientId });
70
109
  if (!client)
@@ -1 +1 @@
1
- {"version":3,"file":"phone_numbers.getter.js","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.getter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"phone_numbers.getter.js","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.getter.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export declare const phoneNumbersMongoSchema: {
2
2
  readonly bsonType: "object";
3
- readonly required: readonly ["client_id", "flow_id", "phone_number"];
3
+ readonly required: readonly ["client_id", "phone_number"];
4
4
  readonly properties: {
5
5
  readonly _id: {
6
6
  readonly bsonType: "objectId";
@@ -9,7 +9,7 @@ export declare const phoneNumbersMongoSchema: {
9
9
  readonly bsonType: "string";
10
10
  };
11
11
  readonly flow_id: {
12
- readonly bsonType: "string";
12
+ readonly bsonType: readonly ["objectId", "string"];
13
13
  };
14
14
  readonly phone_number: {
15
15
  readonly bsonType: "string";
@@ -17,6 +17,15 @@ export declare const phoneNumbersMongoSchema: {
17
17
  readonly is_primary: {
18
18
  readonly bsonType: "bool";
19
19
  };
20
+ readonly provider: {
21
+ readonly bsonType: "string";
22
+ };
23
+ readonly provider_sid: {
24
+ readonly bsonType: "string";
25
+ };
26
+ readonly friendly_name: {
27
+ readonly bsonType: "string";
28
+ };
20
29
  readonly createdAt: {
21
30
  readonly bsonType: "date";
22
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"phone_numbers.schema.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;CAa1B,CAAC"}
1
+ {"version":3,"file":"phone_numbers.schema.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgB1B,CAAC"}
@@ -2,16 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.phoneNumbersMongoSchema = void 0;
4
4
  exports.phoneNumbersMongoSchema = {
5
- bsonType: "object",
6
- required: ["client_id", "flow_id", "phone_number"],
5
+ bsonType: 'object',
6
+ required: ['client_id', 'phone_number'],
7
7
  properties: {
8
- _id: { bsonType: "objectId" },
9
- client_id: { bsonType: "string" },
10
- flow_id: { bsonType: "string" },
11
- phone_number: { bsonType: "string" },
12
- is_primary: { bsonType: "bool" },
13
- createdAt: { bsonType: "date" },
14
- updatedAt: { bsonType: "date" },
8
+ _id: { bsonType: 'objectId' },
9
+ client_id: { bsonType: 'string' },
10
+ flow_id: { bsonType: ['objectId', 'string'] },
11
+ phone_number: { bsonType: 'string' },
12
+ is_primary: { bsonType: 'bool' },
13
+ provider: { bsonType: 'string' },
14
+ provider_sid: { bsonType: 'string' },
15
+ friendly_name: { bsonType: 'string' },
16
+ createdAt: { bsonType: 'date' },
17
+ updatedAt: { bsonType: 'date' },
15
18
  },
16
19
  additionalProperties: false,
17
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"phone_numbers.schema.js","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,uBAAuB,GAAG;IACrC,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,CAAC;IAClD,UAAU,EAAE;QACV,GAAG,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE;QAC7B,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACjC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAC/B,YAAY,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACpC,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;QAChC,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;QAC/B,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;KAChC;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAC"}
1
+ {"version":3,"file":"phone_numbers.schema.js","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,uBAAuB,GAAG;IACrC,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,CAAC;IACvC,UAAU,EAAE;QACV,GAAG,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE;QAC7B,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACjC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE;QAC7C,YAAY,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACpC,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;QAChC,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAChC,YAAY,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACpC,aAAa,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACrC,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;QAC/B,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;KAChC;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAC"}
@@ -1,16 +1,29 @@
1
- import { ObjectId, WithId } from "mongodb";
2
- import { Flow } from "../flows";
1
+ import { ObjectId, WithId } from 'mongodb';
2
+ import { Flow } from '../flows/flows.types';
3
+ export type PurchasedPhoneProviderPayload = {
4
+ provider: 'twilio' | 'telnyx';
5
+ provider_sid: string;
6
+ friendly_name?: string;
7
+ };
3
8
  export type PhoneNumber = {
4
9
  _id?: ObjectId;
5
10
  client_id: string;
6
- flow_id: ObjectId;
11
+ flow_id?: ObjectId;
7
12
  phone_number: string;
8
13
  subscriptionId?: string;
9
14
  is_primary: boolean;
15
+ provider?: 'twilio' | 'telnyx';
16
+ provider_sid?: string;
17
+ friendly_name?: string;
10
18
  createdAt: Date;
11
19
  updatedAt: Date;
12
20
  };
13
21
  export type PhoneNumberWithFlow = WithId<PhoneNumber> & {
14
22
  flow: Flow;
15
23
  };
24
+ export type ClientPhoneNumberForFlow = {
25
+ flowId: string;
26
+ phoneNumber: string;
27
+ isPrimary: boolean;
28
+ };
16
29
  //# sourceMappingURL=phone_numbers.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phone_numbers.types.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,QAAQ,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"phone_numbers.types.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/phone_numbers/phone_numbers.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAE5C,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talkpilot/core-db",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "Core database package for centralized connections and ORM integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  getPhoneDataByPhoneNumber,
3
3
  getPhoneNumbersCollection,
4
+ getPhoneNumbersForFlows,
4
5
  getClientPhoneNumber,
5
6
  getClientPhoneData,
6
7
  createPhoneNumberEntity,
7
- } from "../phone_numbers.getter";
8
- import { getFlowsCollection } from "../../flows";
9
- import { createFlow, createPhoneNumber } from "../../../test-utils/factories";
10
- import { ObjectId } from "mongodb";
11
-
12
- describe("db.phoneNumbers", () => {
13
- describe("getPhoneDataByPhoneNumber", () => {
14
- it("return phone number data with flow", async () => {
8
+ createPurchasedPhoneNumber,
9
+ } from '../phone_numbers.getter';
10
+ import { getFlowsCollection } from '../../flows/flows.getter';
11
+ import { createFlow, createPhoneNumber } from '../../../test-utils/factories';
12
+ import { ObjectId } from 'mongodb';
13
+
14
+ describe('db.phoneNumbers', () => {
15
+ describe('getPhoneDataByPhoneNumber', () => {
16
+ it('return phone number data with flow', async () => {
15
17
  const flow = createFlow({
16
18
  clientId: "test-client-id",
17
19
  conversationSettings: {
@@ -127,9 +129,66 @@ describe("db.phoneNumbers", () => {
127
129
  });
128
130
  });
129
131
 
130
- describe("createPhoneNumberEntity", () => {
131
- it("creates first phone number as primary", async () => {
132
- const clientId = "newClient";
132
+ describe('getPhoneNumbersForFlows', () => {
133
+ it('returns all phone numbers for the client with flow ObjectIds, newest first', async () => {
134
+ const clientId = 'flowsClient';
135
+ const flow1 = createFlow({ clientId });
136
+ const flow2 = createFlow({ clientId });
137
+ await getFlowsCollection().insertMany([flow1, flow2]);
138
+
139
+ const older = createPhoneNumber({
140
+ client_id: clientId,
141
+ flow_id: flow1._id,
142
+ phone_number: '+100',
143
+ is_primary: true,
144
+ createdAt: new Date('2023-01-01'),
145
+ });
146
+ const newer = createPhoneNumber({
147
+ client_id: clientId,
148
+ flow_id: flow2._id,
149
+ phone_number: '+200',
150
+ is_primary: false,
151
+ createdAt: new Date('2023-06-01'),
152
+ });
153
+
154
+ await getPhoneNumbersCollection().insertMany([older, newer]);
155
+
156
+ const result = await getPhoneNumbersForFlows(clientId);
157
+
158
+ expect(result).toHaveLength(2);
159
+ expect(result[0]).toEqual({
160
+ flowId: String(flow2._id),
161
+ phoneNumber: '+200',
162
+ isPrimary: false,
163
+ });
164
+ expect(result[1]).toEqual({
165
+ flowId: String(flow1._id),
166
+ phoneNumber: '+100',
167
+ isPrimary: true,
168
+ });
169
+ });
170
+
171
+ it('returns an empty array when the client has no phone numbers', async () => {
172
+ const result = await getPhoneNumbersForFlows('noSuchClient');
173
+ expect(result).toEqual([]);
174
+ });
175
+
176
+ it('does not include phone numbers for other clients', async () => {
177
+ const clientA = 'clientA';
178
+ const clientB = 'clientB';
179
+ const flow = createFlow();
180
+ await getFlowsCollection().insertOne(flow);
181
+ const phone = createPhoneNumber({ client_id: clientA, flow_id: flow._id });
182
+ await getPhoneNumbersCollection().insertOne(phone);
183
+
184
+ const result = await getPhoneNumbersForFlows(clientB);
185
+ expect(result).toEqual([]);
186
+ });
187
+ });
188
+
189
+ describe('createPhoneNumberEntity', () => {
190
+ it('creates first phone number as primary', async () => {
191
+ const clientId = 'newClient';
133
192
  const flowId = new ObjectId().toHexString();
134
193
  const phoneNumber = "+123456789";
135
194
 
@@ -155,4 +214,34 @@ describe("db.phoneNumbers", () => {
155
214
  expect(result.is_primary).toBe(false);
156
215
  });
157
216
  });
217
+
218
+ describe('createPurchasedPhoneNumber', () => {
219
+ it('persists a phone_numbers document with provider payload and flow', async () => {
220
+ const clientId = 'purchasedClientDb';
221
+ const flowId = new ObjectId().toHexString();
222
+ const phoneNumber = '+15551234567';
223
+ const providerPayload = {
224
+ provider: 'twilio' as const,
225
+ provider_sid: 'PNxxxxxxxx',
226
+ };
227
+
228
+ await createPurchasedPhoneNumber(
229
+ phoneNumber,
230
+ providerPayload,
231
+ clientId,
232
+ flowId,
233
+ );
234
+
235
+ // Re-read from Mongo to confirm insert succeeded (not only the function return value).
236
+ const stored = await getPhoneNumbersCollection().findOne({ phone_number: phoneNumber });
237
+ expect(stored).not.toBeNull();
238
+ expect(stored).toMatchObject({
239
+ phone_number: phoneNumber,
240
+ client_id: clientId,
241
+ provider: 'twilio',
242
+ provider_sid: 'PNxxxxxxxx',
243
+ flow_id: new ObjectId(flowId),
244
+ });
245
+ });
246
+ });
158
247
  });
@@ -1,2 +1,2 @@
1
- export * from "./phone_numbers.getter";
2
- export type { PhoneNumber } from "./phone_numbers.types";
1
+ export * from './phone_numbers.getter';
2
+ export type * from './phone_numbers.types';
@@ -6,8 +6,13 @@ import {
6
6
  getFlowsCollection,
7
7
  ObjectId,
8
8
  findSubscriptions,
9
- } from "../index";
10
- import { PhoneNumber, PhoneNumberWithFlow } from "./phone_numbers.types";
9
+ } from '../index';
10
+ import {
11
+ ClientPhoneNumberForFlow,
12
+ PhoneNumber,
13
+ PhoneNumberWithFlow,
14
+ PurchasedPhoneProviderPayload
15
+ } from "./phone_numbers.types";
11
16
 
12
17
  export const getPhoneNumbersCollection = (): Collection<PhoneNumber> =>
13
18
  getDb().collection<PhoneNumber>("phone_numbers");
@@ -65,6 +70,25 @@ export const getClientPhoneData = async (
65
70
  return getPhoneNumbersCollection().findOne(filter, options);
66
71
  };
67
72
 
73
+ export const getPhoneNumbersForFlows = async (
74
+ clientId: string,
75
+ ): Promise<ClientPhoneNumberForFlow[]> => {
76
+ const docs = await getPhoneNumbersCollection()
77
+ .find({
78
+ client_id: clientId,
79
+ flow_id: { $exists: true, $type: "objectId" },
80
+ })
81
+ .project({ _id: 0, flow_id: 1, phone_number: 1, is_primary: 1 })
82
+ .sort({ createdAt: -1 })
83
+ .toArray();
84
+
85
+ return docs.map((doc) => ({
86
+ flowId: String(doc.flow_id),
87
+ phoneNumber: doc.phone_number,
88
+ isPrimary: doc.is_primary,
89
+ }));
90
+ };
91
+
68
92
  export const createPhoneNumberEntity = async (
69
93
  phoneNumber: string,
70
94
  flowId: string,
@@ -86,13 +110,43 @@ export const createPhoneNumberEntity = async (
86
110
  return phoneNumberData;
87
111
  };
88
112
 
89
- export const findClientByPhoneNumber = async (
113
+ /** API-purchased number; `flowId` may be omitted until the number is bound to a flow. */
114
+ export const createPurchasedPhoneNumber = async (
90
115
  phoneNumber: string,
91
- ): Promise<Client> => {
92
- const phoneData = await getPhoneNumbersCollection().findOne({
116
+ providerPayload: PurchasedPhoneProviderPayload,
117
+ clientId: string,
118
+ flowId?: string | null,
119
+ ): Promise<PhoneNumber> => {
120
+ const existingPhoneForClient = await getClientPhoneData(clientId);
121
+ const isPrimary = !existingPhoneForClient;
122
+
123
+ const now = new Date();
124
+ const trimmedFlowId = flowId?.trim();
125
+ const flowObjectId = trimmedFlowId ? new ObjectId(trimmedFlowId) : undefined;
126
+
127
+ const doc: PhoneNumber = {
93
128
  phone_number: phoneNumber,
94
- });
95
- if (!phoneData) throw new Error("Failed to get phone data");
129
+ client_id: clientId,
130
+ is_primary: isPrimary,
131
+ ...providerPayload,
132
+ createdAt: now,
133
+ updatedAt: now,
134
+ };
135
+
136
+ if (flowObjectId) {
137
+ doc.flow_id = flowObjectId;
138
+ }
139
+
140
+ await getPhoneNumbersCollection().insertOne(doc);
141
+
142
+ const created = await getClientPhoneData(clientId, isPrimary);
143
+ if (!created) throw new Error('Failed to create phoneNumber');
144
+ return created;
145
+ };
146
+
147
+ export const findClientByPhoneNumber = async (phoneNumber: string): Promise<Client> => {
148
+ const phoneData = await getPhoneNumbersCollection().findOne({ phone_number: phoneNumber });
149
+ if (!phoneData) throw new Error('Failed to get phone data');
96
150
  const clientId = phoneData.client_id;
97
151
  const client = await getClientsCollection().findOne({ clientId });
98
152
  if (!client) throw new Error("Failed to get client");
@@ -1,14 +1,17 @@
1
1
  export const phoneNumbersMongoSchema = {
2
- bsonType: "object",
3
- required: ["client_id", "flow_id", "phone_number"],
2
+ bsonType: 'object',
3
+ required: ['client_id', 'phone_number'],
4
4
  properties: {
5
- _id: { bsonType: "objectId" },
6
- client_id: { bsonType: "string" },
7
- flow_id: { bsonType: "string" },
8
- phone_number: { bsonType: "string" },
9
- is_primary: { bsonType: "bool" },
10
- createdAt: { bsonType: "date" },
11
- updatedAt: { bsonType: "date" },
5
+ _id: { bsonType: 'objectId' },
6
+ client_id: { bsonType: 'string' },
7
+ flow_id: { bsonType: ['objectId', 'string'] },
8
+ phone_number: { bsonType: 'string' },
9
+ is_primary: { bsonType: 'bool' },
10
+ provider: { bsonType: 'string' },
11
+ provider_sid: { bsonType: 'string' },
12
+ friendly_name: { bsonType: 'string' },
13
+ createdAt: { bsonType: 'date' },
14
+ updatedAt: { bsonType: 'date' },
12
15
  },
13
16
  additionalProperties: false,
14
17
  } as const;
@@ -1,15 +1,30 @@
1
- import { ObjectId, WithId } from "mongodb";
2
- import { Flow } from "../flows";
1
+ import { ObjectId, WithId } from 'mongodb';
2
+ import { Flow } from '../flows/flows.types';
3
+
4
+ export type PurchasedPhoneProviderPayload = {
5
+ provider: 'twilio' | 'telnyx';
6
+ provider_sid: string;
7
+ friendly_name?: string;
8
+ };
3
9
 
4
10
  export type PhoneNumber = {
5
11
  _id?: ObjectId;
6
12
  client_id: string;
7
- flow_id: ObjectId;
13
+ flow_id?: ObjectId;
8
14
  phone_number: string;
9
15
  subscriptionId?: string;
10
16
  is_primary: boolean;
17
+ provider?: 'twilio' | 'telnyx';
18
+ provider_sid?: string;
19
+ friendly_name?: string;
11
20
  createdAt: Date;
12
21
  updatedAt: Date;
13
22
  };
14
23
 
15
24
  export type PhoneNumberWithFlow = WithId<PhoneNumber> & { flow: Flow };
25
+
26
+ export type ClientPhoneNumberForFlow = {
27
+ flowId: string;
28
+ phoneNumber: string;
29
+ isPrimary: boolean;
30
+ };
@@ -1,4 +0,0 @@
1
- import { Filter } from 'mongodb';
2
- import { Subscription, SimpleSubscriptionFilter } from '../index';
3
- export declare const buildSimpleQuery: (filter: SimpleSubscriptionFilter) => Filter<Subscription>;
4
- //# sourceMappingURL=subscriptions.utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscriptions.utils.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/subscriptions/subscriptions.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAA6B,MAAM,UAAU,CAAC;AAE7F,eAAO,MAAM,gBAAgB,GAAI,QAAQ,wBAAwB,KAAG,MAAM,CAAC,YAAY,CAetF,CAAC"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildSimpleQuery = void 0;
4
- const mongodb_1 = require("mongodb");
5
- const index_1 = require("../index");
6
- const buildSimpleQuery = (filter) => {
7
- const query = {};
8
- if (filter._id) {
9
- query._id = new mongodb_1.ObjectId(filter._id);
10
- }
11
- index_1.simpleFields.forEach((field) => {
12
- const val = filter[field];
13
- if (val !== undefined) {
14
- query[field] = val;
15
- }
16
- });
17
- return query;
18
- };
19
- exports.buildSimpleQuery = buildSimpleQuery;
20
- //# sourceMappingURL=subscriptions.utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscriptions.utils.js","sourceRoot":"","sources":["../../../src/talkpilot/subscriptions/subscriptions.utils.ts"],"names":[],"mappings":";;;AAAA,qCAA2C;AAC3C,oCAA6F;AAEtF,MAAM,gBAAgB,GAAG,CAAC,MAAgC,EAAwB,EAAE;IACzF,MAAM,KAAK,GAAyB,EAAE,CAAC;IAEvC,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,KAAK,CAAC,GAAG,GAAG,IAAI,kBAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,oBAAY,CAAC,OAAO,CAAC,CAAC,KAAkB,EAAE,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,KAAK,CAAC,KAAK,CAAC,GAAG,GAAU,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAfW,QAAA,gBAAgB,oBAe3B"}