eggi-ai-db-schema-2 12.54.2

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 (188) hide show
  1. package/CHANGELOG.md +750 -0
  2. package/README.md +655 -0
  3. package/dist/config/database.d.ts +28 -0
  4. package/dist/config/database.d.ts.map +1 -0
  5. package/dist/config/database.js +72 -0
  6. package/dist/config/database.js.map +1 -0
  7. package/dist/index.d.ts +28 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +199 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/database-service.d.ts +689 -0
  12. package/dist/lib/database-service.d.ts.map +1 -0
  13. package/dist/lib/database-service.js +1362 -0
  14. package/dist/lib/database-service.js.map +1 -0
  15. package/dist/lib/db-types.d.ts +167 -0
  16. package/dist/lib/db-types.d.ts.map +1 -0
  17. package/dist/lib/db-types.js +28 -0
  18. package/dist/lib/db-types.js.map +1 -0
  19. package/dist/lib/db.d.ts +58 -0
  20. package/dist/lib/db.d.ts.map +1 -0
  21. package/dist/lib/db.js +292 -0
  22. package/dist/lib/db.js.map +1 -0
  23. package/dist/lib/index.d.ts +11 -0
  24. package/dist/lib/index.d.ts.map +1 -0
  25. package/dist/lib/index.js +26 -0
  26. package/dist/lib/index.js.map +1 -0
  27. package/dist/lib/pg-client.d.ts +50 -0
  28. package/dist/lib/pg-client.d.ts.map +1 -0
  29. package/dist/lib/pg-client.js +106 -0
  30. package/dist/lib/pg-client.js.map +1 -0
  31. package/dist/lib/schema.d.ts +298 -0
  32. package/dist/lib/schema.d.ts.map +1 -0
  33. package/dist/lib/schema.js +12 -0
  34. package/dist/lib/schema.js.map +1 -0
  35. package/dist/migration-manager.d.ts +49 -0
  36. package/dist/migration-manager.d.ts.map +1 -0
  37. package/dist/migration-manager.js +282 -0
  38. package/dist/migration-manager.js.map +1 -0
  39. package/dist/queries/minimal-connections.d.ts +31 -0
  40. package/dist/queries/minimal-connections.d.ts.map +1 -0
  41. package/dist/queries/minimal-connections.js +143 -0
  42. package/dist/queries/minimal-connections.js.map +1 -0
  43. package/dist/schema.ts +340 -0
  44. package/dist/seed.d.ts +8 -0
  45. package/dist/seed.d.ts.map +1 -0
  46. package/dist/seed.js +40 -0
  47. package/dist/seed.js.map +1 -0
  48. package/dist/types/index.d.ts +7 -0
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/index.js +23 -0
  51. package/dist/types/index.js.map +1 -0
  52. package/dist/types/types.d.ts +77 -0
  53. package/dist/types/types.d.ts.map +1 -0
  54. package/dist/types/types.js +3 -0
  55. package/dist/types/types.js.map +1 -0
  56. package/dist/utils/authenticated-user-operations.d.ts +110 -0
  57. package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
  58. package/dist/utils/authenticated-user-operations.js +292 -0
  59. package/dist/utils/authenticated-user-operations.js.map +1 -0
  60. package/dist/utils/authentication-operations.d.ts +48 -0
  61. package/dist/utils/authentication-operations.d.ts.map +1 -0
  62. package/dist/utils/authentication-operations.js +172 -0
  63. package/dist/utils/authentication-operations.js.map +1 -0
  64. package/dist/utils/company-mapping-job-operations.d.ts +103 -0
  65. package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
  66. package/dist/utils/company-mapping-job-operations.js +413 -0
  67. package/dist/utils/company-mapping-job-operations.js.map +1 -0
  68. package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
  69. package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
  70. package/dist/utils/company-sheet-upload-operations.js +135 -0
  71. package/dist/utils/company-sheet-upload-operations.js.map +1 -0
  72. package/dist/utils/contact-operations.d.ts +70 -0
  73. package/dist/utils/contact-operations.d.ts.map +1 -0
  74. package/dist/utils/contact-operations.js +294 -0
  75. package/dist/utils/contact-operations.js.map +1 -0
  76. package/dist/utils/forager-linkedin-operations.d.ts +74 -0
  77. package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
  78. package/dist/utils/forager-linkedin-operations.js +778 -0
  79. package/dist/utils/forager-linkedin-operations.js.map +1 -0
  80. package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
  81. package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
  82. package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
  83. package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
  84. package/dist/utils/index.d.ts +29 -0
  85. package/dist/utils/index.d.ts.map +1 -0
  86. package/dist/utils/index.js +77 -0
  87. package/dist/utils/index.js.map +1 -0
  88. package/dist/utils/introduction-request-operations.d.ts +159 -0
  89. package/dist/utils/introduction-request-operations.d.ts.map +1 -0
  90. package/dist/utils/introduction-request-operations.js +481 -0
  91. package/dist/utils/introduction-request-operations.js.map +1 -0
  92. package/dist/utils/invitation-operations.d.ts +141 -0
  93. package/dist/utils/invitation-operations.d.ts.map +1 -0
  94. package/dist/utils/invitation-operations.js +749 -0
  95. package/dist/utils/invitation-operations.js.map +1 -0
  96. package/dist/utils/linkedin-account-operations.d.ts +45 -0
  97. package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
  98. package/dist/utils/linkedin-account-operations.js +279 -0
  99. package/dist/utils/linkedin-account-operations.js.map +1 -0
  100. package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
  101. package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
  102. package/dist/utils/linkedin-account-relationship-operations.js +274 -0
  103. package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
  104. package/dist/utils/linkedin-data-operations.d.ts +102 -0
  105. package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
  106. package/dist/utils/linkedin-data-operations.js +613 -0
  107. package/dist/utils/linkedin-data-operations.js.map +1 -0
  108. package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
  109. package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
  110. package/dist/utils/linkedin-identifier-utils.js +63 -0
  111. package/dist/utils/linkedin-identifier-utils.js.map +1 -0
  112. package/dist/utils/linkedin-profile-cache.d.ts +131 -0
  113. package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
  114. package/dist/utils/linkedin-profile-cache.js +418 -0
  115. package/dist/utils/linkedin-profile-cache.js.map +1 -0
  116. package/dist/utils/llm-inference-job-operations.d.ts +116 -0
  117. package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
  118. package/dist/utils/llm-inference-job-operations.js +266 -0
  119. package/dist/utils/llm-inference-job-operations.js.map +1 -0
  120. package/dist/utils/mapping-job-operations.d.ts +272 -0
  121. package/dist/utils/mapping-job-operations.d.ts.map +1 -0
  122. package/dist/utils/mapping-job-operations.js +833 -0
  123. package/dist/utils/mapping-job-operations.js.map +1 -0
  124. package/dist/utils/mapping-operations.d.ts +80 -0
  125. package/dist/utils/mapping-operations.d.ts.map +1 -0
  126. package/dist/utils/mapping-operations.js +318 -0
  127. package/dist/utils/mapping-operations.js.map +1 -0
  128. package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
  129. package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
  130. package/dist/utils/on-demand-mapping-operations.js +728 -0
  131. package/dist/utils/on-demand-mapping-operations.js.map +1 -0
  132. package/dist/utils/onboarding-operations.d.ts +53 -0
  133. package/dist/utils/onboarding-operations.d.ts.map +1 -0
  134. package/dist/utils/onboarding-operations.js +223 -0
  135. package/dist/utils/onboarding-operations.js.map +1 -0
  136. package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
  137. package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
  138. package/dist/utils/organization-assignment-job-operations.js +881 -0
  139. package/dist/utils/organization-assignment-job-operations.js.map +1 -0
  140. package/dist/utils/organization-assignment-operations.d.ts +59 -0
  141. package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
  142. package/dist/utils/organization-assignment-operations.js +130 -0
  143. package/dist/utils/organization-assignment-operations.js.map +1 -0
  144. package/dist/utils/organization-operations.d.ts +275 -0
  145. package/dist/utils/organization-operations.d.ts.map +1 -0
  146. package/dist/utils/organization-operations.js +993 -0
  147. package/dist/utils/organization-operations.js.map +1 -0
  148. package/dist/utils/organization-relationship-operations.d.ts +59 -0
  149. package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
  150. package/dist/utils/organization-relationship-operations.js +240 -0
  151. package/dist/utils/organization-relationship-operations.js.map +1 -0
  152. package/dist/utils/quota-operations.d.ts +107 -0
  153. package/dist/utils/quota-operations.d.ts.map +1 -0
  154. package/dist/utils/quota-operations.js +692 -0
  155. package/dist/utils/quota-operations.js.map +1 -0
  156. package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
  157. package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
  158. package/dist/utils/recursive-mapping-job-operations.js +169 -0
  159. package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
  160. package/dist/utils/relationship-operations.d.ts +130 -0
  161. package/dist/utils/relationship-operations.d.ts.map +1 -0
  162. package/dist/utils/relationship-operations.js +329 -0
  163. package/dist/utils/relationship-operations.js.map +1 -0
  164. package/dist/utils/sales-pipeline-operations.d.ts +143 -0
  165. package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
  166. package/dist/utils/sales-pipeline-operations.js +649 -0
  167. package/dist/utils/sales-pipeline-operations.js.map +1 -0
  168. package/dist/utils/skills-operations.d.ts +117 -0
  169. package/dist/utils/skills-operations.d.ts.map +1 -0
  170. package/dist/utils/skills-operations.js +487 -0
  171. package/dist/utils/skills-operations.js.map +1 -0
  172. package/dist/utils/subscription-operations.d.ts +123 -0
  173. package/dist/utils/subscription-operations.d.ts.map +1 -0
  174. package/dist/utils/subscription-operations.js +391 -0
  175. package/dist/utils/subscription-operations.js.map +1 -0
  176. package/dist/utils/unipile-account-operations.d.ts +96 -0
  177. package/dist/utils/unipile-account-operations.d.ts.map +1 -0
  178. package/dist/utils/unipile-account-operations.js +255 -0
  179. package/dist/utils/unipile-account-operations.js.map +1 -0
  180. package/dist/utils/user-industry-operations.d.ts +80 -0
  181. package/dist/utils/user-industry-operations.d.ts.map +1 -0
  182. package/dist/utils/user-industry-operations.js +237 -0
  183. package/dist/utils/user-industry-operations.js.map +1 -0
  184. package/dist/utils/user-operations.d.ts +87 -0
  185. package/dist/utils/user-operations.d.ts.map +1 -0
  186. package/dist/utils/user-operations.js +212 -0
  187. package/dist/utils/user-operations.js.map +1 -0
  188. package/package.json +98 -0
