@talkpilot/core-db 1.0.1 → 1.0.3

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.
@@ -19,7 +19,7 @@ This package provides a centralized database layer for multiple domains (TalkPil
19
19
  Each domain is isolated. They have their own `db` instance and must be connected independently.
20
20
 
21
21
  ```typescript
22
- import { mongodbClient, municipalDataMongodbClient } from '@talk-pilot/core-db';
22
+ import { mongodbClient, municipalDataMongodbClient } from '@talkpilot/core-db';
23
23
 
24
24
  // TalkPilot
25
25
  await mongodbClient.connect(uri);
package/DEVELOPMENT.md CHANGED
@@ -32,7 +32,7 @@ If you want to use this package in another project locally without publishing it
32
32
 
33
33
  2. In your PROJECT folder:
34
34
  ```bash
35
- npm link @talk-pilot/core-db
35
+ npm link @talkpilot/core-db
36
36
  ```
37
37
 
38
38
  ## Adding a New Getter
@@ -95,4 +95,4 @@ Each developer needs to add the shared token to their local npm configuration. D
95
95
  ```
96
96
  4. Save and exit.
97
97
 
98
- Now you can run `npm publish` and `npm install` for scoped `@talk-pilot` packages without being prompted for credentials.
98
+ Now you can run `npm publish` and `npm install` for scoped `@talkpilot` packages without being prompted for credentials.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # @talk-pilot/core-db
1
+ # @talkpilot/core-db
2
2
 
3
- [![NPM Version](https://img.shields.io/npm/v/@talk-pilot/core-db)](https://www.npmjs.com/package/@talk-pilot/core-db)
3
+ [![NPM Version](https://img.shields.io/npm/v/@talkpilot/core-db)](https://www.npmjs.com/package/@talkpilot/core-db)
4
4
 
5
5
  A TypeScript-based core database management package designed to provide centralized database connections, ORM integrations, and client utilities for other projects. This package manages connections to both **TalkPilot** and **Municipal** MongoDB databases.
6
6
 
@@ -19,9 +19,9 @@ This package is intended to be used as a dependency in other projects. If you're
19
19
  # In your other project:
20
20
  npm install /path/to/core-db
21
21
  # or if published to a registry:
22
- npm install @talk-pilot/core-db
23
- # or via GitHub (ensure you have built or have a prepare script)
24
- npm install github:Talk-Pilot/core-db
22
+ npm install @talkpilot/core-db
23
+ # or via GitHub
24
+ npm install github:talkpilot/core-db
25
25
  ```
26
26
 
27
27
  ## Quick Start
@@ -31,7 +31,7 @@ npm install github:Talk-Pilot/core-db
31
31
  You must initialize the database clients before using any of the getters.
32
32
 
33
33
  ```typescript
34
- import { mongodbClient, municipalDataMongodbClient } from '@talk-pilot/core-db';
34
+ import { mongodbClient, municipalDataMongodbClient } from '@talkpilot/core-db';
35
35
 
36
36
  async function bootstrap() {
37
37
  // Initialize TalkPilot DB
@@ -49,7 +49,7 @@ bootstrap().catch(console.error);
49
49
  Once initialized, you can import and use any of the exported database getters.
50
50
 
51
51
  ```typescript
52
- import { findAgents, findCities } from '@talk-pilot/core-db';
52
+ import { findAgents, findCities } from '@talkpilot/core-db';
53
53
 
54
54
  async function getSummary() {
55
55
  // Get all agents from TalkPilot DB
@@ -89,7 +89,7 @@ The clients will automatically attempt to use the following environment variable
89
89
 
90
90
  1. Clone the repository and install dependencies:
91
91
  ```bash
92
- git clone https://github.com/Talk-Pilot/core-db.git
92
+ git clone https://github.com/talkpilot/core-db.git
93
93
  cd core-db
94
94
  npm install
95
95
  ```
@@ -128,7 +128,7 @@ To publish a new version of the package:
128
128
 
129
129
  4. **Update in other repos**:
130
130
  ```bash
131
- npm update @talk-pilot/core-db
131
+ npm update @talkpilot/core-db
132
132
  ```
133
133
 
134
134
  ## License
@@ -3,7 +3,7 @@ import { Collection, InsertOneResult } from 'mongodb';
3
3
  declare const getClientAudioBuffersCollection: () => Collection<ClientAudioBufferType>;
4
4
  declare const insertClientAudioBuffer: (audioBufferInput: CreateAudioBufferInput) => Promise<InsertOneResult<ClientAudioBufferType>>;
5
5
  declare const findClientAudioBuffersByCallSidAndRange: (callSid: string, startMs?: number, endMs?: number) => Promise<ClientAudioBufferDoc[]>;
6
- declare const getAudioChunksByCallSid: (callSid: string) => Promise<Buffer[]>;
7
- declare const getMergedAudioByCallSid: (callSid: string) => Promise<Buffer>;
6
+ declare const getAudioChunksByCallSid: (callSid: string, limit?: number) => Promise<Buffer[]>;
7
+ declare const getMergedAudioByCallSid: (callSid: string, limit: number) => Promise<Buffer>;
8
8
  export { insertClientAudioBuffer, getClientAudioBuffersCollection, findClientAudioBuffersByCallSidAndRange, getAudioChunksByCallSid, getMergedAudioByCallSid, };
9
9
  //# sourceMappingURL=clientAudioBuffer.getters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clientAudioBuffer.getters.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEtD,QAAA,MAAM,+BAA+B,QAAO,UAAU,CAAC,qBAAqB,CAE3E,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAC3B,kBAAkB,sBAAsB,KACvC,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAsBhD,CAAC;AAEF,QAAA,MAAM,uCAAuC,GAC3C,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,QAAQ,MAAM,KACb,OAAO,CAAC,oBAAoB,EAAE,CAehC,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAuBxE,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAQtE,CAAC;AAEF,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAC/B,uCAAuC,EACvC,uBAAuB,EACvB,uBAAuB,GACxB,CAAC"}
1
+ {"version":3,"file":"clientAudioBuffer.getters.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEtD,QAAA,MAAM,+BAA+B,QAAO,UAAU,CAAC,qBAAqB,CAE3E,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAC3B,kBAAkB,sBAAsB,KACvC,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAsBhD,CAAC;AAEF,QAAA,MAAM,uCAAuC,GAC3C,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,QAAQ,MAAM,KACb,OAAO,CAAC,oBAAoB,EAAE,CAehC,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAU,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAqBxF,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAU,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,MAAM,CAQrF,CAAC;AAEF,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAC/B,uCAAuC,EACvC,uBAAuB,EACvB,uBAAuB,GACxB,CAAC"}
@@ -46,27 +46,31 @@ const findClientAudioBuffersByCallSidAndRange = async (callSid, startMs, endMs)
46
46
  .toArray();
47
47
  };
48
48
  exports.findClientAudioBuffersByCallSidAndRange = findClientAudioBuffersByCallSidAndRange;
49
- const getAudioChunksByCallSid = async (callSid) => {
50
- const collection = getClientAudioBuffersCollection();
51
- const chunks = await collection.find({ callSid }).toArray();
52
- if (!chunks.length) {
49
+ const getAudioChunksByCallSid = async (callSid, limit) => {
50
+ const query = getClientAudioBuffersCollection().find({ callSid });
51
+ if (limit) {
52
+ query.sort({ bucketStartMs: -1 }).limit(limit);
53
+ }
54
+ else {
55
+ query.sort({ bucketStartMs: 1 });
56
+ }
57
+ const docs = await query.toArray();
58
+ if (!docs.length) {
53
59
  return [];
54
60
  }
55
- chunks.sort((a, b) => a.bucketStartMs - b.bucketStartMs);
56
- return chunks.map((chunk) => {
61
+ const orderedDocs = limit ? docs.reverse() : docs;
62
+ return orderedDocs.map((chunk) => {
57
63
  const data = chunk.data;
58
- if (Buffer.isBuffer(data)) {
64
+ if (Buffer.isBuffer(data))
59
65
  return data;
60
- }
61
- if (data?.buffer) {
66
+ if (data?.buffer)
62
67
  return Buffer.from(data.buffer);
63
- }
64
68
  return Buffer.from(data);
65
69
  });
66
70
  };
67
71
  exports.getAudioChunksByCallSid = getAudioChunksByCallSid;
68
- const getMergedAudioByCallSid = async (callSid) => {
69
- const buffers = await getAudioChunksByCallSid(callSid);
72
+ const getMergedAudioByCallSid = async (callSid, limit) => {
73
+ const buffers = await getAudioChunksByCallSid(callSid, limit);
70
74
  if (!buffers.length) {
71
75
  return Buffer.alloc(0);
72
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"clientAudioBuffer.getters.js","sourceRoot":"","sources":["../../../src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts"],"names":[],"mappings":";;;AAAA,iCAAiC;AAQjC,MAAM,+BAA+B,GAAG,GAAsC,EAAE;IAC9E,OAAO,IAAA,UAAK,GAAE,CAAC,UAAU,CAAwB,oBAAoB,CAAC,CAAC;AACzE,CAAC,CAAC;AAsFA,0EAA+B;AApFjC,MAAM,uBAAuB,GAAG,KAAK,EACnC,gBAAwC,EACS,EAAE;IACnD,MAAM,UAAU,GAAG,+BAA+B,EAAE,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,IAAI,QAAQ,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;IAE3D,MAAM,sBAAsB,GAAG;QAC7B,OAAO,EAAE,gBAAgB,CAAC,OAAO;QACjC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ;QACnC,aAAa,EAAE,gBAAgB,CAAC,aAAa;QAC7C,gBAAgB,EAAE,gBAAgB,CAAC,gBAAgB;QACnD,IAAI,EAAE,gBAAgB,CAAC,IAAI;KAC5B,CAAC;IACF,MAAM,8BAA8B,GAA0B;QAC5D,GAAG,sBAAsB;QACzB,KAAK,EAAE,OAAO;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,YAAY;QACvB,SAAS,EAAE,SAAS;KACrB,CAAC;IACF,OAAO,UAAU,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;AAC9D,CAAC,CAAC;AA2DA,0DAAuB;AAzDzB,MAAM,uCAAuC,GAAG,KAAK,EACnD,OAAe,EACf,OAAgB,EAChB,KAAc,EACmB,EAAE;IACnC,MAAM,UAAU,GAAG,+BAA+B,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACvC,OAAO,UAAU;SACd,IAAI,CAAC;QACJ,OAAO;QACP,aAAa,EAAE;YACb,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;SACjB;KACF,CAAC;SACD,OAAO,EAAE,CAAC;AACf,CAAC,CAAC;AAwCA,0FAAuC;AAtCzC,MAAM,uBAAuB,GAAG,KAAK,EAAE,OAAe,EAAqB,EAAE;IAC3E,MAAM,UAAU,GAAG,+BAA+B,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAE5D,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAEnE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAQ,KAAK,CAAC,IAAI,CAAC;QAE7B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAgBA,0DAAuB;AAdzB,MAAM,uBAAuB,GAAG,KAAK,EAAE,OAAe,EAAmB,EAAE;IACzE,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC,CAAC;AAOA,0DAAuB"}
1
+ {"version":3,"file":"clientAudioBuffer.getters.js","sourceRoot":"","sources":["../../../src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talkpilot/core-db",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
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",
@@ -3,8 +3,9 @@ import {
3
3
  insertClientAudioBuffer,
4
4
  findClientAudioBuffersByCallSidAndRange,
5
5
  getMergedAudioByCallSid,
6
+ getAudioChunksByCallSid,
6
7
  } from '../clientAudioBuffer.getters';
7
- import { ObjectId } from 'mongodb';
8
+ import { ObjectId } from '@core/db';
8
9
  import { createAudioBufferInput } from '../../../test-utils/factories';
9
10
 
10
11
  describe('clientAudioBuffers getters', () => {
@@ -59,20 +60,67 @@ describe('clientAudioBuffers getters', () => {
59
60
  const thirdBuffer = Buffer.from([4, 5]);
60
61
 
61
62
  await insertClientAudioBuffer(
62
- createAudioBufferInput({ callSid, bucketStartMs: 1000, data: secondBuffer })
63
+ createAudioBufferInput({ callSid, bucketStartMs: 1000, data: secondBuffer })
63
64
  );
64
65
  await insertClientAudioBuffer(
65
- createAudioBufferInput({ callSid, bucketStartMs: 500, data: firstBuffer })
66
+ createAudioBufferInput({ callSid, bucketStartMs: 500, data: firstBuffer })
66
67
  );
67
68
  await insertClientAudioBuffer(
68
- createAudioBufferInput({ callSid, bucketStartMs: 3000, data: thirdBuffer })
69
+ createAudioBufferInput({ callSid, bucketStartMs: 3000, data: thirdBuffer })
69
70
  );
70
71
 
71
- const merged = await getMergedAudioByCallSid(callSid);
72
+ const merged = await getMergedAudioByCallSid(callSid, 10);
72
73
  const expected = Buffer.concat([firstBuffer, secondBuffer, thirdBuffer]);
73
74
 
74
75
  expect(merged).toBeInstanceOf(Buffer);
75
76
  expect(merged.length).toBe(expected.length);
76
77
  expect(merged.equals(expected)).toBe(true);
77
78
  });
79
+
80
+ it('should return all audio chunks when less than or equal to limit buffers exist', async () => {
81
+ const callSid = 'CA1234567890abcdef1234567890abclt';
82
+
83
+ const limit = 30;
84
+ const buffers: Buffer[] = [];
85
+ for (let i = 0; i < limit; i++) {
86
+ const buf = Buffer.from([i]);
87
+ buffers.push(buf);
88
+ await insertClientAudioBuffer(
89
+ createAudioBufferInput({
90
+ callSid,
91
+ bucketStartMs: 1000 + i * 1000,
92
+ data: buf,
93
+ })
94
+ );
95
+ }
96
+
97
+ const chunks = await getAudioChunksByCallSid(callSid, limit);
98
+
99
+ expect(chunks).toHaveLength(buffers.length);
100
+ expect(chunks.every((chunk) => chunk instanceof Buffer)).toBe(true);
101
+ expect(Buffer.concat(chunks).equals(Buffer.concat(buffers))).toBe(true);
102
+ });
103
+
104
+ it('should return only the last N audio chunks when more than limit buffers exist', async () => {
105
+ const callSid = 'CA1234567890abcdef1234567890abclm';
106
+
107
+ const limit = 30;
108
+ const buffers: Buffer[] = [];
109
+ for (let i = 0; i < 35; i++) {
110
+ const buf = Buffer.from([i]);
111
+ buffers.push(buf);
112
+ await insertClientAudioBuffer(
113
+ createAudioBufferInput({
114
+ callSid,
115
+ bucketStartMs: 1000 + i * 1000,
116
+ data: buf,
117
+ })
118
+ );
119
+ }
120
+
121
+ const chunks = await getAudioChunksByCallSid(callSid, limit);
122
+ const expectedBuffers = buffers.slice(-limit);
123
+ expect(chunks).toHaveLength(expectedBuffers.length);
124
+ expect(Buffer.concat(chunks).equals(Buffer.concat(expectedBuffers))).toBe(true);
125
+ });
78
126
  });
@@ -57,33 +57,31 @@ const findClientAudioBuffersByCallSidAndRange = async (
57
57
  .toArray();
58
58
  };
59
59
 
60
- const getAudioChunksByCallSid = async (callSid: string): Promise<Buffer[]> => {
61
- const collection = getClientAudioBuffersCollection();
62
- const chunks = await collection.find({ callSid }).toArray();
60
+ const getAudioChunksByCallSid = async (callSid: string, limit?: number): Promise<Buffer[]> => {
61
+ const query = getClientAudioBuffersCollection().find({ callSid });
62
+ if (limit) {
63
+ query.sort({ bucketStartMs: -1 }).limit(limit);
64
+ } else {
65
+ query.sort({ bucketStartMs: 1 });
66
+ }
63
67
 
64
- if (!chunks.length) {
68
+ const docs = await query.toArray();
69
+
70
+ if (!docs.length) {
65
71
  return [];
66
72
  }
73
+ const orderedDocs = limit ? docs.reverse() : docs;
67
74
 
68
- chunks.sort((a: any, b: any) => a.bucketStartMs - b.bucketStartMs);
69
-
70
- return chunks.map((chunk: any) => {
75
+ return orderedDocs.map((chunk) => {
71
76
  const data: any = chunk.data;
72
-
73
- if (Buffer.isBuffer(data)) {
74
- return data;
75
- }
76
-
77
- if (data?.buffer) {
78
- return Buffer.from(data.buffer);
79
- }
80
-
77
+ if (Buffer.isBuffer(data)) return data;
78
+ if (data?.buffer) return Buffer.from(data.buffer);
81
79
  return Buffer.from(data);
82
80
  });
83
81
  };
84
82
 
85
- const getMergedAudioByCallSid = async (callSid: string): Promise<Buffer> => {
86
- const buffers = await getAudioChunksByCallSid(callSid);
83
+ const getMergedAudioByCallSid = async (callSid: string, limit: number): Promise<Buffer> => {
84
+ const buffers = await getAudioChunksByCallSid(callSid, limit);
87
85
 
88
86
  if (!buffers.length) {
89
87
  return Buffer.alloc(0);