@scavio/twenty 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,518 @@
1
+ import { createRequire as __createRequire } from 'module';
2
+ const require = __createRequire(import.meta.url);
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ try {
11
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
+ } catch (e2) {
13
+ throw mod = 0, e2;
14
+ }
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // node_modules/@sniptt/guards/build/guards/primitives.js
34
+ var require_primitives = __commonJS({
35
+ "node_modules/@sniptt/guards/build/guards/primitives.js"(exports) {
36
+ "use strict";
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.isSymbol = exports.isBigInt = exports.isString = exports.isNumber = exports.isBoolean = exports.isUndefined = void 0;
39
+ var isUndefined = (term) => {
40
+ return typeof term === "undefined";
41
+ };
42
+ exports.isUndefined = isUndefined;
43
+ var isBoolean = (term) => {
44
+ return typeof term === "boolean";
45
+ };
46
+ exports.isBoolean = isBoolean;
47
+ var isNumber = (term) => {
48
+ return typeof term === "number" && !Number.isNaN(term);
49
+ };
50
+ exports.isNumber = isNumber;
51
+ var isString = (term) => {
52
+ return typeof term === "string";
53
+ };
54
+ exports.isString = isString;
55
+ var isBigInt = (term) => {
56
+ return typeof term === "bigint";
57
+ };
58
+ exports.isBigInt = isBigInt;
59
+ var isSymbol = (term) => {
60
+ return typeof term === "symbol";
61
+ };
62
+ exports.isSymbol = isSymbol;
63
+ }
64
+ });
65
+
66
+ // node_modules/@sniptt/guards/build/guards/structural.js
67
+ var require_structural = __commonJS({
68
+ "node_modules/@sniptt/guards/build/guards/structural.js"(exports) {
69
+ "use strict";
70
+ Object.defineProperty(exports, "__esModule", { value: true });
71
+ exports.isDate = exports.isWeakSet = exports.isWeakMap = exports.isSet = exports.isMap = exports.isArray = exports.isObject = exports.isFunction = exports.isNull = void 0;
72
+ var isNull = (term) => {
73
+ return term === null;
74
+ };
75
+ exports.isNull = isNull;
76
+ var isFunction = (term) => {
77
+ return typeof term === "function";
78
+ };
79
+ exports.isFunction = isFunction;
80
+ var isObject = (term) => {
81
+ return !exports.isNull(term) && typeof term === "object";
82
+ };
83
+ exports.isObject = isObject;
84
+ var isArray = (term) => {
85
+ return Array.isArray(term);
86
+ };
87
+ exports.isArray = isArray;
88
+ var isMap = (term) => {
89
+ return term instanceof Map;
90
+ };
91
+ exports.isMap = isMap;
92
+ var isSet = (term) => {
93
+ return term instanceof Set;
94
+ };
95
+ exports.isSet = isSet;
96
+ var isWeakMap = (term) => {
97
+ return term instanceof WeakMap;
98
+ };
99
+ exports.isWeakMap = isWeakMap;
100
+ var isWeakSet = (term) => {
101
+ return term instanceof WeakSet;
102
+ };
103
+ exports.isWeakSet = isWeakSet;
104
+ var isDate = (term) => {
105
+ return term instanceof Date;
106
+ };
107
+ exports.isDate = isDate;
108
+ }
109
+ });
110
+
111
+ // node_modules/@sniptt/guards/build/guards/convenience.js
112
+ var require_convenience = __commonJS({
113
+ "node_modules/@sniptt/guards/build/guards/convenience.js"(exports) {
114
+ "use strict";
115
+ Object.defineProperty(exports, "__esModule", { value: true });
116
+ exports.isNegativeInteger = exports.isNonNegativeInteger = exports.isPositiveInteger = exports.isInteger = exports.isNumberOrNaN = exports.isNonEmptyString = exports.isNonEmptyArray = exports.isObjectOrNull = void 0;
117
+ var primitives_1 = require_primitives();
118
+ var structural_1 = require_structural();
119
+ var isObjectOrNull = (term) => {
120
+ return typeof term === "object";
121
+ };
122
+ exports.isObjectOrNull = isObjectOrNull;
123
+ var isNonEmptyArray = (term) => {
124
+ return structural_1.isArray(term) && term.length > 0;
125
+ };
126
+ exports.isNonEmptyArray = isNonEmptyArray;
127
+ var isNonEmptyString = (term) => {
128
+ return primitives_1.isString(term) && term.length > 0;
129
+ };
130
+ exports.isNonEmptyString = isNonEmptyString;
131
+ var isNumberOrNaN = (term) => {
132
+ return typeof term === "number";
133
+ };
134
+ exports.isNumberOrNaN = isNumberOrNaN;
135
+ var isInteger = (term) => {
136
+ return primitives_1.isNumber(term) && Number.isInteger(term);
137
+ };
138
+ exports.isInteger = isInteger;
139
+ var isPositiveInteger = (term) => {
140
+ return exports.isInteger(term) && term > 0;
141
+ };
142
+ exports.isPositiveInteger = isPositiveInteger;
143
+ var isNonNegativeInteger = (term) => {
144
+ return exports.isInteger(term) && term >= 0;
145
+ };
146
+ exports.isNonNegativeInteger = isNonNegativeInteger;
147
+ var isNegativeInteger = (term) => {
148
+ return exports.isInteger(term) && term < 0;
149
+ };
150
+ exports.isNegativeInteger = isNegativeInteger;
151
+ }
152
+ });
153
+
154
+ // node_modules/@sniptt/guards/build/index.js
155
+ var require_build = __commonJS({
156
+ "node_modules/@sniptt/guards/build/index.js"(exports) {
157
+ "use strict";
158
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o2, m, k, k2) {
159
+ if (k2 === void 0) k2 = k;
160
+ Object.defineProperty(o2, k2, { enumerable: true, get: function() {
161
+ return m[k];
162
+ } });
163
+ }) : (function(o2, m, k, k2) {
164
+ if (k2 === void 0) k2 = k;
165
+ o2[k2] = m[k];
166
+ }));
167
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o2, v) {
168
+ Object.defineProperty(o2, "default", { enumerable: true, value: v });
169
+ }) : function(o2, v) {
170
+ o2["default"] = v;
171
+ });
172
+ var __importStar = exports && exports.__importStar || function(mod) {
173
+ if (mod && mod.__esModule) return mod;
174
+ var result = {};
175
+ if (mod != null) {
176
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
177
+ }
178
+ __setModuleDefault(result, mod);
179
+ return result;
180
+ };
181
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
182
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
183
+ };
184
+ Object.defineProperty(exports, "__esModule", { value: true });
185
+ exports.structural = exports.primitives = exports.convenience = void 0;
186
+ exports.convenience = __importStar(require_convenience());
187
+ __exportStar(require_convenience(), exports);
188
+ exports.primitives = __importStar(require_primitives());
189
+ __exportStar(require_primitives(), exports);
190
+ exports.structural = __importStar(require_structural());
191
+ __exportStar(require_structural(), exports);
192
+ }
193
+ });
194
+
195
+ // src/logic-functions/start-enrichment.ts
196
+ import { CoreApiClient } from "twenty-client-sdk/core";
197
+
198
+ // twenty-sdk-define-stub:__twenty-sdk-define-stub__
199
+ var __defineFactoryStub = (config) => ({
200
+ success: true,
201
+ config,
202
+ errors: []
203
+ });
204
+ var __anyHandler = {
205
+ get(_target, prop) {
206
+ if (prop === "__esModule") return true;
207
+ if (prop === Symbol.toPrimitive) return () => "";
208
+ if (typeof prop === "symbol") return void 0;
209
+ return new Proxy(() => void 0, __anyHandler);
210
+ },
211
+ apply() {
212
+ return new Proxy(() => void 0, __anyHandler);
213
+ }
214
+ };
215
+ var __anyStub = new Proxy(() => void 0, __anyHandler);
216
+ var defineLogicFunction = __defineFactoryStub;
217
+ var STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS = __anyStub;
218
+
219
+ // src/constants/universal-identifiers.ts
220
+ var LOGIC_FUNCTION_UNIVERSAL_IDENTIFIERS = {
221
+ startEnrichment: "3299b3b9-f0cd-4ed8-aa81-5ec2b4650606",
222
+ enrichWorker: "d677dd12-557a-4a33-b285-d360b879ebdd"
223
+ };
224
+ var START_ENRICHMENT_ROUTE_PATH = "/scavio/enrich-companies";
225
+
226
+ // src/scavio/company-repository.ts
227
+ var PAGE_SIZE = 200;
228
+ var createCompanyRepository = (client) => ({
229
+ read: async (ids) => {
230
+ const records = [];
231
+ for (let start = 0; start < ids.length; start += PAGE_SIZE) {
232
+ const page = ids.slice(start, start + PAGE_SIZE);
233
+ const result = await client.query({
234
+ companies: {
235
+ __args: { filter: { id: { in: page } }, first: page.length },
236
+ edges: {
237
+ node: {
238
+ id: true,
239
+ name: true,
240
+ domainName: { primaryLinkUrl: true },
241
+ linkedinLink: { primaryLinkUrl: true },
242
+ scavioEnrichmentStatus: true
243
+ }
244
+ }
245
+ }
246
+ });
247
+ for (const edge of result.companies?.edges ?? []) {
248
+ if (edge?.node?.id) {
249
+ records.push(edge.node);
250
+ }
251
+ }
252
+ }
253
+ return records;
254
+ },
255
+ update: async (id, data) => {
256
+ await client.mutation({
257
+ updateCompany: { __args: { id, data }, id: true }
258
+ });
259
+ },
260
+ updateMany: async (ids, data) => {
261
+ for (let start = 0; start < ids.length; start += PAGE_SIZE) {
262
+ await client.mutation({
263
+ updateCompanies: {
264
+ __args: { filter: { id: { in: ids.slice(start, start + PAGE_SIZE) } }, data },
265
+ id: true
266
+ }
267
+ });
268
+ }
269
+ }
270
+ });
271
+
272
+ // node_modules/twenty-sdk/dist/logic-function/index.mjs
273
+ var import_guards = __toESM(require_build(), 1);
274
+ import { MetadataApiClient as o } from "twenty-client-sdk/metadata";
275
+ var S = ({ objectNameSingular: e2, recordId: t2, displayName: n2 }) => `[[record:${e2}:${t2}:${n2}]]`;
276
+ var C = "\n id\n handle\n displayName\n visibility\n connectedAccountId\n isSyncEnabled\n participantHandleFieldUniversalIdentifier\n messagingProviderUniversalIdentifier\n";
277
+ var w = `
278
+ mutation CreateAppMessageChannel($input: CreateAppMessageChannelInput!) {
279
+ createAppMessageChannel(input: $input) {
280
+ ${C}
281
+ }
282
+ }
283
+ `;
284
+ var E = `
285
+ query ListAppMessageChannels($filter: ListAppMessageChannelsInput) {
286
+ appMessageChannels(filter: $filter) {
287
+ ${C}
288
+ }
289
+ }
290
+ `;
291
+ var O = `
292
+ mutation UpdateAppMessageChannel($input: UpdateAppMessageChannelInput!) {
293
+ updateAppMessageChannel(input: $input) {
294
+ ${C}
295
+ }
296
+ }
297
+ `;
298
+ var A = `
299
+ mutation DeleteAppMessageChannel($id: UUID!) {
300
+ deleteAppMessageChannel(id: $id) {
301
+ ${C}
302
+ }
303
+ }
304
+ `;
305
+ var L = "\n id\n externalId\n name\n isSynced\n messageChannelId\n";
306
+ var R = `
307
+ query ListAppMessageFolders($filter: ListAppMessageFoldersInput) {
308
+ appMessageFolders(filter: $filter) {
309
+ ${L}
310
+ }
311
+ }
312
+ `;
313
+ var B = `
314
+ mutation SyncAppMessageFolders($input: SyncAppMessageFoldersInput!) {
315
+ syncAppMessageFolders(input: $input) {
316
+ ${L}
317
+ }
318
+ }
319
+ `;
320
+ var U = "agentChatAssistant";
321
+ var ze = S({
322
+ objectNameSingular: U,
323
+ recordId: U,
324
+ displayName: "Ada"
325
+ });
326
+ var Ue = async (e2) => {
327
+ let { enqueueJobs: t2 } = await new o().mutation({ enqueueJobs: {
328
+ __args: { input: e2 },
329
+ enqueued: true,
330
+ logicFunctionUniversalIdentifier: true,
331
+ enqueuedJobsCount: true,
332
+ jobIds: true,
333
+ jobs: {
334
+ jobId: true,
335
+ sizeBytes: true
336
+ },
337
+ availableBytes: true
338
+ } });
339
+ return t2;
340
+ };
341
+
342
+ // src/scavio/enqueue-workers.ts
343
+ var enqueueWorkers = async (payloads, options) => {
344
+ if (payloads.length === 0) {
345
+ return;
346
+ }
347
+ await Ue({
348
+ logicFunctionUniversalIdentifier: LOGIC_FUNCTION_UNIVERSAL_IDENTIFIERS.enrichWorker,
349
+ jobs: payloads.map((payload) => ({ payload })),
350
+ ...options?.delayMs ? { delayMs: options.delayMs } : {}
351
+ });
352
+ };
353
+
354
+ // src/scavio/record-ids.ts
355
+ var extractRecordIds = (records) => {
356
+ const list = Array.isArray(records) ? records : [records];
357
+ const ids = list.map((record) => typeof record === "string" ? record : record?.id).filter((id) => typeof id === "string" && id.trim() !== "");
358
+ return [...new Set(ids)];
359
+ };
360
+
361
+ // src/scavio/constants.ts
362
+ var SCAVIO_API_KEY_ENV_VAR_NAME = "SCAVIO_API_KEY";
363
+ var PARALLEL_REQUESTS_ENV_VAR_NAME = "SCAVIO_PARALLEL_REQUESTS";
364
+ var DEFAULT_PARALLEL_REQUESTS = 1;
365
+ var MAX_PARALLEL_REQUESTS = 10;
366
+ var MAX_COMPANIES_PER_RUN = 1e3;
367
+
368
+ // src/scavio/settings.ts
369
+ var getApiKey = () => {
370
+ const key = process.env[SCAVIO_API_KEY_ENV_VAR_NAME]?.trim();
371
+ return key ? key : void 0;
372
+ };
373
+ var getParallelRequests = () => {
374
+ const raw = Number(process.env[PARALLEL_REQUESTS_ENV_VAR_NAME]);
375
+ if (!Number.isFinite(raw) || raw < 1) {
376
+ return DEFAULT_PARALLEL_REQUESTS;
377
+ }
378
+ return Math.min(Math.floor(raw), MAX_PARALLEL_REQUESTS);
379
+ };
380
+
381
+ // src/scavio/normalize-domain.ts
382
+ var SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:\/\//;
383
+ var LEADING_WWW_REGEX = /^www\./;
384
+ var HOST_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)+$/;
385
+ var normalizeDomain = (raw) => {
386
+ if (typeof raw !== "string") {
387
+ return void 0;
388
+ }
389
+ const host = raw.trim().toLowerCase().replace(SCHEME_REGEX, "").split(/[/?#]/)[0].split(":")[0].replace(LEADING_WWW_REGEX, "");
390
+ return HOST_REGEX.test(host) ? host : void 0;
391
+ };
392
+
393
+ // src/scavio/start-enrichment.ts
394
+ var MISSING_KEY_MESSAGE = "Add your Scavio API key in Settings > Applications > Scavio Company Enrichment.";
395
+ var splitIntoChains = (ids, chains) => {
396
+ const count = Math.max(1, Math.min(chains, ids.length));
397
+ const lists = Array.from({ length: count }, () => []);
398
+ ids.forEach((id, index) => lists[index % count].push(id));
399
+ return lists.filter((list) => list.length > 0);
400
+ };
401
+ var startEnrichment = async ({
402
+ recordIds,
403
+ repository,
404
+ enqueueWorkers: enqueueWorkers2,
405
+ apiKey,
406
+ parallelRequests,
407
+ now
408
+ }) => {
409
+ if (!apiKey) {
410
+ return { success: false, queued: 0, noWebsite: 0, notFound: 0, message: MISSING_KEY_MESSAGE };
411
+ }
412
+ const ids = recordIds.slice(0, MAX_COMPANIES_PER_RUN);
413
+ const companies = await repository.read(ids);
414
+ const withWebsite = [];
415
+ const withoutWebsite = [];
416
+ for (const company of companies) {
417
+ (normalizeDomain(company.domainName?.primaryLinkUrl) ? withWebsite : withoutWebsite).push(
418
+ company.id
419
+ );
420
+ }
421
+ if (withoutWebsite.length > 0) {
422
+ await repository.updateMany(withoutWebsite, {
423
+ scavioEnrichmentStatus: "NO_WEBSITE",
424
+ scavioEnrichmentNote: "Add the company website (Domains field) to enrich it.",
425
+ scavioLastEnrichedAt: now
426
+ });
427
+ }
428
+ if (withWebsite.length > 0) {
429
+ await repository.updateMany(withWebsite, {
430
+ scavioEnrichmentStatus: "QUEUED",
431
+ scavioEnrichmentNote: null
432
+ });
433
+ try {
434
+ await enqueueWorkers2(
435
+ splitIntoChains(withWebsite, parallelRequests).map((companyIds) => ({
436
+ companyIds,
437
+ rateLimitRetries: 0
438
+ }))
439
+ );
440
+ } catch {
441
+ await repository.updateMany(withWebsite, {
442
+ scavioEnrichmentStatus: "FAILED",
443
+ scavioEnrichmentNote: "Twenty could not queue the enrichment. Try again."
444
+ });
445
+ return {
446
+ success: false,
447
+ queued: 0,
448
+ noWebsite: withoutWebsite.length,
449
+ notFound: ids.length - companies.length,
450
+ message: "Twenty could not queue the enrichment. Try again."
451
+ };
452
+ }
453
+ }
454
+ return {
455
+ success: true,
456
+ queued: withWebsite.length,
457
+ noWebsite: withoutWebsite.length,
458
+ notFound: ids.length - companies.length
459
+ };
460
+ };
461
+
462
+ // src/logic-functions/start-enrichment.ts
463
+ var isRoutePayload = (input) => typeof input === "object" && input !== null && "requestContext" in input;
464
+ var handler = async (input) => {
465
+ const recordIds = isRoutePayload(input) ? extractRecordIds(input.body?.recordIds ?? []) : extractRecordIds(input?.records ?? []);
466
+ return startEnrichment({
467
+ recordIds,
468
+ repository: createCompanyRepository(new CoreApiClient()),
469
+ enqueueWorkers,
470
+ apiKey: getApiKey(),
471
+ parallelRequests: getParallelRequests(),
472
+ now: (/* @__PURE__ */ new Date()).toISOString()
473
+ });
474
+ };
475
+ var start_enrichment_default = defineLogicFunction({
476
+ universalIdentifier: LOGIC_FUNCTION_UNIVERSAL_IDENTIFIERS.startEnrichment,
477
+ name: "start-scavio-enrichment",
478
+ description: "Queues a Scavio enrichment for the given companies. Results are written to each company as it finishes.",
479
+ timeoutSeconds: 60,
480
+ handler,
481
+ httpRouteTriggerSettings: {
482
+ path: START_ENRICHMENT_ROUTE_PATH,
483
+ httpMethod: "POST",
484
+ isAuthRequired: true
485
+ },
486
+ workflowActionTriggerSettings: {
487
+ label: "Enrich companies with Scavio",
488
+ icon: "IconSparkles",
489
+ inputSchema: [
490
+ {
491
+ type: "object",
492
+ properties: {
493
+ records: {
494
+ type: "records",
495
+ objectUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
496
+ label: "Companies"
497
+ }
498
+ }
499
+ }
500
+ ],
501
+ outputSchema: [
502
+ {
503
+ type: "object",
504
+ properties: {
505
+ success: { type: "boolean", label: "Started" },
506
+ queued: { type: "number", label: "Companies queued" },
507
+ noWebsite: { type: "number", label: "Companies without a website" },
508
+ notFound: { type: "number", label: "Companies not found" },
509
+ message: { type: "string", label: "Message" }
510
+ }
511
+ }
512
+ ]
513
+ }
514
+ });
515
+ export {
516
+ start_enrichment_default as default
517
+ };
518
+ //# sourceMappingURL=start-enrichment.mjs.map