package/README.md ADDED
@@ -0,0 +1,655 @@
1
+ # eggi-ai-db-schema
2
+
3
+ [![npm version](https://badge.fury.io/js/eggi-ai-db-schema.svg)](https://badge.fury.io/js/eggi-ai-db-schema)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Type-safe database schema and client for Eggi.AI with AWS RDS integration using **native PostgreSQL queries**. Perfect for Lambda functions, backend services, and any Node.js application that needs secure, performant database access.
7
+
8
+ ## 📦 Installation
9
+
10
+ ```bash
11
+ npm install eggi-ai-db-schema
12
+ ```
13
+
14
+ ## 🎯 What's New
15
+
16
+ ### v12.13.0 - Organizations in Mapping Jobs
17
+ - ✅ **Organizations Array**: Mapping jobs now include which workspaces they were exported to
18
+ - ✅ **Multiple Organizations**: Support for jobs exported to multiple organizations
19
+
20
+ ### v12.12.0 - Unlimited Quota Support
21
+ - ✅ **Null for Unlimited**: `null` quotaLimit indicates unlimited quotas (PRO_VERSION with active subscription)
22
+ - ✅ **UTC Period Calculations**: Fixed timezone issues - all quota periods use UTC for consistent boundaries
23
+ - ✅ **Always Returns Both**: Daily and monthly quotas always returned for all organizations
24
+
25
+ ### v12.0.0 - Native PostgreSQL Migration
26
+ **🚀 Native PostgreSQL Migration**: Complete removal of Drizzle ORM in favor of native PostgreSQL queries for better performance, flexibility, and control.
27
+
28
+ - ✅ **Direct SQL queries** using the `pg` library
29
+ - ✅ **Full type safety** with TypeScript interfaces
30
+ - ✅ **Better performance** without ORM overhead
31
+ - ✅ **More control** over query optimization
32
+ - ✅ **Cleaner code** with parameterized queries
33
+
34
+ ## 📚 Important Documentation
35
+
36
+ - **[CHANGELOG.md](./CHANGELOG.md)** - Complete version history and changes
37
+ - **[Migration System](./docs/MIGRATIONS.md)** - Custom migration management system
38
+
39
+ ## 🗄️ Database Management
40
+
41
+ ### Schema Architecture
42
+
43
+ This package uses a **multi-schema PostgreSQL architecture**:
44
+
45
+ - **`public` schema**: Core application tables (`users`, `skills`, `organizations`, etc.)
46
+ - **`linkedin` schema**: LinkedIn-specific data (`accounts`, `work_experience`, `education`, etc.)
47
+ - **`monitoring` schema**: System tracking (`mapping_jobs`, `llm_inference_jobs`, etc.)
48
+
49
+ ### Custom Migration System
50
+
51
+ This package uses a **sophisticated custom migration system** that provides:
52
+
53
+ - **Hash Validation**: Detects if local files have been modified after being applied
54
+ - **Environment Support**: Separate dev and prod database connections via AWS Secrets Manager
55
+ - **Comprehensive Error Handling**: Clear error messages and validation
56
+ - **Unified Interface**: Single script for all migration operations
57
+
58
+ #### Migration Commands
59
+
60
+ ```bash
61
+ # Unified migration script
62
+ ./scripts/migrate.sh dev status # Check dev migration status
63
+ ./scripts/migrate.sh dev apply # Apply dev migrations
64
+ ./scripts/migrate.sh dev init # Initialize dev migration system
65
+
66
+ ./scripts/migrate.sh prod status # Check prod migration status
67
+ ./scripts/migrate.sh prod apply # Apply prod migrations
68
+ ./scripts/migrate.sh prod init # Initialize prod migration system
69
+
70
+ # Using npm scripts
71
+ npm run migrate:dev:status # Check dev migration status
72
+ npm run migrate:dev:apply # Apply dev migrations
73
+ npm run migrate:dev:init # Initialize dev migration system
74
+
75
+ npm run migrate:prod:status # Check prod migration status
76
+ npm run migrate:prod:apply # Apply prod migrations
77
+ npm run migrate:prod:init # Initialize prod migration system
78
+ ```
79
+
80
+ #### Migration Files
81
+
82
+ - **Location**: `migrations/` directory
83
+ - **Format**: SQL files with naming pattern `0000_description.sql`
84
+ - **Validation**: SHA256 hash validation ensures file integrity
85
+ - **Tracking**: Custom `migrations.applied_migrations` table tracks applied migrations
86
+
87
+ ## 🚀 Quick Start
88
+
89
+ ### For Lambda Functions (Recommended Approach)
90
+
91
+ ```typescript
92
+ import { dbService } from "eggi-ai-db-schema";
93
+
94
+ // Initialize database connection at module level for reuse across Lambda invocations
95
+ // This ensures optimal connection pooling and prevents race conditions
96
+ const dbInitialization = dbService.initialize({
97
+ connection: {
98
+ databaseUrl: process.env.DATABASE_URL,
99
+ },
100
+ poolConfig: {
101
+ max: 1, // Single connection per Lambda container (optimal for Lambda)
102
+ idleTimeoutMillis: 120000,
103
+ connectionTimeoutMillis: 30000,
104
+ },
105
+ });
106
+
107
+ export const handler = async event => {
108
+ // Ensure database is ready (reuses connection across invocations)
109
+ await dbInitialization;
110
+
111
+ // Use high-level database service methods
112
+ const mappingJob = await dbService.createMappingJobForLinkedInAccount({
113
+ linkedinAccountId: 123,
114
+ jobMetadata: { source: "lambda" },
115
+ });
116
+
117
+ const userProfile = await dbService.getUserById(123);
118
+
119
+ return {
120
+ statusCode: 200,
121
+ body: JSON.stringify({ mappingJob, userProfile }),
122
+ };
123
+ };
124
+ ```
125
+
126
+ ### Direct Database Access
127
+
128
+ ```typescript
129
+ import { initializeDb, getDb } from "eggi-ai-db-schema";
130
+
131
+ export const handler = async event => {
132
+ try {
133
+ // Initialize with smart defaults based on environment
134
+ await initializeDb({
135
+ poolConfig: {
136
+ max: 1, // Lambda: 1, Local: 3, ECS: 5
137
+ },
138
+ });
139
+
140
+ const db = await getDb();
141
+
142
+ // Execute native SQL queries with full type safety
143
+ const result = await db.query(
144
+ `
145
+ SELECT u.id, u.given_name, u.family_name, la.forager_id
146
+ FROM public.users u
147
+ LEFT JOIN linkedin.accounts la ON u.id = la.user_id
148
+ WHERE u.id = $1
149
+ `,
150
+ [123]
151
+ );
152
+
153
+ const user = result.rows[0];
154
+
155
+ return {
156
+ statusCode: 200,
157
+ body: JSON.stringify(user),
158
+ };
159
+ } catch (error) {
160
+ console.error("Database error:", error);
161
+ throw error;
162
+ }
163
+ };
164
+ ```
165
+
166
+ ### Normalized Skills Architecture
167
+
168
+ ```typescript
169
+ import { findOrCreateSkill, addProfileSkills, getPopularSkills } from "eggi-ai-db-schema";
170
+
171
+ // Process LinkedIn profile skills (auto-normalized to lowercase)
172
+ const skillIds = await findOrCreateSkills(db, ["JavaScript", "Machine Learning", "Leadership"]);
173
+
174
+ // Add skills to a profile
175
+ await addProfileSkills(db, linkedinAccountId, [
176
+ { skillId: skillIds[0], displayName: "JavaScript" },
177
+ { skillId: skillIds[1], displayName: "Machine Learning" },
178
+ ]);
179
+
180
+ // Get analytics
181
+ const popularSkills = await getPopularSkills(db, 50);
182
+ // Returns most popular skills across all profiles
183
+ ```
184
+
185
+ ### LinkedIn Account Operations
186
+
187
+ This package provides provider-specific operations for LinkedIn accounts:
188
+
189
+ **Forager Provider Operations:**
190
+ ```typescript
191
+ import {
192
+ findLinkedInAccountByForagerId,
193
+ findLinkedInAccountByPublicIdentifier,
194
+ findOrCreateLinkedInAccountByForagerId,
195
+ storeCompleteLinkedInProfileByForagerId,
196
+ } from "eggi-ai-db-schema";
197
+ ```
198
+
199
+ **Ghost Genius Provider Operations:**
200
+ ```typescript
201
+ import {
202
+ findLinkedInAccountByAcoa,
203
+ findOrCreateLinkedInAccountByAcoa,
204
+ storeCompleteLinkedInProfileByAcoa,
205
+ } from "eggi-ai-db-schema";
206
+ ```
207
+
208
+ **Shared Operations:**
209
+ ```typescript
210
+ import {
211
+ findLinkedInAccountByAnyIdentifier, // Works with forager_id, ACoA, or public_identifier
212
+ } from "eggi-ai-db-schema";
213
+ ```
214
+
215
+ ### LinkedIn Account-Based Relationship Operations
216
+
217
+ ```typescript
218
+ import {
219
+ upsertLinkedInAccountRelationshipScore,
220
+ getLinkedInAccountRelationships,
221
+ getTopLinkedInAccountConnections,
222
+ } from "eggi-ai-db-schema";
223
+
224
+ // Create relationship score between LinkedIn accounts
225
+ await upsertLinkedInAccountRelationshipScore(db, {
226
+ linkedinAccountIdA: 123,
227
+ linkedinAccountIdB: 456,
228
+ score: 85, // 0-100 relationship strength
229
+ modelVersion: "v1.2.0",
230
+ analysisType: "MESSAGE_ANALYSER",
231
+ mappingJobId: 789,
232
+ metadata: {
233
+ sources: ["linkedin"],
234
+ analysisDate: new Date().toISOString(),
235
+ conversationCount: 15,
236
+ messageCount: 89,
237
+ },
238
+ });
239
+
240
+ // Get all relationships for a LinkedIn account
241
+ const relationships = await getLinkedInAccountRelationships(db, 123);
242
+
243
+ // Get top connections for LinkedIn analysis
244
+ const topConnections = await getTopLinkedInAccountConnections(db, 123, 10);
245
+ ```
246
+
247
+ ### For Development
248
+
249
+ ```bash
250
+ # Clone the repository for development
251
+ git clone https://github.com/Eggi-AI-Inc/db-schema.git
252
+ cd db-schema
253
+
254
+ # Set up environment
255
+ cp env.example .env
256
+ # Edit .env with your AWS credentials and secret ARNs
257
+
258
+ # Configure connection (Direct RDS via AWS Secrets Manager)
259
+ cp env.example .env
260
+ # Fill in AWS creds and RDS direct secret ARN
261
+
262
+ # Generate and apply schema
263
+ # Migration commands are now handled by the unified script
264
+ ./scripts/migrate.sh dev status
265
+ ./scripts/migrate.sh dev apply
266
+ ```
267
+
268
+ ## 📦 Usage Examples
269
+
270
+ ### Type-Safe Database Operations
271
+
272
+ ```typescript
273
+ import { getDb, query, queryOne } from "eggi-ai-db-schema";
274
+
275
+ // Get fully-typed database client
276
+ const db = await getDb();
277
+
278
+ // Execute parameterized queries with type safety
279
+ const users = await query<User>(
280
+ db,
281
+ `
282
+ SELECT id, given_name, family_name, created_at
283
+ FROM public.users
284
+ WHERE given_name ILIKE $1
285
+ LIMIT $2
286
+ `,
287
+ [`%John%`, 10]
288
+ );
289
+
290
+ // Query single record
291
+ const user = await queryOne<User>(
292
+ db,
293
+ `
294
+ SELECT id, given_name, family_name
295
+ FROM public.users
296
+ WHERE id = $1
297
+ `,
298
+ [123]
299
+ );
300
+
301
+ // Insert with RETURNING
302
+ const newUser = await queryOne<User>(
303
+ db,
304
+ `
305
+ INSERT INTO public.users (given_name, family_name, created_at)
306
+ VALUES ($1, $2, NOW())
307
+ RETURNING id, given_name, family_name, created_at
308
+ `,
309
+ ["Jane", "Doe"]
310
+ );
311
+
312
+ // Complex joins
313
+ const userProfiles = await query(
314
+ db,
315
+ `
316
+ SELECT
317
+ u.id as user_id,
318
+ u.given_name,
319
+ u.family_name,
320
+ la.forager_id,
321
+ la.public_identifier,
322
+ la.headline
323
+ FROM public.users u
324
+ LEFT JOIN linkedin.accounts la ON u.id = la.user_id
325
+ WHERE u.id = ANY($1::int[])
326
+ `,
327
+ [[123, 456, 789]]
328
+ );
329
+ ```
330
+
331
+ ## 🗄️ Schema Overview
332
+
333
+ | Table | Purpose | Key Fields |
334
+ | ------------------------------ | ------------------------------ | ------------------------------------------------------------- |
335
+ | **public.users** | Core user accounts | `id`, `given_name`, `family_name`, `created_at` |
336
+ | **public.authenticated_users** | Authentication records | `user_id`, `cognito_user_id`, `signup_email` |
337
+ | **linkedin.accounts** | LinkedIn platform identifiers | `forager_id` (nullable), `public_identifier`, `linkedin_identifier_acoa` |
338
+ | **linkedin.work_experience** | Professional experience | `linkedin_account_id`, `company_name`, `title` |
339
+ | **linkedin.education** | Educational background | `linkedin_account_id`, `school_name`, `degree` |
340
+ | **public.contact_infos** | User contact information | `user_id`, `type`, `value`, `source` |
341
+ | **linkedin.relationships** | LinkedIn account relationships | `linkedin_account_id_a`, `linkedin_account_id_b`, `score` |
342
+ | **public.organizations** | Workspaces and teams | `id`, `name`, `workspace_type`, `subscription_tier`, `created_by_user_id` |
343
+ | **monitoring.mapping_jobs** | Relationship analysis jobs | `id`, `linkedin_account_id`, `completed_at` |
344
+ | **monitoring.mapping_job_quotas** | Quota tracking (v12.12.0+) | `id`, `authenticated_user_id`, `organization_id`, `quota_period`, `quota_limit` (nullable), `current_usage` |
345
+ | **monitoring.organization_assignment_jobs** | Org assignment tracking (v12.13.0+) | `id`, `mapping_job_id`, `organization_id`, `completed_at` |
346
+ | **public.skills** | Normalized skills library | `id`, `name`, `normalized_name` |
347
+
348
+ ### Supported Platforms
349
+
350
+ - **LinkedIn** - Professional networking
351
+ - **Email/Contact** - Communication channels
352
+
353
+ ## 📚 Documentation
354
+
355
+ - **[🛠️ Local Development](docs/LOCAL_DEVELOPMENT.md)** - IP whitelisting and local development workflow
356
+ - **[🗄️ Schema Guide](docs/SCHEMA.md)** - Database schema documentation and examples
357
+ - **[🔄 Migration Guide](docs/MIGRATIONS.md)** - Database migration workflows
358
+ - **[📊 API Reference](docs/API.md)** - TypeScript API documentation
359
+
360
+ ## 🚨 Common Issues & Quick Fixes
361
+
362
+ ### AWS RDS SSL Connection Error
363
+
364
+ **Error:**
365
+
366
+ ```
367
+ PostgresError: no pg_hba.conf entry for host <IP>, user <USER>, database <DB>, no encryption
368
+ ```
369
+
370
+ **Quick Fix:**
371
+
372
+ ```bash
373
+ # SSL issues are now handled automatically by the migration system
374
+ ./scripts/migrate.sh dev status
375
+ ```
376
+
377
+ 📖 **Full Solution**: [SSL Fix Documentation](./docs/LOCAL_DEVELOPMENT.md#ssl-certificate-issues) | [Stack Overflow Reference](https://stackoverflow.com/questions/76818549/postgresql-migration-issue-in-aws-rds-with-drizzle-orm-no-pg-hba-conf-entry-fo)
378
+
379
+ ## 🔧 Development Workflow
380
+
381
+ ### Prerequisites
382
+
383
+ 1. **IP Whitelisting**: Your IP address must be whitelisted for database access
384
+ 2. **AWS Credentials**: Configure in `.env` file
385
+ 3. **Node.js 20+**: Required for TypeScript and native pg library
386
+
387
+ ### Quick Setup
388
+
389
+ ```bash
390
+ # 1. Setup environment
391
+ cp env.example .env
392
+ # Edit .env with AWS credentials and DATABASE_SECRET_ARN
393
+
394
+ # 2. Install dependencies
395
+ npm install
396
+
397
+ # 3. Setup database connection
398
+ ./scripts/migrate.sh dev init
399
+
400
+ # 4. Check migration status
401
+ ./scripts/migrate.sh dev status
402
+
403
+ # 5. Apply migrations if needed
404
+ ./scripts/migrate.sh dev apply
405
+ ```
406
+
407
+ ## 🚨 Breaking Changes in v12.0.0
408
+
409
+ ### Native PostgreSQL Migration
410
+
411
+ **MAJOR CHANGE**: v12.0.0 removes Drizzle ORM entirely in favor of native PostgreSQL queries:
412
+
413
+ #### What Changed:
414
+
415
+ - ❌ **Removed**: All Drizzle ORM dependencies (`drizzle-orm`, `postgres`)
416
+ - ❌ **Removed**: Drizzle query builder syntax (`.select()`, `.insert()`, etc.)
417
+ - ✅ **Added**: Native `pg` library with connection pooling
418
+ - ✅ **Added**: Type-safe query helpers (`query`, `queryOne`, `execute`)
419
+ - ✅ **Added**: TypeScript interfaces for all database entities
420
+
421
+ #### Migration Impact:
422
+
423
+ - **All queries** must be rewritten using native SQL
424
+ - **Type definitions** remain unchanged (still strongly typed)
425
+ - **Connection management** improved with native pooling
426
+ - **Performance** improved by removing ORM overhead
427
+
428
+ #### Required Code Updates:
429
+
430
+ ```typescript
431
+ // OLD (v11.x and earlier with Drizzle)
432
+ import { getDb, eq, users } from "eggi-ai-db-schema";
433
+
434
+ const db = await getDb();
435
+ const user = await db.query.users.findFirst({
436
+ where: eq(users.id, 123),
437
+ });
438
+
439
+ // NEW (v12.0.0+ with native SQL)
440
+ import { getDb, queryOne } from "eggi-ai-db-schema";
441
+ import { User } from "eggi-ai-db-schema";
442
+
443
+ const db = await getDb();
444
+ const user = await queryOne<User>(
445
+ db,
446
+ `SELECT id, given_name, family_name, created_at FROM public.users WHERE id = $1`,
447
+ [123]
448
+ );
449
+ ```
450
+
451
+ 📖 **Migration Guide**: See [CHANGELOG.md](./CHANGELOG.md) for complete migration instructions.
452
+
453
+ ## 🎯 Key Features
454
+
455
+ - **🔒 AWS Secrets Manager Integration**: Automatic credential fetching
456
+ - **🌐 IP-based Security**: Secure database access via IP whitelisting
457
+ - **📦 NPM Package**: Reusable across multiple services
458
+ - **🔄 TypeScript Support**: Full type safety with native PostgreSQL
459
+ - **🗄️ Schema Validation**: Custom migration system with hash validation
460
+ - **🚀 LinkedIn Account-Based Relationships**: LinkedIn-scoped relationship analysis
461
+ - **⚡ Object-Oriented Database Service**: Auto-initializing singleton service
462
+ - **🧠 Smart Environment Detection**: Automatic optimal configuration (Lambda: 1 connection, Local: 3, ECS: 5)
463
+ - **⚡️ Native Performance**: Direct SQL queries without ORM overhead
464
+
465
+ ## 📊 Available Scripts
466
+
467
+ | Script | Purpose |
468
+ | ---------------------------------- | --------------------------------------- |
469
+ | `npm run build` | Build TypeScript to dist/ |
470
+ | `npm run dev` | Run example code with tsx |
471
+ | `npm run format` | Format code with Prettier |
472
+ | `npm run type-check` | Run TypeScript type checking |
473
+ | `npm run clean` | Remove dist/ directory |
474
+ | `npm run pack:test` | Test npm package contents |
475
+ | **Migration Scripts** | |
476
+ | `./scripts/migrate.sh dev status` | Check dev migration status |
477
+ | `./scripts/migrate.sh dev apply` | Apply dev migrations |
478
+ | `./scripts/migrate.sh dev init` | Initialize dev migration system |
479
+ | `./scripts/migrate.sh prod status` | Check prod migration status |
480
+ | `./scripts/migrate.sh prod apply` | Apply prod migrations |
481
+ | `./scripts/migrate.sh prod init` | Initialize prod migration system |
482
+ | `npm run migrate:dev:*` | Dev environment migration commands |
483
+ | `npm run migrate:prod:*` | Prod environment migration commands |
484
+ | **Version Management** | |
485
+ | `npm run update-version` | Interactive version updater script |
486
+ | `npm run version:patch` | Increment patch version (1.0.0 → 1.0.1) |
487
+ | `npm run version:minor` | Increment minor version (1.0.0 → 1.1.0) |
488
+ | `npm run version:major` | Increment major version (1.0.0 → 2.0.0) |
489
+
490
+ ## 🚀 CI/CD Pipeline & NPM Publishing
491
+
492
+ This package uses **GitHub Actions** for automated testing and publishing to npm registry with an **npm version-based workflow**.
493
+
494
+ ### 📦 Publishing Workflow
495
+
496
+ The publishing workflow is triggered by:
497
+
498
+ - **Push to main branch** with `package.json` version changes
499
+ - **Manual workflow dispatch** via GitHub Actions UI
500
+
501
+ ### 🏷️ Publishing a New Version
502
+
503
+ #### Method 1: Interactive Script (Recommended)
504
+
505
+ ```bash
506
+ # Use the interactive version updater
507
+ ./scripts/update-version.sh
508
+
509
+ # Follow prompts to enter new version (e.g., 12.0.0)
510
+ # Script updates package.json automatically
511
+
512
+ # Commit and push to main branch
513
+ git add package.json
514
+ git commit -m "bump version to v12.0.0"
515
+ git push origin main
516
+ ```
517
+
518
+ #### Method 2: Manual npm Commands
519
+
520
+ ```bash
521
+ # Increment version using npm
522
+ npm version patch # 1.0.0 → 1.0.1 (bug fixes)
523
+ npm version minor # 1.0.0 → 1.1.0 (new features)
524
+ npm version major # 1.0.0 → 2.0.0 (breaking changes)
525
+
526
+ # Commit and push to main branch
527
+ git add package.json package-lock.json
528
+ git commit -m "bump version to v$(node -p 'require("./package.json").version')"
529
+ git push origin main
530
+ ```
531
+
532
+ ### 🔄 CI/CD Workflow Steps
533
+
534
+ The automated pipeline performs the following:
535
+
536
+ #### **Test Job**
537
+
538
+ - ✅ Checkout code
539
+ - ✅ Setup Node.js 20 with npm cache
540
+ - ✅ Install dependencies (`npm ci`)
541
+ - ✅ Type checking and build (`npm run build`)
542
+ - ✅ Format checking (`npm run format --check`)
543
+
544
+ #### **Publish Job** (runs after tests pass, only when version changes)
545
+
546
+ - ✅ Version change detection (compares current vs previous package.json)
547
+ - ✅ Build package (`npm run build`)
548
+ - ✅ Check if version exists on npm (prevents duplicates)
549
+ - ✅ Publish to npm registry (`npm publish --access public`)
550
+ - ✅ Create GitHub release with git tag (e.g., `v12.0.0`)
551
+ - ✅ Generate release notes with package links
552
+
553
+ ### 📋 Prerequisites
554
+
555
+ Before publishing, ensure you have:
556
+
557
+ - ✅ **NPM_ACCESS_TOKEN** secret configured in GitHub repository settings
558
+ - ✅ Package version updated in `package.json` (if not using npm version commands)
559
+ - ✅ Updated `CHANGELOG.md` with new features/fixes
560
+ - ✅ All tests passing locally
561
+
562
+ ### 📊 Monitoring
563
+
564
+ Monitor publishing progress at:
565
+
566
+ - **GitHub Actions**: `https://github.com/Eggi-AI-Inc/eggi.ai-db-schema/actions`
567
+ - **NPM Package**: `https://www.npmjs.com/package/eggi-ai-db-schema`
568
+
569
+ ### 🔧 Package Configuration
570
+
571
+ The package is configured for:
572
+
573
+ - **Public access** on npm registry
574
+ - **ESM/CommonJS compatibility** via package.json exports
575
+ - **TypeScript definitions** included
576
+ - **Tree-shaking friendly** exports
577
+ - **Minimal bundle size** via optimized .npmignore
578
+
579
+ ### 📦 Package Optimization
580
+
581
+ To keep the package lightweight and focused:
582
+
583
+ - ✅ **Migration files excluded** - `migrations/` directory not included in npm package
584
+ - ✅ **Development files excluded** - Source TypeScript, config files, and docs excluded
585
+ - ✅ **Only essential files** - Compiled JavaScript, TypeScript definitions, and README
586
+ - ✅ **No internal tooling** - Build scripts and development dependencies excluded
587
+
588
+ **Result**: Optimized package size with full TypeScript support and native PostgreSQL functionality
589
+
590
+ ### 📦 Installation in Projects
591
+
592
+ Once published, install in your projects:
593
+
594
+ ```bash
595
+ # Install the package
596
+ npm install eggi-ai-db-schema
597
+
598
+ # Use in Lambda functions
599
+ import { getDb, queryOne } from "eggi-ai-db-schema";
600
+ import { User } from "eggi-ai-db-schema";
601
+ ```
602
+
603
+ ### 🎯 Version Strategy
604
+
605
+ - **Patch** (1.0.x): Bug fixes, security updates
606
+ - **Minor** (1.x.0): New features, backward compatible
607
+ - **Major** (x.0.0): Breaking changes, API changes
608
+
609
+ ## 🔐 Direct Database Access
610
+
611
+ This project uses **public RDS access** with security controls:
612
+
613
+ 1. **IP Whitelisting**: Your IP must be added to infrastructure allowlist
614
+ 2. **SSL Encryption**: All connections require SSL/TLS
615
+ 3. **Direct Connection**: Use any SQL client (pgAdmin, DBeaver, etc.)
616
+ 4. **CI/CD Ready**: GitHub Actions work automatically
617
+
618
+ ## 📈 Architecture
619
+
620
+ ```
621
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
622
+ │ Application │ │ @eggi-ai/ │ │ PostgreSQL │
623
+ │ Services │───▶│ db-schema │───▶│ Database │
624
+ │ │ │ (Native pg) │ │ (IP Whitelisted) │
625
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
626
+
627
+
628
+ ┌─────────────────┐
629
+ │ AWS Secrets │
630
+ │ Manager │
631
+ └─────────────────┘
632
+ ```
633
+
634
+ ## 🆘 Need Help?
635
+
636
+ - **Setup Issues**: Check [Local Development Guide](docs/LOCAL_DEVELOPMENT.md)
637
+ - **Schema Questions**: Review [Schema Documentation](docs/SCHEMA.md)
638
+ - **Migration Issues**: See [Migration Guide](docs/MIGRATIONS.md)
639
+ - **API Usage**: Check [API Reference](docs/API.md)
640
+
641
+ ---
642
+
643
+ **🎯 Result**: Production-ready database schema with secure IP-whitelisted access, AWS integration, native PostgreSQL queries, and comprehensive TypeScript support.
644
+
645
+
646
+ ## 🆘 Need Help?
647
+
648
+ - **Setup Issues**: Check [Local Development Guide](docs/LOCAL_DEVELOPMENT.md)
649
+ - **Schema Questions**: Review [Schema Documentation](docs/SCHEMA.md)
650
+ - **Migration Issues**: See [Migration Guide](docs/MIGRATIONS.md)
651
+ - **API Usage**: Check [API Reference](docs/API.md)
652
+
653
+ ---
654
+
655
+ **🎯 Result**: Production-ready database schema with secure IP-whitelisted access, AWS integration, native PostgreSQL queries, and comprehensive TypeScript support.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Database Configuration
3
+ *
4
+ * Centralized database connection configuration for different environments
5
+ * Uses AWS Secrets Manager for both dev and prod environments
6
+ */
7
+ export interface DatabaseConfig {
8
+ host: string;
9
+ port: number;
10
+ database: string;
11
+ username: string;
12
+ password: string;
13
+ ssl?: boolean;
14
+ }
15
+ /**
16
+ * Get database credentials from AWS Secrets Manager
17
+ */
18
+ declare function getDatabaseCredentials(env: "dev" | "prod"): Promise<DatabaseConfig>;
19
+ export { getDatabaseCredentials };
20
+ /**
21
+ * Get database connection string for environment
22
+ */
23
+ export declare function getConnectionString(env?: "dev" | "prod"): Promise<string>;
24
+ /**
25
+ * Get database config for environment
26
+ */
27
+ export declare function getDatabaseConfig(env?: "dev" | "prod"): Promise<DatabaseConfig>;
28
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/config/database.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAwBD;;GAEG;AACH,iBAAe,sBAAsB,CAAC,GAAG,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAiClF;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,GAAE,KAAK,GAAG,MAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAQtF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,GAAE,KAAK,GAAG,MAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAE5F"}