eggi-ai-db-schema-2 0.1.1

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