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.
- package/CHANGELOG.md +750 -0
- package/README.md +660 -0
- package/dist/config/database.d.ts +28 -0
- package/dist/config/database.d.ts.map +1 -0
- package/dist/config/database.js +72 -0
- package/dist/config/database.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/database-service.d.ts +714 -0
- package/dist/lib/database-service.d.ts.map +1 -0
- package/dist/lib/database-service.js +1394 -0
- package/dist/lib/database-service.js.map +1 -0
- package/dist/lib/db-types.d.ts +167 -0
- package/dist/lib/db-types.d.ts.map +1 -0
- package/dist/lib/db-types.js +28 -0
- package/dist/lib/db-types.js.map +1 -0
- package/dist/lib/db.d.ts +58 -0
- package/dist/lib/db.d.ts.map +1 -0
- package/dist/lib/db.js +292 -0
- package/dist/lib/db.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +26 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/pg-client.d.ts +50 -0
- package/dist/lib/pg-client.d.ts.map +1 -0
- package/dist/lib/pg-client.js +106 -0
- package/dist/lib/pg-client.js.map +1 -0
- package/dist/lib/schema.d.ts +298 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +12 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/migration-manager.d.ts +49 -0
- package/dist/migration-manager.d.ts.map +1 -0
- package/dist/migration-manager.js +282 -0
- package/dist/migration-manager.js.map +1 -0
- package/dist/queries/minimal-connections.d.ts +31 -0
- package/dist/queries/minimal-connections.d.ts.map +1 -0
- package/dist/queries/minimal-connections.js +143 -0
- package/dist/queries/minimal-connections.js.map +1 -0
- package/dist/schema.ts +340 -0
- package/dist/seed.d.ts +8 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +40 -0
- package/dist/seed.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/types.d.ts +77 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +3 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/authenticated-user-operations.d.ts +110 -0
- package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
- package/dist/utils/authenticated-user-operations.js +292 -0
- package/dist/utils/authenticated-user-operations.js.map +1 -0
- package/dist/utils/authentication-operations.d.ts +48 -0
- package/dist/utils/authentication-operations.d.ts.map +1 -0
- package/dist/utils/authentication-operations.js +172 -0
- package/dist/utils/authentication-operations.js.map +1 -0
- package/dist/utils/company-mapping-job-operations.d.ts +103 -0
- package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/company-mapping-job-operations.js +413 -0
- package/dist/utils/company-mapping-job-operations.js.map +1 -0
- package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
- package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
- package/dist/utils/company-sheet-upload-operations.js +135 -0
- package/dist/utils/company-sheet-upload-operations.js.map +1 -0
- package/dist/utils/contact-operations.d.ts +70 -0
- package/dist/utils/contact-operations.d.ts.map +1 -0
- package/dist/utils/contact-operations.js +294 -0
- package/dist/utils/contact-operations.js.map +1 -0
- package/dist/utils/forager-linkedin-operations.d.ts +74 -0
- package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/forager-linkedin-operations.js +778 -0
- package/dist/utils/forager-linkedin-operations.js.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
- package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
- package/dist/utils/index.d.ts +29 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +77 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/introduction-request-operations.d.ts +160 -0
- package/dist/utils/introduction-request-operations.d.ts.map +1 -0
- package/dist/utils/introduction-request-operations.js +492 -0
- package/dist/utils/introduction-request-operations.js.map +1 -0
- package/dist/utils/invitation-operations.d.ts +141 -0
- package/dist/utils/invitation-operations.d.ts.map +1 -0
- package/dist/utils/invitation-operations.js +749 -0
- package/dist/utils/invitation-operations.js.map +1 -0
- package/dist/utils/linkedin-account-operations.d.ts +45 -0
- package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-operations.js +279 -0
- package/dist/utils/linkedin-account-operations.js.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.js +274 -0
- package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
- package/dist/utils/linkedin-data-operations.d.ts +102 -0
- package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-data-operations.js +613 -0
- package/dist/utils/linkedin-data-operations.js.map +1 -0
- package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
- package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
- package/dist/utils/linkedin-identifier-utils.js +63 -0
- package/dist/utils/linkedin-identifier-utils.js.map +1 -0
- package/dist/utils/linkedin-profile-cache.d.ts +131 -0
- package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
- package/dist/utils/linkedin-profile-cache.js +418 -0
- package/dist/utils/linkedin-profile-cache.js.map +1 -0
- package/dist/utils/llm-inference-job-operations.d.ts +116 -0
- package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
- package/dist/utils/llm-inference-job-operations.js +267 -0
- package/dist/utils/llm-inference-job-operations.js.map +1 -0
- package/dist/utils/mapping-job-operations.d.ts +272 -0
- package/dist/utils/mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/mapping-job-operations.js +833 -0
- package/dist/utils/mapping-job-operations.js.map +1 -0
- package/dist/utils/mapping-operations.d.ts +80 -0
- package/dist/utils/mapping-operations.d.ts.map +1 -0
- package/dist/utils/mapping-operations.js +318 -0
- package/dist/utils/mapping-operations.js.map +1 -0
- package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
- package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
- package/dist/utils/on-demand-mapping-operations.js +728 -0
- package/dist/utils/on-demand-mapping-operations.js.map +1 -0
- package/dist/utils/onboarding-operations.d.ts +53 -0
- package/dist/utils/onboarding-operations.d.ts.map +1 -0
- package/dist/utils/onboarding-operations.js +223 -0
- package/dist/utils/onboarding-operations.js.map +1 -0
- package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
- package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-job-operations.js +881 -0
- package/dist/utils/organization-assignment-job-operations.js.map +1 -0
- package/dist/utils/organization-assignment-operations.d.ts +59 -0
- package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-operations.js +130 -0
- package/dist/utils/organization-assignment-operations.js.map +1 -0
- package/dist/utils/organization-operations.d.ts +284 -0
- package/dist/utils/organization-operations.d.ts.map +1 -0
- package/dist/utils/organization-operations.js +1030 -0
- package/dist/utils/organization-operations.js.map +1 -0
- package/dist/utils/organization-relationship-operations.d.ts +79 -0
- package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
- package/dist/utils/organization-relationship-operations.js +294 -0
- package/dist/utils/organization-relationship-operations.js.map +1 -0
- package/dist/utils/quota-operations.d.ts +107 -0
- package/dist/utils/quota-operations.d.ts.map +1 -0
- package/dist/utils/quota-operations.js +692 -0
- package/dist/utils/quota-operations.js.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.js +169 -0
- package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
- package/dist/utils/relationship-operations.d.ts +130 -0
- package/dist/utils/relationship-operations.d.ts.map +1 -0
- package/dist/utils/relationship-operations.js +329 -0
- package/dist/utils/relationship-operations.js.map +1 -0
- package/dist/utils/sales-pipeline-operations.d.ts +163 -0
- package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
- package/dist/utils/sales-pipeline-operations.js +725 -0
- package/dist/utils/sales-pipeline-operations.js.map +1 -0
- package/dist/utils/skills-operations.d.ts +117 -0
- package/dist/utils/skills-operations.d.ts.map +1 -0
- package/dist/utils/skills-operations.js +487 -0
- package/dist/utils/skills-operations.js.map +1 -0
- package/dist/utils/subscription-operations.d.ts +123 -0
- package/dist/utils/subscription-operations.d.ts.map +1 -0
- package/dist/utils/subscription-operations.js +391 -0
- package/dist/utils/subscription-operations.js.map +1 -0
- package/dist/utils/unipile-account-operations.d.ts +96 -0
- package/dist/utils/unipile-account-operations.d.ts.map +1 -0
- package/dist/utils/unipile-account-operations.js +255 -0
- package/dist/utils/unipile-account-operations.js.map +1 -0
- package/dist/utils/user-industry-operations.d.ts +80 -0
- package/dist/utils/user-industry-operations.d.ts.map +1 -0
- package/dist/utils/user-industry-operations.js +237 -0
- package/dist/utils/user-industry-operations.js.map +1 -0
- package/dist/utils/user-operations.d.ts +87 -0
- package/dist/utils/user-operations.d.ts.map +1 -0
- package/dist/utils/user-operations.js +212 -0
- package/dist/utils/user-operations.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* =============================================================================
|
|
4
|
+
* INTRODUCTION REQUEST OPERATIONS
|
|
5
|
+
* =============================================================================
|
|
6
|
+
*
|
|
7
|
+
* Database operations for managing introduction requests between users
|
|
8
|
+
*
|
|
9
|
+
* @author Eggi.ai Team
|
|
10
|
+
* @version 1.0.0 - Initial implementation
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.createIntroductionRequest = createIntroductionRequest;
|
|
14
|
+
exports.getIntroductionRequestsByUser = getIntroductionRequestsByUser;
|
|
15
|
+
exports.getIntroductionRequestById = getIntroductionRequestById;
|
|
16
|
+
exports.hasExistingIntroductionRequest = hasExistingIntroductionRequest;
|
|
17
|
+
exports.updateIntroductionRequestStatus = updateIntroductionRequestStatus;
|
|
18
|
+
exports.markIntroductionRequestAsSeen = markIntroductionRequestAsSeen;
|
|
19
|
+
exports.getReceivedIntroductionRequests = getReceivedIntroductionRequests;
|
|
20
|
+
exports.getSentIntroductionRequests = getSentIntroductionRequests;
|
|
21
|
+
exports.markReceivedIntroductionRequestsAsSeen = markReceivedIntroductionRequestsAsSeen;
|
|
22
|
+
const pg_client_1 = require("../lib/pg-client");
|
|
23
|
+
/**
|
|
24
|
+
* Create a new introduction request
|
|
25
|
+
*
|
|
26
|
+
* @param db - Database instance
|
|
27
|
+
* @param params - Introduction request parameters
|
|
28
|
+
* @returns Created introduction request
|
|
29
|
+
* @throws Error if relationship ID or requester user ID doesn't exist
|
|
30
|
+
* @throws Error if unique constraint is violated (duplicate request)
|
|
31
|
+
*/
|
|
32
|
+
async function createIntroductionRequest(db, params) {
|
|
33
|
+
try {
|
|
34
|
+
const sql = `
|
|
35
|
+
INSERT INTO public.introduction_requests (by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at)
|
|
36
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
|
|
37
|
+
RETURNING id, by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at
|
|
38
|
+
`;
|
|
39
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [
|
|
40
|
+
params.byUserId,
|
|
41
|
+
params.toUserId,
|
|
42
|
+
params.toRelationshipId,
|
|
43
|
+
params.contactInfoId || null,
|
|
44
|
+
params.message || null,
|
|
45
|
+
params.status || "pending",
|
|
46
|
+
false,
|
|
47
|
+
]);
|
|
48
|
+
if (!result) {
|
|
49
|
+
throw new Error("Failed to create introduction request");
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
id: result.id,
|
|
53
|
+
createdAt: result.created_at,
|
|
54
|
+
byUserId: result.by_user_id,
|
|
55
|
+
toRelationshipId: result.to_relationship_id,
|
|
56
|
+
contactInfoId: result.contact_info_id,
|
|
57
|
+
message: result.message,
|
|
58
|
+
status: result.status,
|
|
59
|
+
wasSeenByReceiver: result.was_seen_by_receiver,
|
|
60
|
+
toUserId: result.to_user_id,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// Handle unique constraint violation
|
|
65
|
+
if (error.code === "23505") {
|
|
66
|
+
throw new Error("An introduction request for this relationship already exists");
|
|
67
|
+
}
|
|
68
|
+
// Handle foreign key violation
|
|
69
|
+
if (error.code === "23503") {
|
|
70
|
+
throw new Error("Invalid user ID or relationship ID - referenced record not found");
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get introduction requests sent by a user
|
|
77
|
+
*
|
|
78
|
+
* @param db - Database instance
|
|
79
|
+
* @param userId - User ID who sent the requests
|
|
80
|
+
* @param limit - Maximum number of requests to return (default: 50)
|
|
81
|
+
* @returns Array of introduction requests
|
|
82
|
+
*/
|
|
83
|
+
async function getIntroductionRequestsByUser(db, userId, limit = 50) {
|
|
84
|
+
const sql = `
|
|
85
|
+
SELECT id, by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at
|
|
86
|
+
FROM public.introduction_requests
|
|
87
|
+
WHERE by_user_id = $1
|
|
88
|
+
ORDER BY created_at DESC
|
|
89
|
+
LIMIT $2
|
|
90
|
+
`;
|
|
91
|
+
const results = await (0, pg_client_1.query)(db, sql, [userId, limit]);
|
|
92
|
+
return results.map(r => ({
|
|
93
|
+
id: r.id,
|
|
94
|
+
createdAt: r.created_at,
|
|
95
|
+
byUserId: r.by_user_id,
|
|
96
|
+
toRelationshipId: r.to_relationship_id,
|
|
97
|
+
contactInfoId: r.contact_info_id,
|
|
98
|
+
message: r.message,
|
|
99
|
+
status: r.status,
|
|
100
|
+
wasSeenByReceiver: r.was_seen_by_receiver,
|
|
101
|
+
toUserId: r.to_user_id,
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get a specific introduction request by ID
|
|
106
|
+
*
|
|
107
|
+
* @param db - Database instance
|
|
108
|
+
* @param requestId - Introduction request ID
|
|
109
|
+
* @returns Introduction request or null if not found
|
|
110
|
+
*/
|
|
111
|
+
async function getIntroductionRequestById(db, requestId) {
|
|
112
|
+
const sql = `
|
|
113
|
+
SELECT id, by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at
|
|
114
|
+
FROM public.introduction_requests
|
|
115
|
+
WHERE id = $1
|
|
116
|
+
LIMIT 1
|
|
117
|
+
`;
|
|
118
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [requestId]);
|
|
119
|
+
if (!result)
|
|
120
|
+
return null;
|
|
121
|
+
return {
|
|
122
|
+
id: result.id,
|
|
123
|
+
createdAt: result.created_at,
|
|
124
|
+
byUserId: result.by_user_id,
|
|
125
|
+
toRelationshipId: result.to_relationship_id,
|
|
126
|
+
contactInfoId: result.contact_info_id,
|
|
127
|
+
message: result.message,
|
|
128
|
+
status: result.status,
|
|
129
|
+
wasSeenByReceiver: result.was_seen_by_receiver,
|
|
130
|
+
toUserId: result.to_user_id,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if an introduction request already exists for a relationship
|
|
135
|
+
*
|
|
136
|
+
* @param db - Database instance
|
|
137
|
+
* @param byUserId - User ID making the request
|
|
138
|
+
* @param toRelationshipId - Relationship ID
|
|
139
|
+
* @returns True if request exists, false otherwise
|
|
140
|
+
*/
|
|
141
|
+
async function hasExistingIntroductionRequest(db, byUserId, toRelationshipId) {
|
|
142
|
+
const sql = `
|
|
143
|
+
SELECT id
|
|
144
|
+
FROM public.introduction_requests
|
|
145
|
+
WHERE by_user_id = $1 AND to_relationship_id = $2
|
|
146
|
+
LIMIT 1
|
|
147
|
+
`;
|
|
148
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [
|
|
149
|
+
byUserId,
|
|
150
|
+
toRelationshipId,
|
|
151
|
+
]);
|
|
152
|
+
return !!result;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Update introduction request status
|
|
156
|
+
*
|
|
157
|
+
* @param db - Database instance
|
|
158
|
+
* @param requestId - Introduction request ID
|
|
159
|
+
* @param status - New status
|
|
160
|
+
* @returns Updated introduction request
|
|
161
|
+
*/
|
|
162
|
+
async function updateIntroductionRequestStatus(db, requestId, status) {
|
|
163
|
+
const sql = `
|
|
164
|
+
UPDATE public.introduction_requests
|
|
165
|
+
SET status = $1
|
|
166
|
+
WHERE id = $2
|
|
167
|
+
RETURNING id, by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at
|
|
168
|
+
`;
|
|
169
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [status, requestId]);
|
|
170
|
+
if (!result) {
|
|
171
|
+
throw new Error(`Introduction request ${requestId} not found`);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
id: result.id,
|
|
175
|
+
createdAt: result.created_at,
|
|
176
|
+
byUserId: result.by_user_id,
|
|
177
|
+
toRelationshipId: result.to_relationship_id,
|
|
178
|
+
contactInfoId: result.contact_info_id,
|
|
179
|
+
message: result.message,
|
|
180
|
+
status: result.status,
|
|
181
|
+
wasSeenByReceiver: result.was_seen_by_receiver,
|
|
182
|
+
toUserId: result.to_user_id,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Mark introduction request as seen
|
|
187
|
+
*
|
|
188
|
+
* @param db - Database instance
|
|
189
|
+
* @param requestId - Introduction request ID
|
|
190
|
+
* @returns Updated introduction request
|
|
191
|
+
*/
|
|
192
|
+
async function markIntroductionRequestAsSeen(db, requestId) {
|
|
193
|
+
const sql = `
|
|
194
|
+
UPDATE public.introduction_requests
|
|
195
|
+
SET was_seen_by_receiver = true
|
|
196
|
+
WHERE id = $1
|
|
197
|
+
RETURNING id, by_user_id, to_user_id, to_relationship_id, contact_info_id, message, status, was_seen_by_receiver, created_at
|
|
198
|
+
`;
|
|
199
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [requestId]);
|
|
200
|
+
if (!result) {
|
|
201
|
+
throw new Error(`Introduction request ${requestId} not found`);
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
id: result.id,
|
|
205
|
+
createdAt: result.created_at,
|
|
206
|
+
byUserId: result.by_user_id,
|
|
207
|
+
toRelationshipId: result.to_relationship_id,
|
|
208
|
+
contactInfoId: result.contact_info_id,
|
|
209
|
+
message: result.message,
|
|
210
|
+
status: result.status,
|
|
211
|
+
wasSeenByReceiver: result.was_seen_by_receiver,
|
|
212
|
+
toUserId: result.to_user_id,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get introduction requests received by a user (where user is the contributor)
|
|
217
|
+
* Filtered by organization - only returns requests for relationships assigned to the organization
|
|
218
|
+
*
|
|
219
|
+
* @param db - Database instance
|
|
220
|
+
* @param userId - User ID who is the contributor
|
|
221
|
+
* @param organizationId - Organization ID to filter by
|
|
222
|
+
* @returns Array of detailed introduction requests
|
|
223
|
+
*/
|
|
224
|
+
async function getReceivedIntroductionRequests(db, userId, organizationId) {
|
|
225
|
+
// First, get the user's LinkedIn account
|
|
226
|
+
const linkedinAccountSql = `SELECT id FROM linkedin.accounts WHERE user_id = $1 LIMIT 1`;
|
|
227
|
+
const userLinkedInAccount = await (0, pg_client_1.queryOne)(db, linkedinAccountSql, [userId]);
|
|
228
|
+
if (!userLinkedInAccount) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
// Query for introduction requests where user is the contributor
|
|
232
|
+
// Filter by organization through organization_user_relationships_assignments
|
|
233
|
+
const sql = `
|
|
234
|
+
SELECT
|
|
235
|
+
ir.id,
|
|
236
|
+
ir.created_at,
|
|
237
|
+
ir.to_relationship_id,
|
|
238
|
+
oura.id as organization_user_relationship_assignment_id,
|
|
239
|
+
ir.message,
|
|
240
|
+
ir.status,
|
|
241
|
+
ir.was_seen_by_receiver,
|
|
242
|
+
requester_user.id as requester_id,
|
|
243
|
+
requester_user.given_name as requester_given_name,
|
|
244
|
+
requester_user.family_name as requester_family_name,
|
|
245
|
+
COALESCE(requester_account.profile_image_cloudfront_url, requester_account.profile_picture_url) as requester_profile_picture_url,
|
|
246
|
+
target_user.id as target_id,
|
|
247
|
+
target_user.given_name as target_given_name,
|
|
248
|
+
target_user.family_name as target_family_name,
|
|
249
|
+
target_account.headline as target_headline,
|
|
250
|
+
COALESCE(target_account.profile_image_cloudfront_url, target_account.profile_picture_url) as target_profile_picture_url,
|
|
251
|
+
target_account.id as target_account_id
|
|
252
|
+
FROM public.introduction_requests ir
|
|
253
|
+
INNER JOIN linkedin.relationships lr ON ir.to_relationship_id = lr.id
|
|
254
|
+
INNER JOIN public.organization_user_relationships_assignments oura
|
|
255
|
+
ON oura.linkedin_relationship_id = lr.id AND oura.organization_id = $3
|
|
256
|
+
INNER JOIN public.users target_user ON ir.to_user_id = target_user.id
|
|
257
|
+
LEFT JOIN linkedin.accounts target_account ON target_user.id = target_account.user_id
|
|
258
|
+
INNER JOIN public.users requester_user ON ir.by_user_id = requester_user.id
|
|
259
|
+
LEFT JOIN linkedin.accounts requester_account ON requester_user.id = requester_account.user_id
|
|
260
|
+
WHERE (
|
|
261
|
+
lr.linkedin_account_id_a = $1 OR lr.linkedin_account_id_b = $1
|
|
262
|
+
)
|
|
263
|
+
AND ir.by_user_id != $2
|
|
264
|
+
ORDER BY ir.created_at DESC
|
|
265
|
+
`;
|
|
266
|
+
const results = await (0, pg_client_1.query)(db, sql, [userLinkedInAccount.id, userId, organizationId]);
|
|
267
|
+
// Fetch work experience for each target separately
|
|
268
|
+
const enrichedResults = await Promise.all(results.map(async (row) => {
|
|
269
|
+
let currentPosition = null;
|
|
270
|
+
let currentCompany = null;
|
|
271
|
+
if (row.target_account_id) {
|
|
272
|
+
const workExpSql = `
|
|
273
|
+
SELECT position, company
|
|
274
|
+
FROM linkedin.work_experience
|
|
275
|
+
WHERE linkedin_account_id = $1
|
|
276
|
+
ORDER BY
|
|
277
|
+
CASE WHEN end_date IS NULL THEN 0 ELSE 1 END,
|
|
278
|
+
start_date DESC
|
|
279
|
+
LIMIT 1
|
|
280
|
+
`;
|
|
281
|
+
const workExp = await (0, pg_client_1.queryOne)(db, workExpSql, [row.target_account_id]);
|
|
282
|
+
if (workExp) {
|
|
283
|
+
currentPosition = workExp.position;
|
|
284
|
+
currentCompany = workExp.company;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
id: row.id,
|
|
289
|
+
createdAt: row.created_at,
|
|
290
|
+
toRelationshipId: row.to_relationship_id,
|
|
291
|
+
organizationUserRelationshipAssignmentId: row.organization_user_relationship_assignment_id,
|
|
292
|
+
message: row.message,
|
|
293
|
+
status: row.status,
|
|
294
|
+
wasSeenByReceiver: row.was_seen_by_receiver,
|
|
295
|
+
requester: {
|
|
296
|
+
id: row.requester_id,
|
|
297
|
+
givenName: row.requester_given_name,
|
|
298
|
+
familyName: row.requester_family_name,
|
|
299
|
+
profilePictureUrl: row.requester_profile_picture_url,
|
|
300
|
+
},
|
|
301
|
+
target: {
|
|
302
|
+
id: row.target_id,
|
|
303
|
+
givenName: row.target_given_name,
|
|
304
|
+
familyName: row.target_family_name,
|
|
305
|
+
headline: row.target_headline,
|
|
306
|
+
currentPosition,
|
|
307
|
+
currentCompany,
|
|
308
|
+
profilePictureUrl: row.target_profile_picture_url,
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
}));
|
|
312
|
+
return enrichedResults;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get introduction requests sent by a user (where user is the requester)
|
|
316
|
+
* Filtered by organization - only returns requests for relationships assigned to the organization
|
|
317
|
+
*
|
|
318
|
+
* @param db - Database instance
|
|
319
|
+
* @param userId - User ID who sent the requests
|
|
320
|
+
* @param organizationId - Organization ID to filter by
|
|
321
|
+
* @returns Array of detailed introduction requests with contributor info
|
|
322
|
+
*/
|
|
323
|
+
async function getSentIntroductionRequests(db, userId, organizationId) {
|
|
324
|
+
const sql = `
|
|
325
|
+
SELECT
|
|
326
|
+
ir.id,
|
|
327
|
+
ir.created_at,
|
|
328
|
+
ir.to_relationship_id,
|
|
329
|
+
oura.id as organization_user_relationship_assignment_id,
|
|
330
|
+
ir.message,
|
|
331
|
+
ir.status,
|
|
332
|
+
ir.was_seen_by_receiver,
|
|
333
|
+
requester_user.id as requester_id,
|
|
334
|
+
requester_user.given_name as requester_given_name,
|
|
335
|
+
requester_user.family_name as requester_family_name,
|
|
336
|
+
COALESCE(requester_account.profile_image_cloudfront_url, requester_account.profile_picture_url) as requester_profile_picture_url,
|
|
337
|
+
target_user.id as target_id,
|
|
338
|
+
target_user.given_name as target_given_name,
|
|
339
|
+
target_user.family_name as target_family_name,
|
|
340
|
+
target_account.headline as target_headline,
|
|
341
|
+
COALESCE(target_account.profile_image_cloudfront_url, target_account.profile_picture_url) as target_profile_picture_url,
|
|
342
|
+
target_account.id as target_account_id,
|
|
343
|
+
account_a.id as account_a_id,
|
|
344
|
+
account_a.user_id as account_a_user_id,
|
|
345
|
+
account_b.id as account_b_id,
|
|
346
|
+
account_b.user_id as account_b_user_id
|
|
347
|
+
FROM public.introduction_requests ir
|
|
348
|
+
INNER JOIN linkedin.relationships lr ON ir.to_relationship_id = lr.id
|
|
349
|
+
INNER JOIN public.organization_user_relationships_assignments oura
|
|
350
|
+
ON oura.linkedin_relationship_id = lr.id AND oura.organization_id = $2
|
|
351
|
+
INNER JOIN public.users requester_user ON ir.by_user_id = requester_user.id
|
|
352
|
+
LEFT JOIN linkedin.accounts requester_account ON requester_user.id = requester_account.user_id
|
|
353
|
+
INNER JOIN public.users target_user ON ir.to_user_id = target_user.id
|
|
354
|
+
LEFT JOIN linkedin.accounts target_account ON target_user.id = target_account.user_id
|
|
355
|
+
INNER JOIN linkedin.accounts account_a ON lr.linkedin_account_id_a = account_a.id
|
|
356
|
+
INNER JOIN linkedin.accounts account_b ON lr.linkedin_account_id_b = account_b.id
|
|
357
|
+
WHERE ir.by_user_id = $1
|
|
358
|
+
ORDER BY ir.created_at DESC
|
|
359
|
+
`;
|
|
360
|
+
const results = await (0, pg_client_1.query)(db, sql, [userId, organizationId]);
|
|
361
|
+
// Enrich results with contributor and work experience
|
|
362
|
+
const enrichedResults = await Promise.all(results.map(async (row) => {
|
|
363
|
+
// Determine contributor ID (the person in the relationship who is NOT the target)
|
|
364
|
+
let contributorUserId = null;
|
|
365
|
+
if (row.target_account_id === row.account_a_id) {
|
|
366
|
+
contributorUserId = row.account_b_user_id;
|
|
367
|
+
}
|
|
368
|
+
else if (row.target_account_id === row.account_b_id) {
|
|
369
|
+
contributorUserId = row.account_a_user_id;
|
|
370
|
+
}
|
|
371
|
+
// Fetch contributor user info
|
|
372
|
+
let contributor = null;
|
|
373
|
+
if (contributorUserId) {
|
|
374
|
+
const contributorSql = `
|
|
375
|
+
SELECT
|
|
376
|
+
u.id,
|
|
377
|
+
u.given_name,
|
|
378
|
+
u.family_name,
|
|
379
|
+
COALESCE(la.profile_image_cloudfront_url, la.profile_picture_url) as profile_picture_url
|
|
380
|
+
FROM public.users u
|
|
381
|
+
LEFT JOIN linkedin.accounts la ON u.id = la.user_id
|
|
382
|
+
WHERE u.id = $1
|
|
383
|
+
LIMIT 1
|
|
384
|
+
`;
|
|
385
|
+
const contributorData = await (0, pg_client_1.queryOne)(db, contributorSql, [contributorUserId]);
|
|
386
|
+
if (contributorData) {
|
|
387
|
+
contributor = {
|
|
388
|
+
id: contributorData.id,
|
|
389
|
+
givenName: contributorData.given_name,
|
|
390
|
+
familyName: contributorData.family_name,
|
|
391
|
+
profilePictureUrl: contributorData.profile_picture_url,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Fetch target work experience
|
|
396
|
+
let currentPosition = null;
|
|
397
|
+
let currentCompany = null;
|
|
398
|
+
if (row.target_account_id) {
|
|
399
|
+
const workExpSql = `
|
|
400
|
+
SELECT position, company
|
|
401
|
+
FROM linkedin.work_experience
|
|
402
|
+
WHERE linkedin_account_id = $1
|
|
403
|
+
ORDER BY
|
|
404
|
+
CASE WHEN end_date IS NULL THEN 0 ELSE 1 END,
|
|
405
|
+
start_date DESC
|
|
406
|
+
LIMIT 1
|
|
407
|
+
`;
|
|
408
|
+
const workExp = await (0, pg_client_1.queryOne)(db, workExpSql, [row.target_account_id]);
|
|
409
|
+
if (workExp) {
|
|
410
|
+
currentPosition = workExp.position;
|
|
411
|
+
currentCompany = workExp.company;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
id: row.id,
|
|
416
|
+
createdAt: row.created_at,
|
|
417
|
+
toRelationshipId: row.to_relationship_id,
|
|
418
|
+
organizationUserRelationshipAssignmentId: row.organization_user_relationship_assignment_id,
|
|
419
|
+
message: row.message,
|
|
420
|
+
status: row.status,
|
|
421
|
+
wasSeenByReceiver: row.was_seen_by_receiver,
|
|
422
|
+
requester: {
|
|
423
|
+
id: row.requester_id,
|
|
424
|
+
givenName: row.requester_given_name,
|
|
425
|
+
familyName: row.requester_family_name,
|
|
426
|
+
profilePictureUrl: row.requester_profile_picture_url,
|
|
427
|
+
},
|
|
428
|
+
target: {
|
|
429
|
+
id: row.target_id,
|
|
430
|
+
givenName: row.target_given_name,
|
|
431
|
+
familyName: row.target_family_name,
|
|
432
|
+
headline: row.target_headline,
|
|
433
|
+
currentPosition,
|
|
434
|
+
currentCompany,
|
|
435
|
+
profilePictureUrl: row.target_profile_picture_url,
|
|
436
|
+
},
|
|
437
|
+
contributor,
|
|
438
|
+
};
|
|
439
|
+
}));
|
|
440
|
+
return enrichedResults;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Mark all received introduction requests as seen for a user
|
|
444
|
+
* Filtered by organization - only marks requests for relationships assigned to the organization
|
|
445
|
+
*
|
|
446
|
+
* Updates was_seen_by_receiver = true for all introduction requests where:
|
|
447
|
+
* - The user is the contributor (one of the two people in the relationship)
|
|
448
|
+
* - The user is NOT the requester
|
|
449
|
+
* - was_seen_by_receiver is currently false
|
|
450
|
+
* - The relationship is assigned to the specified organization
|
|
451
|
+
*
|
|
452
|
+
* @param db - Database instance
|
|
453
|
+
* @param userId - The user ID marking requests as seen
|
|
454
|
+
* @param organizationId - Organization ID to filter by
|
|
455
|
+
* @returns Number of requests marked as seen
|
|
456
|
+
*/
|
|
457
|
+
async function markReceivedIntroductionRequestsAsSeen(db, userId, organizationId) {
|
|
458
|
+
// First, get the user's LinkedIn account
|
|
459
|
+
const linkedinAccountSql = `SELECT id FROM linkedin.accounts WHERE user_id = $1 LIMIT 1`;
|
|
460
|
+
const userLinkedInAccount = await (0, pg_client_1.queryOne)(db, linkedinAccountSql, [userId]);
|
|
461
|
+
if (!userLinkedInAccount) {
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
464
|
+
// Update introduction requests - filter by organization through organization_user_relationships_assignments
|
|
465
|
+
const sql = `
|
|
466
|
+
UPDATE public.introduction_requests
|
|
467
|
+
SET was_seen_by_receiver = true
|
|
468
|
+
WHERE
|
|
469
|
+
EXISTS (
|
|
470
|
+
SELECT 1
|
|
471
|
+
FROM linkedin.relationships lr
|
|
472
|
+
INNER JOIN public.organization_user_relationships_assignments oura
|
|
473
|
+
ON oura.linkedin_relationship_id = lr.id AND oura.organization_id = $3
|
|
474
|
+
WHERE lr.id = introduction_requests.to_relationship_id
|
|
475
|
+
AND (
|
|
476
|
+
lr.linkedin_account_id_a = $1
|
|
477
|
+
OR lr.linkedin_account_id_b = $1
|
|
478
|
+
)
|
|
479
|
+
)
|
|
480
|
+
AND introduction_requests.by_user_id != $2
|
|
481
|
+
AND introduction_requests.was_seen_by_receiver = false
|
|
482
|
+
RETURNING id
|
|
483
|
+
`;
|
|
484
|
+
const result = await (0, pg_client_1.query)(db, sql, [
|
|
485
|
+
userLinkedInAccount.id,
|
|
486
|
+
userId,
|
|
487
|
+
organizationId,
|
|
488
|
+
]);
|
|
489
|
+
// Return the number of rows affected
|
|
490
|
+
return result.length;
|
|
491
|
+
}
|
|
492
|
+
//# sourceMappingURL=introduction-request-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introduction-request-operations.js","sourceRoot":"","sources":["../../src/utils/introduction-request-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* =============================================================================
|
|
3
|
+
* INVITATION OPERATIONS - Database Operations for User Invitations
|
|
4
|
+
* =============================================================================
|
|
5
|
+
* Helper functions for managing user invitations to organizations
|
|
6
|
+
*/
|
|
7
|
+
import { Pool, PoolClient } from 'pg';
|
|
8
|
+
type DbType = Pool | PoolClient | any;
|
|
9
|
+
export interface CreateInvitationInput {
|
|
10
|
+
email: string;
|
|
11
|
+
invitedByUserId: number;
|
|
12
|
+
shadowUserId: number;
|
|
13
|
+
organizationId: number;
|
|
14
|
+
invitationMessage?: string;
|
|
15
|
+
invitedUserPermissionsRole?: "ADMIN" | "REGULAR";
|
|
16
|
+
expiresInDays?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface InvitationDetails {
|
|
19
|
+
id: number;
|
|
20
|
+
email: string;
|
|
21
|
+
token: string;
|
|
22
|
+
invitationMessage: string | null;
|
|
23
|
+
invitedUserPermissionsRole: "ADMIN" | "REGULAR";
|
|
24
|
+
invitedByUserId: number;
|
|
25
|
+
shadowUserId: number;
|
|
26
|
+
organizationId: number;
|
|
27
|
+
createdAt: Date;
|
|
28
|
+
expiresAt: Date;
|
|
29
|
+
usedAt: Date | null;
|
|
30
|
+
revokedAt: Date | null;
|
|
31
|
+
}
|
|
32
|
+
export interface InvitationWithDetails extends InvitationDetails {
|
|
33
|
+
invitedByUser: {
|
|
34
|
+
id: number;
|
|
35
|
+
givenName: string | null;
|
|
36
|
+
familyName: string | null;
|
|
37
|
+
};
|
|
38
|
+
shadowUser: {
|
|
39
|
+
id: number;
|
|
40
|
+
givenName: string | null;
|
|
41
|
+
familyName: string | null;
|
|
42
|
+
profilePictureUrl: string | null;
|
|
43
|
+
};
|
|
44
|
+
organization: {
|
|
45
|
+
id: number;
|
|
46
|
+
name: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface ValidateTokenResult {
|
|
50
|
+
valid: boolean;
|
|
51
|
+
invitation?: InvitationWithDetails;
|
|
52
|
+
reason?: "not_found" | "expired" | "already_used" | "revoked";
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Comprehensive validation for invitation eligibility
|
|
56
|
+
* Checks all three scenarios:
|
|
57
|
+
* a) No active invitation exists for this email
|
|
58
|
+
* b) Email is not already used by an authenticated user
|
|
59
|
+
* c) Email is not reserved by contact_info
|
|
60
|
+
*/
|
|
61
|
+
export declare function validateInvitationEligibility(db: DbType, email: string): Promise<{
|
|
62
|
+
eligible: boolean;
|
|
63
|
+
reason?: "active_invitation" | "email_registered" | "email_reserved";
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Returns true if there is a still-active (pending) invitation for this email anywhere
|
|
67
|
+
* Active means: not used, not revoked, and not expired
|
|
68
|
+
*/
|
|
69
|
+
export declare function hasActiveInvitationByEmail(db: DbType, email: string): Promise<boolean>;
|
|
70
|
+
/**
|
|
71
|
+
* Returns true if there is a still-active (pending) invitation for this email in the given organization
|
|
72
|
+
*/
|
|
73
|
+
export declare function hasActiveInvitationByEmailForOrg(db: DbType, email: string, organizationId: number): Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Email is already used by an authenticated user if there exists authentication.users → contact_infos value match (case-insensitive)
|
|
76
|
+
*/
|
|
77
|
+
export declare function isEmailUsedByAuthenticatedUser(db: DbType, email: string): Promise<boolean>;
|
|
78
|
+
/**
|
|
79
|
+
* Returns true if any contact_info indicates the email is reserved/owned and should not be invited again.
|
|
80
|
+
* Criteria: ci.type = 'EMAIL' OR ci.source IN ('MANUAL', 'INVITATION') for the same email value.
|
|
81
|
+
*/
|
|
82
|
+
export declare function isEmailReservedByContactInfo(db: DbType, email: string): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Generate a cryptographically secure invitation token
|
|
85
|
+
* @returns 32-character hex string
|
|
86
|
+
*/
|
|
87
|
+
export declare function generateInvitationToken(): string;
|
|
88
|
+
/**
|
|
89
|
+
* Create a new invitation
|
|
90
|
+
*/
|
|
91
|
+
export declare function createInvitation(db: DbType, input: CreateInvitationInput): Promise<InvitationDetails>;
|
|
92
|
+
/**
|
|
93
|
+
* Validate an invitation token and return invitation details
|
|
94
|
+
*/
|
|
95
|
+
export declare function validateInvitationToken(db: DbType, token: string): Promise<ValidateTokenResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Mark an invitation as used
|
|
98
|
+
*/
|
|
99
|
+
export declare function markInvitationAsUsed(db: DbType, token: string): Promise<InvitationDetails | null>;
|
|
100
|
+
/**
|
|
101
|
+
* Revoke an invitation
|
|
102
|
+
*/
|
|
103
|
+
export declare function revokeInvitation(db: DbType, invitationId: number): Promise<InvitationDetails | null>;
|
|
104
|
+
/**
|
|
105
|
+
* Get invitation by ID
|
|
106
|
+
*/
|
|
107
|
+
export declare function getInvitationById(db: DbType, invitationId: number): Promise<InvitationWithDetails | null>;
|
|
108
|
+
/**
|
|
109
|
+
* Get invitation by token
|
|
110
|
+
*/
|
|
111
|
+
export declare function getInvitationByToken(db: DbType, token: string): Promise<InvitationWithDetails | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Get all pending invitations for an organization
|
|
114
|
+
*/
|
|
115
|
+
export declare function getPendingInvitationsByOrganization(db: DbType, organizationId: number): Promise<InvitationWithDetails[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Get all invitations (pending, used, expired, revoked) for an organization
|
|
118
|
+
*/
|
|
119
|
+
export declare function getAllInvitationsByOrganization(db: DbType, organizationId: number): Promise<InvitationWithDetails[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Check if a pending invitation exists for an email in an organization
|
|
122
|
+
*/
|
|
123
|
+
export declare function hasPendingInvitation(db: DbType, email: string, organizationId: number): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* Check if a shadow user has an active invitation for an organization
|
|
126
|
+
*/
|
|
127
|
+
export declare function hasActiveInvitationForShadowUser(db: DbType, shadowUserId: number, organizationId: number): Promise<boolean>;
|
|
128
|
+
/**
|
|
129
|
+
* Get all invitations sent by a specific user
|
|
130
|
+
*/
|
|
131
|
+
export declare function getInvitationsSentByUser(db: DbType, invitedByUserId: number): Promise<InvitationWithDetails[]>;
|
|
132
|
+
/**
|
|
133
|
+
* Get all pending invitations sent by a specific user
|
|
134
|
+
*/
|
|
135
|
+
export declare function getPendingInvitationsSentByUser(db: DbType, invitedByUserId: number): Promise<InvitationWithDetails[]>;
|
|
136
|
+
/**
|
|
137
|
+
* Delete expired invitations older than specified days
|
|
138
|
+
*/
|
|
139
|
+
export declare function cleanupExpiredInvitations(db: DbType, olderThanDays?: number): Promise<number>;
|
|
140
|
+
export {};
|
|
141
|
+
//# sourceMappingURL=invitation-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitation-operations.d.ts","sourceRoot":"","sources":["../../src/utils/invitation-operations.ts"],"names":[],"mappings":"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"}
|