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
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ /**
3
+ * =============================================================================
4
+ * UNIPILE ACCOUNT OPERATIONS UTILITIES
5
+ * =============================================================================
6
+ * Utility functions for creating and managing Unipile social media accounts
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createUnipileAccount = createUnipileAccount;
10
+ exports.upsertUnipileAccount = upsertUnipileAccount;
11
+ exports.getUserLinkedAccountStatus = getUserLinkedAccountStatus;
12
+ exports.checkAcoaAlreadyConnectedToDifferentUser = checkAcoaAlreadyConnectedToDifferentUser;
13
+ exports.batchMarkAccountsAsSynced = batchMarkAccountsAsSynced;
14
+ const pg_client_1 = require("../lib/pg-client");
15
+ const db_1 = require("../lib/db");
16
+ // =============================================================================
17
+ // UNIPILE ACCOUNT OPERATIONS
18
+ // =============================================================================
19
+ /**
20
+ * Creates a new Unipile account record
21
+ *
22
+ * @param data - Unipile account creation data
23
+ * @returns Promise resolving to the created account
24
+ */
25
+ async function createUnipileAccount(db, data) {
26
+ if (!data.linkedinAccountId || !data.unipileAccountId) {
27
+ throw new Error("Missing required fields: linkedinAccountId and unipileAccountId are required");
28
+ }
29
+ try {
30
+ const sql = `
31
+ INSERT INTO public.unipile_accounts (
32
+ linkedin_account_id,
33
+ unipile_account_id,
34
+ is_active,
35
+ connected_at,
36
+ last_synced_at,
37
+ metadata,
38
+ created_at,
39
+ updated_at
40
+ )
41
+ VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
42
+ RETURNING
43
+ id,
44
+ linkedin_account_id,
45
+ unipile_account_id,
46
+ is_active,
47
+ connected_at,
48
+ last_synced_at,
49
+ metadata,
50
+ created_at,
51
+ updated_at
52
+ `;
53
+ const result = await (0, pg_client_1.queryOne)(db, sql, [
54
+ data.linkedinAccountId,
55
+ data.unipileAccountId,
56
+ data.isActive ?? true,
57
+ data.connectedAt || new Date(),
58
+ data.lastSyncedAt || null,
59
+ JSON.stringify(data.metadata || {}),
60
+ ]);
61
+ if (!result) {
62
+ throw new Error("Failed to create Unipile account");
63
+ }
64
+ return result;
65
+ }
66
+ catch (error) {
67
+ if (error instanceof Error && error.message.includes("unique constraint")) {
68
+ throw new Error(`Social account already has a Unipile account linked`);
69
+ }
70
+ throw new Error(`Failed to create Unipile account: ${error instanceof Error ? error.message : "Unknown error"}`);
71
+ }
72
+ }
73
+ /**
74
+ * Creates or updates a Unipile account (upsert)
75
+ *
76
+ * @param data - Unipile account data
77
+ * @returns Promise resolving to the created or updated account
78
+ */
79
+ async function upsertUnipileAccount(db, data) {
80
+ if (!data.linkedinAccountId || !data.unipileAccountId) {
81
+ throw new Error("Missing required fields: linkedinAccountId and unipileAccountId are required");
82
+ }
83
+ try {
84
+ const sql = `
85
+ INSERT INTO public.unipile_accounts (
86
+ linkedin_account_id,
87
+ unipile_account_id,
88
+ is_active,
89
+ connected_at,
90
+ last_synced_at,
91
+ metadata,
92
+ created_at,
93
+ updated_at
94
+ )
95
+ VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
96
+ ON CONFLICT (linkedin_account_id)
97
+ DO UPDATE SET
98
+ unipile_account_id = EXCLUDED.unipile_account_id,
99
+ is_active = EXCLUDED.is_active,
100
+ connected_at = EXCLUDED.connected_at,
101
+ last_synced_at = EXCLUDED.last_synced_at,
102
+ metadata = EXCLUDED.metadata,
103
+ updated_at = NOW()
104
+ RETURNING
105
+ id,
106
+ linkedin_account_id,
107
+ unipile_account_id,
108
+ is_active,
109
+ connected_at,
110
+ last_synced_at,
111
+ metadata,
112
+ created_at,
113
+ updated_at
114
+ `;
115
+ const result = await (0, pg_client_1.queryOne)(db, sql, [
116
+ data.linkedinAccountId,
117
+ data.unipileAccountId,
118
+ data.isActive ?? true,
119
+ data.connectedAt || new Date(),
120
+ data.lastSyncedAt || null,
121
+ JSON.stringify(data.metadata || {}),
122
+ ]);
123
+ if (!result) {
124
+ throw new Error("Failed to upsert Unipile account");
125
+ }
126
+ return result;
127
+ }
128
+ catch (error) {
129
+ throw new Error(`Failed to upsert Unipile account: ${error instanceof Error ? error.message : "Unknown error"}`);
130
+ }
131
+ }
132
+ /**
133
+ * Gets a simple boolean map of which social accounts are linked for a user
134
+ * Optimized for frontend UI to show connection status without sensitive data
135
+ *
136
+ * @param cognitoUserId - The Cognito user ID
137
+ * @param activeOnly - Whether to only consider active accounts (default: true)
138
+ * @returns Promise resolving to a simple boolean map of linked platforms
139
+ */
140
+ async function getUserLinkedAccountStatus(db, cognitoUserId, activeOnly = true) {
141
+ try {
142
+ // First get the user ID from authenticated_users table
143
+ const userSql = `
144
+ SELECT user_id
145
+ FROM authentication.users
146
+ WHERE cognito_user_id = $1
147
+ LIMIT 1
148
+ `;
149
+ const authUser = await (0, pg_client_1.queryOne)(db, userSql, [cognitoUserId]);
150
+ if (!authUser || !authUser.user_id) {
151
+ // User not found - return all false
152
+ return {
153
+ linkedin: false,
154
+ whatsapp: false,
155
+ twitter: false,
156
+ instagram: false,
157
+ facebook: false,
158
+ };
159
+ }
160
+ // Get LinkedIn accounts that have active Unipile connections
161
+ const linkedAccountsSql = `
162
+ SELECT la.id
163
+ FROM linkedin.accounts la
164
+ INNER JOIN public.unipile_accounts ua ON la.id = ua.linkedin_account_id
165
+ WHERE la.user_id = $1
166
+ ${activeOnly ? 'AND ua.is_active = true' : ''}
167
+ LIMIT 1
168
+ `;
169
+ const linkedAccounts = await (0, pg_client_1.query)(db, linkedAccountsSql, [authUser.user_id]);
170
+ // Since linkedinAccounts is LinkedIn-only, any result means LinkedIn is connected
171
+ const hasLinkedIn = linkedAccounts.length > 0;
172
+ return {
173
+ linkedin: hasLinkedIn,
174
+ whatsapp: false, // Only LinkedIn is supported in new schema
175
+ twitter: false,
176
+ instagram: false,
177
+ facebook: false,
178
+ };
179
+ }
180
+ catch (error) {
181
+ throw new Error(`Failed to get social account status: ${error instanceof Error ? error.message : "Unknown error"}`);
182
+ }
183
+ }
184
+ /**
185
+ * Checks if a LinkedIn account with the given ACoA identifier is already connected
186
+ * to a different user via an active Unipile account
187
+ *
188
+ * @param db - Database connection
189
+ * @param linkedinIdentifierAcoa - The ACoA identifier to check
190
+ * @param currentUserId - The current user ID (to exclude from the check)
191
+ * @returns Promise resolving to the existing account's user ID if found, null otherwise
192
+ */
193
+ async function checkAcoaAlreadyConnectedToDifferentUser(db, linkedinIdentifierAcoa, currentUserId) {
194
+ if (!linkedinIdentifierAcoa || !linkedinIdentifierAcoa.startsWith("ACoA")) {
195
+ throw new Error("Invalid ACoA identifier - must start with 'ACoA'");
196
+ }
197
+ try {
198
+ const sql = `
199
+ SELECT la.user_id
200
+ FROM linkedin.accounts la
201
+ INNER JOIN public.unipile_accounts ua ON la.id = ua.linkedin_account_id
202
+ WHERE la.linkedin_identifier_acoa = $1
203
+ AND la.user_id != $2
204
+ AND ua.is_active = true
205
+ LIMIT 1
206
+ `;
207
+ const result = await (0, pg_client_1.queryOne)(db, sql, [linkedinIdentifierAcoa, currentUserId]);
208
+ return result?.user_id || null;
209
+ }
210
+ catch (error) {
211
+ throw new Error(`Failed to check ACoA connection: ${error instanceof Error ? error.message : "Unknown error"}`);
212
+ }
213
+ }
214
+ /**
215
+ * Batch updates last synced time for multiple accounts
216
+ *
217
+ * @param accountIds - Array of account IDs to update
218
+ * @param syncTime - Optional: specific sync time (defaults to now)
219
+ * @returns Promise resolving to number of updated accounts
220
+ */
221
+ async function batchMarkAccountsAsSynced(db, accountIds, syncTime) {
222
+ if (accountIds.length === 0) {
223
+ return 0;
224
+ }
225
+ try {
226
+ const updateTime = syncTime || new Date();
227
+ (0, db_1.debugLogDbOperation)("update", "unipile_accounts", { lastSyncedAt: updateTime }, undefined, {
228
+ operation: "updateUnipileAccountSyncTime",
229
+ account_ids: accountIds,
230
+ count: accountIds.length,
231
+ });
232
+ // Create placeholders for the IN clause: $2, $3, $4, ...
233
+ const placeholders = accountIds.map((_, i) => `$${i + 2}`).join(', ');
234
+ const sql = `
235
+ UPDATE public.unipile_accounts
236
+ SET
237
+ last_synced_at = $1,
238
+ updated_at = NOW()
239
+ WHERE id IN (${placeholders})
240
+ RETURNING id
241
+ `;
242
+ const updatedAccounts = await (0, pg_client_1.query)(db, sql, [updateTime, ...accountIds]);
243
+ (0, db_1.debugLogDbOperation)("update", "unipile_accounts", { lastSyncedAt: updateTime }, updatedAccounts, {
244
+ operation: "updateUnipileAccountSyncTime",
245
+ account_ids: accountIds,
246
+ count: accountIds.length,
247
+ updated_count: updatedAccounts.length,
248
+ });
249
+ return updatedAccounts.length;
250
+ }
251
+ catch (error) {
252
+ throw new Error(`Failed to batch update sync time: ${error instanceof Error ? error.message : "Unknown error"}`);
253
+ }
254
+ }
255
+ //# sourceMappingURL=unipile-account-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unipile-account-operations.js","sourceRoot":"","sources":["../../src/utils/unipile-account-operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * =============================================================================
3
+ * USER INDUSTRY OPERATIONS
4
+ * =============================================================================
5
+ * Helper functions for managing user-industry assignments
6
+ */
7
+ import { Pool, PoolClient } from 'pg';
8
+ import type { Database } from "../lib/db";
9
+ /**
10
+ * Get all industries for a user
11
+ * @param db - Database connection
12
+ * @param userId - User ID
13
+ * @returns Array of industry names (lowercase)
14
+ */
15
+ export declare function getUserIndustries(db: Database | Pool | PoolClient, userId: number): Promise<string[]>;
16
+ /**
17
+ * Get industries for multiple users (optimized batch query)
18
+ * @param db - Database connection
19
+ * @param userIds - Array of user IDs
20
+ * @returns Map of userId -> industry names array
21
+ */
22
+ export declare function getBatchUserIndustries(db: Database | Pool | PoolClient, userIds: number[]): Promise<Map<number, string[]>>;
23
+ /**
24
+ * Find or create an industry by name (always lowercase)
25
+ * @param db - Database connection
26
+ * @param industryName - Industry name (will be converted to lowercase)
27
+ * @returns Industry ID
28
+ */
29
+ export declare function findOrCreateIndustry(db: Database | Pool | PoolClient, industryName: string): Promise<number>;
30
+ /**
31
+ * Assign industries to a user (replaces existing assignments)
32
+ * @param db - Database connection
33
+ * @param userId - User ID
34
+ * @param industryNames - Array of industry names
35
+ */
36
+ export declare function setUserIndustries(db: Database | Pool | PoolClient, userId: number, industryNames: string[]): Promise<void>;
37
+ /**
38
+ * Add industries to a user (keeps existing assignments)
39
+ * @param db - Database connection
40
+ * @param userId - User ID
41
+ * @param industryNames - Array of industry names to add
42
+ */
43
+ export declare function addUserIndustries(db: Database | Pool | PoolClient, userId: number, industryNames: string[]): Promise<void>;
44
+ /**
45
+ * Remove specific industries from a user
46
+ * @param db - Database connection
47
+ * @param userId - User ID
48
+ * @param industryNames - Array of industry names to remove
49
+ */
50
+ export declare function removeUserIndustries(db: Database | Pool | PoolClient, userId: number, industryNames: string[]): Promise<void>;
51
+ /**
52
+ * Remove all industries from a user
53
+ * @param db - Database connection
54
+ * @param userId - User ID
55
+ */
56
+ export declare function clearUserIndustries(db: Database | Pool | PoolClient, userId: number): Promise<void>;
57
+ /**
58
+ * Check if a user has a specific industry
59
+ * @param db - Database connection
60
+ * @param userId - User ID
61
+ * @param industryName - Industry name to check
62
+ * @returns True if user has the industry
63
+ */
64
+ export declare function userHasIndustry(db: Database | Pool | PoolClient, userId: number, industryName: string): Promise<boolean>;
65
+ /**
66
+ * Get all unique industries in the system
67
+ * @param db - Database connection
68
+ * @param limit - Optional limit (default: 1000)
69
+ * @returns Array of industry names
70
+ */
71
+ export declare function getAllIndustries(db: Database | Pool | PoolClient, limit?: number): Promise<string[]>;
72
+ /**
73
+ * Search industries by partial name match
74
+ * @param db - Database connection
75
+ * @param searchTerm - Search term (case-insensitive)
76
+ * @param limit - Optional limit (default: 20)
77
+ * @returns Array of matching industry names
78
+ */
79
+ export declare function searchIndustries(db: Database | Pool | PoolClient, searchTerm: string, limit?: number): Promise<string[]>;
80
+ //# sourceMappingURL=user-industry-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-industry-operations.d.ts","sourceRoot":"","sources":["../../src/utils/user-industry-operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAU3G;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAmChC;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoClH;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzG;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAAE,KAAK,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUhH;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB"}
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ /**
3
+ * =============================================================================
4
+ * USER INDUSTRY OPERATIONS
5
+ * =============================================================================
6
+ * Helper functions for managing user-industry assignments
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.getUserIndustries = getUserIndustries;
10
+ exports.getBatchUserIndustries = getBatchUserIndustries;
11
+ exports.findOrCreateIndustry = findOrCreateIndustry;
12
+ exports.setUserIndustries = setUserIndustries;
13
+ exports.addUserIndustries = addUserIndustries;
14
+ exports.removeUserIndustries = removeUserIndustries;
15
+ exports.clearUserIndustries = clearUserIndustries;
16
+ exports.userHasIndustry = userHasIndustry;
17
+ exports.getAllIndustries = getAllIndustries;
18
+ exports.searchIndustries = searchIndustries;
19
+ const pg_client_1 = require("../lib/pg-client");
20
+ /**
21
+ * Get all industries for a user
22
+ * @param db - Database connection
23
+ * @param userId - User ID
24
+ * @returns Array of industry names (lowercase)
25
+ */
26
+ async function getUserIndustries(db, userId) {
27
+ const sql = `
28
+ SELECT i.name
29
+ FROM public.user_industry_assignments uia
30
+ INNER JOIN public.industries i ON uia.industry_id = i.id
31
+ WHERE uia.user_id = $1
32
+ `;
33
+ const results = await (0, pg_client_1.query)(db, sql, [userId]);
34
+ return results.map(r => r.name);
35
+ }
36
+ /**
37
+ * Get industries for multiple users (optimized batch query)
38
+ * @param db - Database connection
39
+ * @param userIds - Array of user IDs
40
+ * @returns Map of userId -> industry names array
41
+ */
42
+ async function getBatchUserIndustries(db, userIds) {
43
+ if (userIds.length === 0) {
44
+ return new Map();
45
+ }
46
+ const placeholders = userIds.map((_, i) => `$${i + 1}`).join(', ');
47
+ const sql = `
48
+ SELECT uia.user_id, i.name as industry_name
49
+ FROM public.user_industry_assignments uia
50
+ INNER JOIN public.industries i ON uia.industry_id = i.id
51
+ WHERE uia.user_id IN (${placeholders})
52
+ `;
53
+ const results = await (0, pg_client_1.query)(db, sql, userIds);
54
+ // Group by user ID
55
+ const industryMap = new Map();
56
+ for (const result of results) {
57
+ const existing = industryMap.get(result.user_id) || [];
58
+ existing.push(result.industry_name);
59
+ industryMap.set(result.user_id, existing);
60
+ }
61
+ // Ensure all users have an entry (even if empty array)
62
+ for (const userId of userIds) {
63
+ if (!industryMap.has(userId)) {
64
+ industryMap.set(userId, []);
65
+ }
66
+ }
67
+ return industryMap;
68
+ }
69
+ /**
70
+ * Find or create an industry by name (always lowercase)
71
+ * @param db - Database connection
72
+ * @param industryName - Industry name (will be converted to lowercase)
73
+ * @returns Industry ID
74
+ */
75
+ async function findOrCreateIndustry(db, industryName) {
76
+ const normalizedName = industryName.trim().toLowerCase();
77
+ if (!normalizedName) {
78
+ throw new Error("Industry name cannot be empty");
79
+ }
80
+ // Try to find existing
81
+ const existingSql = `SELECT id FROM public.industries WHERE name = $1 LIMIT 1`;
82
+ const existing = await (0, pg_client_1.queryOne)(db, existingSql, [normalizedName]);
83
+ if (existing) {
84
+ return existing.id;
85
+ }
86
+ // Create new with ON CONFLICT DO NOTHING
87
+ const insertSql = `
88
+ INSERT INTO public.industries (name, created_at)
89
+ VALUES ($1, NOW())
90
+ ON CONFLICT (name) DO NOTHING
91
+ RETURNING id
92
+ `;
93
+ const newIndustry = await (0, pg_client_1.queryOne)(db, insertSql, [normalizedName]);
94
+ if (newIndustry) {
95
+ return newIndustry.id;
96
+ }
97
+ // If conflict happened, fetch again
98
+ const retryExisting = await (0, pg_client_1.queryOne)(db, existingSql, [normalizedName]);
99
+ if (!retryExisting) {
100
+ throw new Error(`Failed to find or create industry: ${normalizedName}`);
101
+ }
102
+ return retryExisting.id;
103
+ }
104
+ /**
105
+ * Assign industries to a user (replaces existing assignments)
106
+ * @param db - Database connection
107
+ * @param userId - User ID
108
+ * @param industryNames - Array of industry names
109
+ */
110
+ async function setUserIndustries(db, userId, industryNames) {
111
+ // Remove existing assignments
112
+ const deleteSql = `DELETE FROM public.user_industry_assignments WHERE user_id = $1`;
113
+ await (0, pg_client_1.execute)(db, deleteSql, [userId]);
114
+ // Add new assignments
115
+ if (industryNames.length > 0) {
116
+ await addUserIndustries(db, userId, industryNames);
117
+ }
118
+ }
119
+ /**
120
+ * Add industries to a user (keeps existing assignments)
121
+ * @param db - Database connection
122
+ * @param userId - User ID
123
+ * @param industryNames - Array of industry names to add
124
+ */
125
+ async function addUserIndustries(db, userId, industryNames) {
126
+ if (industryNames.length === 0) {
127
+ return;
128
+ }
129
+ // Find or create all industries
130
+ const industryIds = [];
131
+ for (const name of industryNames) {
132
+ const id = await findOrCreateIndustry(db, name);
133
+ industryIds.push(id);
134
+ }
135
+ // Create assignments (ignore conflicts if already assigned)
136
+ const values = industryIds.map((industryId, i) => `($1, $${i + 2})`).join(', ');
137
+ const sql = `
138
+ INSERT INTO public.user_industry_assignments (user_id, industry_id, created_at)
139
+ VALUES ${values}
140
+ ON CONFLICT (user_id, industry_id) DO NOTHING
141
+ `;
142
+ await (0, pg_client_1.execute)(db, sql, [userId, ...industryIds]);
143
+ }
144
+ /**
145
+ * Remove specific industries from a user
146
+ * @param db - Database connection
147
+ * @param userId - User ID
148
+ * @param industryNames - Array of industry names to remove
149
+ */
150
+ async function removeUserIndustries(db, userId, industryNames) {
151
+ if (industryNames.length === 0) {
152
+ return;
153
+ }
154
+ const normalizedNames = industryNames.map(n => n.trim().toLowerCase());
155
+ // Get industry IDs
156
+ const placeholders = normalizedNames.map((_, i) => `$${i + 1}`).join(', ');
157
+ const selectSql = `SELECT id FROM public.industries WHERE name IN (${placeholders})`;
158
+ const industryRecords = await (0, pg_client_1.query)(db, selectSql, normalizedNames);
159
+ if (industryRecords.length === 0) {
160
+ return; // No industries to remove
161
+ }
162
+ const industryIds = industryRecords.map(r => r.id);
163
+ // Delete assignments
164
+ const deletePlaceholders = industryIds.map((_, i) => `$${i + 2}`).join(', ');
165
+ const deleteSql = `
166
+ DELETE FROM public.user_industry_assignments
167
+ WHERE user_id = $1 AND industry_id IN (${deletePlaceholders})
168
+ `;
169
+ await (0, pg_client_1.execute)(db, deleteSql, [userId, ...industryIds]);
170
+ }
171
+ /**
172
+ * Remove all industries from a user
173
+ * @param db - Database connection
174
+ * @param userId - User ID
175
+ */
176
+ async function clearUserIndustries(db, userId) {
177
+ const sql = `DELETE FROM public.user_industry_assignments WHERE user_id = $1`;
178
+ await (0, pg_client_1.execute)(db, sql, [userId]);
179
+ }
180
+ /**
181
+ * Check if a user has a specific industry
182
+ * @param db - Database connection
183
+ * @param userId - User ID
184
+ * @param industryName - Industry name to check
185
+ * @returns True if user has the industry
186
+ */
187
+ async function userHasIndustry(db, userId, industryName) {
188
+ const normalizedName = industryName.trim().toLowerCase();
189
+ const sql = `
190
+ SELECT uia.id
191
+ FROM public.user_industry_assignments uia
192
+ INNER JOIN public.industries i ON uia.industry_id = i.id
193
+ WHERE uia.user_id = $1 AND i.name = $2
194
+ LIMIT 1
195
+ `;
196
+ const result = await (0, pg_client_1.queryOne)(db, sql, [userId, normalizedName]);
197
+ return result !== null;
198
+ }
199
+ /**
200
+ * Get all unique industries in the system
201
+ * @param db - Database connection
202
+ * @param limit - Optional limit (default: 1000)
203
+ * @returns Array of industry names
204
+ */
205
+ async function getAllIndustries(db, limit = 1000) {
206
+ const sql = `
207
+ SELECT name
208
+ FROM public.industries
209
+ ORDER BY name
210
+ LIMIT $1
211
+ `;
212
+ const results = await (0, pg_client_1.query)(db, sql, [limit]);
213
+ return results.map(r => r.name);
214
+ }
215
+ /**
216
+ * Search industries by partial name match
217
+ * @param db - Database connection
218
+ * @param searchTerm - Search term (case-insensitive)
219
+ * @param limit - Optional limit (default: 20)
220
+ * @returns Array of matching industry names
221
+ */
222
+ async function searchIndustries(db, searchTerm, limit = 20) {
223
+ const normalizedSearch = searchTerm.trim().toLowerCase();
224
+ if (!normalizedSearch) {
225
+ return [];
226
+ }
227
+ const sql = `
228
+ SELECT name
229
+ FROM public.industries
230
+ WHERE name ILIKE $1
231
+ ORDER BY name
232
+ LIMIT $2
233
+ `;
234
+ const results = await (0, pg_client_1.query)(db, sql, [`%${normalizedSearch}%`, limit]);
235
+ return results.map(r => r.name);
236
+ }
237
+ //# sourceMappingURL=user-industry-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-industry-operations.js","sourceRoot":"","sources":["../../src/utils/user-industry-operations.ts"],"names":[],"mappings":"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"}