twenty-app-intake 0.2.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.
- package/manifest.json +1466 -0
- package/package.json +56 -0
- package/public/logo.svg +20 -0
- package/src/front-components/dashboard.mjs +21994 -0
- package/src/front-components/dashboard.mjs.map +7 -0
- package/src/front-components/settings-panel.mjs +22150 -0
- package/src/front-components/settings-panel.mjs.map +7 -0
- package/src/front-components/source-panel.mjs +22010 -0
- package/src/front-components/source-panel.mjs.map +7 -0
- package/src/logic-functions/health.mjs +118 -0
- package/src/logic-functions/health.mjs.map +7 -0
- package/src/logic-functions/register.mjs +183 -0
- package/src/logic-functions/register.mjs.map +7 -0
- package/src/logic-functions/retry.mjs +1244 -0
- package/src/logic-functions/retry.mjs.map +7 -0
- package/src/logic-functions/test-ingest.mjs +549 -0
- package/src/logic-functions/test-ingest.mjs.map +7 -0
- package/src/logic-functions/webhook.mjs +1213 -0
- package/src/logic-functions/webhook.mjs.map +7 -0
- package/src/post-install.mjs +181 -0
- package/src/post-install.mjs.map +7 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["twenty-sdk-define-stub:__twenty-sdk-define-stub__", "../../../../src/logic-functions/retry.ts", "../../../../src/constants/universal-identifiers.ts", "../../../../src/lib/pipeline.ts", "../../../../src/lib/result.ts", "../../../../src/lib/stages/load-source.stage.ts", "../../../../src/lib/stages/verify-signature.stage.ts", "../../../../src/lib/idempotency.ts", "../../../../src/lib/stages/idempotency.stage.ts", "../../../../src/lib/flattener.ts", "../../../../src/lib/stages/flatten.stage.ts", "../../../../src/constants/field-map.ts", "../../../../src/lib/type-detector.ts", "../../../../src/lib/classifier.ts", "../../../../src/lib/normalizer.ts", "../../../../src/lib/stages/normalize.stage.ts", "../../../../src/lib/rest-client.ts", "../../../../src/lib/stages/sync-schema.stage.ts", "../../../../src/lib/note-formatter.ts", "../../../../src/lib/stages/upsert-record.stage.ts", "../../../../src/lib/stages/write-log.stage.ts", "../../../../src/lib/pipeline-factory.ts"],
|
|
4
|
+
"sourcesContent": ["\n// Auto-generated stub for twenty-sdk/define injected by the SDK CLI build.\n// Real implementations would pull in zod, twenty-shared and ~1MB of code; at\n// runtime only `default.config.handler` is consumed, so tiny no-ops suffice.\nconst __defineFactoryStub = (config) => ({\n success: true,\n config,\n errors: [],\n});\n\nconst __anyHandler = {\n get(_target, prop) {\n if (prop === '__esModule') return true;\n if (prop === Symbol.toPrimitive) return () => '';\n if (typeof prop === 'symbol') return undefined;\n return new Proxy(() => undefined, __anyHandler);\n },\n apply() {\n return new Proxy(() => undefined, __anyHandler);\n },\n};\nconst __anyStub = new Proxy(() => undefined, __anyHandler);\n\nexport const createValidationResult = __defineFactoryStub;\nexport const defineAgent = __defineFactoryStub;\nexport const defineApplication = __defineFactoryStub;\nexport const defineApplicationRole = __defineFactoryStub;\nexport const defineCommandMenuItem = __defineFactoryStub;\nexport const defineConnectionProvider = __defineFactoryStub;\nexport const defineField = __defineFactoryStub;\nexport const defineFrontComponent = __defineFactoryStub;\nexport const defineLogicFunction = __defineFactoryStub;\nexport const defineNavigationMenuItem = __defineFactoryStub;\nexport const defineObject = __defineFactoryStub;\nexport const definePageLayout = __defineFactoryStub;\nexport const definePageLayoutTab = __defineFactoryStub;\nexport const definePostInstallLogicFunction = __defineFactoryStub;\nexport const definePreInstallLogicFunction = __defineFactoryStub;\nexport const defineRole = __defineFactoryStub;\nexport const defineSkill = __defineFactoryStub;\nexport const defineView = __defineFactoryStub;\nexport const AggregateOperations = __anyStub;\nexport const DateDisplayFormat = __anyStub;\nexport const FieldMetadataSettingsOnClickAction = __anyStub;\nexport const FieldType = __anyStub;\nexport const HTTPMethod = __anyStub;\nexport const NavigationMenuItemType = __anyStub;\nexport const NumberDataType = __anyStub;\nexport const ObjectRecordGroupByDateGranularity = __anyStub;\nexport const OnDeleteAction = __anyStub;\nexport const PageLayoutTabLayoutMode = __anyStub;\nexport const PermissionFlag = __anyStub;\nexport const RelationType = __anyStub;\nexport const STANDARD_OBJECT = __anyStub;\nexport const STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS = __anyStub;\nexport const ViewCalendarLayout = __anyStub;\nexport const ViewFilterGroupLogicalOperator = __anyStub;\nexport const ViewFilterOperand = __anyStub;\nexport const ViewKey = __anyStub;\nexport const ViewOpenRecordIn = __anyStub;\nexport const ViewSortDirection = __anyStub;\nexport const ViewType = __anyStub;\nexport const ViewVisibility = __anyStub;\nexport const generateDefaultFieldUniversalIdentifier = __anyStub;\nexport const validateFields = __anyStub;\n", "import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';\nimport { CoreApiClient } from 'twenty-client-sdk/core';\nimport { MetadataApiClient } from 'twenty-client-sdk/metadata';\nimport { IDS } from '../constants/universal-identifiers';\nimport { createPipeline } from '../lib/pipeline-factory';\nimport type { PipelineContext } from '../lib/pipeline';\nimport { coreApi } from '../lib/rest-client';\n\nconst handler = async (params: RoutePayload) => {\n const logId = params.pathParameters?.['logId'];\n if (!logId) {\n return { statusCode: 400, body: { error: 'Missing logId in URL' } };\n }\n\n // Fetch the existing log\n const logResult = await coreApi.get<{\n data: {\n intakeLog: {\n id: string;\n status: string;\n rawPayload: string | null;\n intakeSourceId: string | null;\n error: string | null;\n };\n };\n }>(`/intakeLogs/${logId}`).catch(() => null);\n\n const log = logResult?.data?.intakeLog;\n\n if (!log) {\n return { statusCode: 404, body: { error: `IntakeLog ${logId} not found` } };\n }\n\n if (log.status === 'SUCCESS') {\n return {\n statusCode: 400,\n body: { error: 'This ingestion already succeeded \u2014 no retry needed', status: log.status },\n };\n }\n\n if (!log.rawPayload) {\n return {\n statusCode: 400,\n body: { error: 'No raw payload stored on this log \u2014 retry requires rawPayload field (logs created in v0.2.0+)' },\n };\n }\n\n let rawPayload: Record<string, unknown>;\n try {\n rawPayload = JSON.parse(log.rawPayload);\n } catch {\n return { statusCode: 400, body: { error: 'rawPayload is not valid JSON' } };\n }\n\n // We need a sourceSlug to run the pipeline \u2014 get it from the source record\n let sourceSlug = 'unknown';\n if (log.intakeSourceId) {\n const srcResult = await coreApi.get<{ data: { intakeSource: { slug: string } } }>(\n `/intakeSources/${log.intakeSourceId}`,\n ).catch(() => null);\n sourceSlug = srcResult?.data?.intakeSource?.slug ?? 'unknown';\n }\n\n const startedAt = Date.now();\n const coreClient = new CoreApiClient();\n const metadataClient = new MetadataApiClient();\n const pipeline = createPipeline(coreClient, metadataClient);\n\n const ctx: PipelineContext = {\n sourceSlug,\n rawBody: undefined, // HMAC skipped on retry \u2014 source already verified originally\n rawPayload,\n headers: {},\n startedAt,\n skipDedup: true, // Critical \u2014 bypass idempotency so the payload re-runs\n fieldsCreated: 0,\n fieldsMatched: 0,\n warnings: [],\n events: [],\n };\n\n const result = await pipeline.run(ctx);\n\n if (!result.ok) {\n return {\n statusCode: 500,\n body: {\n error: `Retry failed: ${result.error.message}`,\n code: result.error.code,\n originalLogId: logId,\n },\n };\n }\n\n const { value: finalCtx } = result;\n\n return {\n statusCode: 200,\n body: {\n success: true,\n originalLogId: logId,\n recordId: finalCtx.personId ?? finalCtx.companyId,\n recordType: finalCtx.recordType,\n personId: finalCtx.personId,\n companyId: finalCtx.companyId,\n fieldsCreated: finalCtx.fieldsCreated,\n processingMs: Date.now() - startedAt,\n warnings: finalCtx.warnings,\n },\n };\n};\n\nexport default defineLogicFunction({\n universalIdentifier: IDS.RETRY_LOGIC_FUNCTION,\n name: 'intake-retry',\n description: 'Retry a failed ingestion using the stored raw payload from an IntakeLog record.',\n timeoutSeconds: 30,\n handler,\n httpRouteTriggerSettings: {\n path: '/intake/logs/:logId/retry',\n httpMethod: 'POST',\n isAuthRequired: true,\n },\n});\n", "export const IDS = {\n APPLICATION: '96a389dd-384a-43a1-a376-9d3cf01b6ab7',\n DEFAULT_ROLE: '3dd2cdb0-32c7-44b4-9f7b-0a9c667ec249',\n\n // Objects\n INTAKE_SOURCE_OBJECT: '8c1c227c-db7d-4834-b328-cacbe8af0bfc',\n INTAKE_LOG_OBJECT: 'b77a2439-1503-4ef6-ab8b-8f4293bc19da',\n INTAKE_FIELD_RULE_OBJECT: 'e74df817-ff25-4bfb-bdf0-651662ca327e',\n\n // IntakeSource fields\n INTAKE_SOURCE_NAME: '0deb7e4b-bb90-4c86-b903-5208b42041e2',\n INTAKE_SOURCE_SLUG: '18f7645b-2dce-4145-b1b6-9cc3332c0578',\n INTAKE_SOURCE_TARGET_OBJECT: '65f3d7f7-a601-4375-9c67-684d0044620b',\n INTAKE_SOURCE_SECRET: '4c919402-07f5-4041-ade6-a42402f1881f',\n INTAKE_SOURCE_STATUS: '6f1fa6fe-02b4-48ab-b1ee-97c600bbf483',\n INTAKE_SOURCE_CREATE_OPP: '67ae59aa-2275-4ef2-b594-137f6bfafd99',\n INTAKE_SOURCE_OPP_TEMPLATE: '3907b346-77a6-4c79-a4d7-6e1cc20bb82b',\n INTAKE_SOURCE_TOTAL_INGESTED: '69655a93-bc70-48bd-874e-aeccc63ee1a8',\n INTAKE_SOURCE_TOTAL_FAILED: '27b3a499-183e-4cc3-8e40-938f953a986d',\n INTAKE_SOURCE_LAST_INGESTED: 'e167f628-9865-468e-894a-b4b6150cec26',\n\n // IntakeLog fields\n INTAKE_LOG_SOURCE_RELATION: 'b1c623ea-7a9a-47a5-bee4-35fdd668a637',\n INTAKE_LOG_STATUS: '8b6d26d1-f89c-486c-a617-9f9f6a9ca36d',\n INTAKE_LOG_PAYLOAD_HASH: 'c43bb1ad-e78a-4c60-bd95-02475ede7f44',\n INTAKE_LOG_RECORD_ID: '77a55116-a64b-4954-8369-341022dd5bdd',\n INTAKE_LOG_RECORD_TYPE: '02154e96-5808-48ed-8838-51083f174550',\n INTAKE_LOG_FIELDS_CREATED: '2295ca2b-b559-4b38-9771-12dd8d3d76d7',\n INTAKE_LOG_FIELDS_MATCHED: '83d07a0f-5bcd-4fb1-9759-f9b04b9381d8',\n INTAKE_LOG_OVERFLOW_COUNT: '4090acb1-f48a-4957-bb91-c642f8f434a7',\n INTAKE_LOG_PROCESSING_MS: 'a9191f27-4b40-42e9-8cce-20c75900e12c',\n INTAKE_LOG_ERROR: '8d9979f1-9774-43a8-b958-d1b37bd4ecc7',\n INTAKE_LOG_PROCESSED_AT: 'a8d99fbd-722e-4987-8afe-b830ac026f0a',\n\n // IntakeFieldRule fields\n INTAKE_FIELD_RULE_SOURCE_RELATION: '396dd1f1-3873-4efa-a6bb-7b41eda14d83',\n INTAKE_FIELD_RULE_INPUT_PATTERN: '757201a0-9f64-47b9-bf3a-a793074bf84e',\n INTAKE_FIELD_RULE_CANONICAL_NAME: 'fafebc55-a2cc-4c9f-975b-050c2676659d',\n INTAKE_FIELD_RULE_FIELD_TYPE: '72d1f6d8-d63e-419e-a244-8127d7b4705f',\n INTAKE_FIELD_RULE_PRIORITY: '911df299-940b-44f9-92f7-3fd01fde01a7',\n INTAKE_FIELD_RULE_IS_ACTIVE: '6f9cd96d-aecd-437f-a7b5-d45548782771',\n\n // Logic Functions\n WEBHOOK_LOGIC_FUNCTION: '8323c257-48fe-4bb6-b1dd-166844f575c0',\n HEALTH_LOGIC_FUNCTION: '4ece4e39-286b-4820-81f4-b7beee71d092',\n REGISTER_LOGIC_FUNCTION: '56d46e18-6cae-4d99-9893-b7d70740c9db',\n\n // IntakeSource reverse relation fields\n INTAKE_SOURCE_LOGS_REVERSE: '6ecfa369-22e0-4812-bb75-4338cea8be65',\n INTAKE_SOURCE_RULES_REVERSE: '776fefaf-0eee-4ec0-93e0-d11bd80c1e20',\n\n // v0.2.0 \u2014 rawPayload + retry + post-install + UI\n INTAKE_LOG_RAW_PAYLOAD: 'b65c9e1c-f2c1-4c52-a5b3-1e1ac3139692',\n RETRY_LOGIC_FUNCTION: '90f20396-a69a-4ae4-af20-6be65c565bb5',\n POST_INSTALL_LOGIC_FUNCTION: 'e836fdd6-fd54-4aa4-ba6d-87d5a02148ef',\n LOG_RETRY_FRONT_COMPONENT: '0cb97f6d-30e2-48c8-90e1-241b82870b4d',\n FIELD_RULES_TABLE_FRONT_COMPONENT: 'c35faad9-3468-4746-9c1c-b13d73e5e09b',\n SOURCE_PAGE_LAYOUT: '8c894ba8-5c8c-45ed-b0af-1d22ede93eb9',\n SOURCE_LAYOUT_TAB_RULES: '80f5c49a-083c-4062-8bd5-ae158abb6c33',\n SOURCE_LAYOUT_TAB_RULES_WIDGET: '26a9ebb7-1d59-4b03-a018-56968f6df224',\n LOG_PAGE_LAYOUT: 'b0972802-ede5-463c-9f59-cb05f04957db',\n LOG_LAYOUT_TAB_RETRY: '6b109695-ba3a-43de-a31a-23119ccf87ba',\n LOG_LAYOUT_TAB_RETRY_WIDGET: '11727c1a-5145-46de-9742-88d07d64c72e',\n SAMPLE_RULE_PHONE: '8440da8d-8ac4-4f4b-baa2-4d62936cde35',\n SAMPLE_RULE_EMAIL: 'd123cde4-05aa-44e1-86f6-454be1d7048b',\n SAMPLE_RULE_FULLNAME: '00e49fe8-1b48-4f5b-aaf4-414d0923c712',\n\n // Views & Navigation\n SOURCES_VIEW: '4435cd43-5c13-472f-b4f9-b686c0f46285',\n LOGS_VIEW: 'a2cd0a93-9778-4ba5-99d9-b8b89c4fb39d',\n INTAKE_NAV_ITEM: 'e81bf288-5686-4713-86ae-e2947b124cab',\n} as const;\n", "import type { Result, AppError } from './result';\nimport type { NormalizedField } from './normalizer';\n\nexport type PipelineContext = {\n // \u2500\u2500 Entry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sourceSlug: string;\n rawBody: string | undefined;\n rawPayload: Record<string, unknown>;\n headers: Record<string, string | undefined>;\n startedAt: number;\n\n // \u2500\u2500 Resolved source config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n source?: {\n id: string;\n name: string;\n slug: string;\n targetObject: 'PERSON' | 'COMPANY' | 'AUTO';\n webhookSecret: string | null;\n status: 'ACTIVE' | 'PAUSED';\n createOpportunity: boolean;\n opportunityNameTemplate: string;\n };\n\n // \u2500\u2500 Idempotency \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n payloadHash?: string;\n\n // \u2500\u2500 Transformation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n flat?: Record<string, unknown>;\n structuredCompany?: Record<string, unknown>;\n structuredPerson?: Record<string, unknown>;\n normalizedFields?: NormalizedField[];\n crmFields?: NormalizedField[];\n noteFields?: NormalizedField[];\n\n // \u2500\u2500 Schema sync \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n fieldsCreated: number;\n fieldsMatched: number;\n\n // \u2500\u2500 Output \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n personId?: string;\n companyId?: string;\n opportunityId?: string;\n noteId?: string;\n recordType?: 'PERSON' | 'COMPANY';\n\n // \u2500\u2500 Flags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n skipDedup?: boolean;\n\n // \u2500\u2500 Diagnostics \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n warnings: string[];\n events: PipelineEvent[];\n};\n\nexport type PipelineEvent = {\n stage: string;\n message: string;\n data?: unknown;\n};\n\nexport interface PipelineStage {\n readonly name: string;\n execute(ctx: PipelineContext): Promise<Result<PipelineContext>>;\n}\n\nexport class Pipeline {\n private readonly stages: PipelineStage[] = [];\n\n use(stage: PipelineStage): this {\n this.stages.push(stage);\n return this;\n }\n\n async run(initial: PipelineContext): Promise<Result<PipelineContext, AppError>> {\n let ctx = initial;\n\n for (const stage of this.stages) {\n const result = await stage.execute(ctx);\n\n if (!result.ok) {\n return {\n ok: false,\n error: { ...result.error, stage: stage.name },\n };\n }\n\n ctx = result.value;\n ctx.events.push({ stage: stage.name, message: 'completed' });\n }\n\n return { ok: true, value: ctx };\n }\n}\n", "export type AppError = {\n code: ErrorCode;\n message: string;\n stage?: string;\n details?: unknown;\n};\n\nexport const ErrorCode = {\n INVALID_SIGNATURE: 'INVALID_SIGNATURE',\n INVALID_PAYLOAD: 'INVALID_PAYLOAD',\n SOURCE_NOT_FOUND: 'SOURCE_NOT_FOUND',\n SOURCE_PAUSED: 'SOURCE_PAUSED',\n DUPLICATE_PAYLOAD: 'DUPLICATE_PAYLOAD',\n FIELD_CREATE_FAILED: 'FIELD_CREATE_FAILED',\n RECORD_UPSERT_FAILED: 'RECORD_UPSERT_FAILED',\n NOTE_CREATE_FAILED: 'NOTE_CREATE_FAILED',\n SCHEMA_FETCH_FAILED: 'SCHEMA_FETCH_FAILED',\n INTERNAL_ERROR: 'INTERNAL_ERROR',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport type Ok<T> = { ok: true; value: T };\nexport type Err<E extends AppError = AppError> = { ok: false; error: E };\nexport type Result<T, E extends AppError = AppError> = Ok<T> | Err<E>;\n\nexport const ok = <T>(value: T): Ok<T> => ({ ok: true, value });\n\nexport const err = <E extends AppError>(\n code: E['code'],\n message: string,\n details?: unknown,\n): Err<E> =>\n ({ ok: false, error: { code, message, details } as E });\n\nexport function isOk<T>(r: Result<T>): r is Ok<T> {\n return r.ok;\n}\n\nexport function unwrapOr<T>(r: Result<T>, fallback: T): T {\n return r.ok ? r.value : fallback;\n}\n\nexport function mapResult<T, U>(\n r: Result<T>,\n fn: (v: T) => U,\n): Result<U> {\n return r.ok ? ok(fn(r.value)) : r;\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok, err, ErrorCode } from '../result';\nimport type { CoreApiClient } from 'twenty-client-sdk/core';\n\nexport class LoadSourceStage implements PipelineStage {\n readonly name = 'load-source';\n\n constructor(private readonly client: CoreApiClient) {}\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n const result = await this.client.query({\n intakeSources: {\n __args: { filter: { slug: { eq: ctx.sourceSlug } } },\n edges: {\n node: {\n id: true,\n name: true,\n slug: true,\n targetObject: true,\n webhookSecret: true,\n status: true,\n createOpportunity: true,\n opportunityNameTemplate: true,\n },\n },\n },\n });\n\n const node = result.intakeSources?.edges?.[0]?.node;\n\n if (!node) {\n return err(ErrorCode.SOURCE_NOT_FOUND, `No Intake source found with slug \"${ctx.sourceSlug}\"`);\n }\n\n if (node.status === 'PAUSED') {\n return err(ErrorCode.SOURCE_PAUSED, `Source \"${node.name}\" is paused`);\n }\n\n return ok({\n ...ctx,\n source: {\n id: node.id,\n name: node.name,\n slug: node.slug,\n targetObject: node.targetObject as 'PERSON' | 'COMPANY' | 'AUTO',\n webhookSecret: node.webhookSecret ?? null,\n status: node.status as 'ACTIVE' | 'PAUSED',\n createOpportunity: node.createOpportunity ?? true,\n opportunityNameTemplate: node.opportunityNameTemplate ?? '{{source}} \u2014 {{firstName}} {{lastName}}',\n },\n });\n }\n}\n", "import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok, err, ErrorCode } from '../result';\n\nexport class VerifySignatureStage implements PipelineStage {\n readonly name = 'verify-signature';\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n const secret = ctx.source?.webhookSecret;\n\n // If INTAKE_REQUIRE_HMAC is enabled globally, reject sources without a secret\n const requireHmac = process.env['INTAKE_REQUIRE_HMAC'] === 'true';\n if (!secret) {\n if (requireHmac) return err(ErrorCode.INVALID_SIGNATURE, 'This source has no webhook secret \u2014 INTAKE_REQUIRE_HMAC is enabled');\n return ok(ctx);\n }\n\n const signature = ctx.headers['x-webhook-signature'];\n if (!signature) {\n return err(ErrorCode.INVALID_SIGNATURE, 'Missing X-Webhook-Signature header');\n }\n\n if (!ctx.rawBody) {\n ctx.warnings.push('rawBody unavailable \u2014 skipping HMAC verification');\n return ok(ctx);\n }\n\n const expected = createHmac('sha256', secret)\n .update(ctx.rawBody)\n .digest('hex');\n\n const sigBuf = Buffer.from(signature.replace(/^sha256=/, ''));\n const expBuf = Buffer.from(expected);\n\n if (sigBuf.length !== expBuf.length || !timingSafeEqual(sigBuf, expBuf)) {\n return err(ErrorCode.INVALID_SIGNATURE, 'Webhook signature verification failed');\n }\n\n return ok(ctx);\n }\n}\n", "import { createHash } from 'node:crypto';\n\n/**\n * Compute a stable SHA-256 hash of a payload.\n * Keys are sorted before hashing so that { a:1, b:2 } and { b:2, a:1 }\n * produce the same hash \u2014 safe to retry from any client.\n */\nexport function computePayloadHash(payload: unknown): string {\n const stable = stableStringify(payload);\n return createHash('sha256').update(stable).digest('hex');\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || value === undefined) return String(value);\n if (typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) {\n return '[' + value.map(stableStringify).join(',') + ']';\n }\n const obj = value as Record<string, unknown>;\n const sorted = Object.keys(obj)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`)\n .join(',');\n return '{' + sorted + '}';\n}\n\n/** Derive a human-readable idempotency window label. */\nexport function withinWindow(processedAt: Date, windowMs = 5 * 60 * 1000): boolean {\n return Date.now() - processedAt.getTime() < windowMs;\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok, err, ErrorCode } from '../result';\nimport { computePayloadHash, withinWindow } from '../idempotency';\nimport type { CoreApiClient } from 'twenty-client-sdk/core';\n\nexport class IdempotencyStage implements PipelineStage {\n readonly name = 'idempotency';\n\n constructor(private readonly client: CoreApiClient) {}\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n const hash = computePayloadHash(ctx.rawPayload);\n\n // Retry path \u2014 skip dedup so previously seen payloads can be re-run\n if (ctx.skipDedup) return ok({ ...ctx, payloadHash: hash });\n\n\n // Check if we've seen this payload recently\n const existing = await this.client.query({\n intakeLogs: {\n __args: {\n filter: { payloadHash: { eq: hash } },\n orderBy: { processedAt: 'DescNullsLast' },\n first: 1,\n },\n edges: {\n node: {\n id: true,\n status: true,\n recordId: true,\n processedAt: true,\n },\n },\n },\n });\n\n const prior = existing.intakeLogs?.edges?.[0]?.node;\n\n const windowMins = parseInt(process.env['INTAKE_DEDUP_WINDOW_MINUTES'] ?? '5', 10);\n if (prior && withinWindow(new Date(prior.processedAt), windowMins * 60 * 1000)) {\n return err(\n ErrorCode.DUPLICATE_PAYLOAD,\n `Duplicate payload \u2014 already processed ${prior.status.toLowerCase()} (log ${prior.id})`,\n { priorLogId: prior.id, priorRecordId: prior.recordId },\n );\n }\n\n return ok({ ...ctx, payloadHash: hash });\n }\n}\n", "type FlatRecord = Record<string, unknown>;\n\nconst MAX_DEPTH = 8;\n\n/**\n * Recursively flatten a nested object into a single-level record.\n * Arrays are kept as-is (classified as notes downstream).\n * Circular references are detected and dropped.\n *\n * e.g. { user: { phone: \"x\" } } \u2192 { userPhone: \"x\" }\n */\nexport function flatten(\n input: unknown,\n prefix = '',\n depth = 0,\n seen = new WeakSet<object>(),\n): FlatRecord {\n if (depth > MAX_DEPTH) return {};\n if (input === null || input === undefined) return {};\n if (typeof input !== 'object') {\n return prefix ? { [prefix]: input } : {};\n }\n if (Array.isArray(input)) {\n return prefix ? { [prefix]: input } : {};\n }\n\n const obj = input as Record<string, unknown>;\n\n if (seen.has(obj)) return {};\n seen.add(obj);\n\n const result: FlatRecord = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const newKey = prefix ? `${prefix}${toPascalSegment(key)}` : toCamelSegment(key);\n\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value)\n ) {\n const nested = flatten(value, newKey, depth + 1, seen);\n Object.assign(result, nested);\n } else {\n result[newKey] = value;\n }\n }\n\n return result;\n}\n\n/** Convert a snake_case or kebab-case segment to camelCase. */\nfunction toCamelSegment(s: string): string {\n return s.replace(/[-_]([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n\n/** Convert a snake_case or kebab-case segment to PascalCase for joining. */\nfunction toPascalSegment(s: string): string {\n const camel = toCamelSegment(s);\n return camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n\n/**\n * Detect whether a top-level payload is \"structured\" (pipeline-app style\n * with nested `company` / `person` object keys) or \"flat\" (contact-form style).\n */\nexport type PayloadStructure =\n | { type: 'structured'; company: FlatRecord | null; person: FlatRecord | null; extra: FlatRecord }\n | { type: 'flat'; data: FlatRecord };\n\nexport function detectStructure(raw: unknown): PayloadStructure {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { type: 'flat', data: {} };\n }\n\n const obj = raw as Record<string, unknown>;\n const hasObjectCompany =\n 'company' in obj && typeof obj['company'] === 'object' && obj['company'] !== null && !Array.isArray(obj['company']);\n const hasObjectPerson =\n 'person' in obj && typeof obj['person'] === 'object' && obj['person'] !== null && !Array.isArray(obj['person']);\n\n if (!hasObjectCompany && !hasObjectPerson) {\n return { type: 'flat', data: flatten(obj) };\n }\n\n // Keep company and person in their original nested form \u2014 they are already\n // in Twenty's native composite format (domainName, address, emails, phones, etc.)\n const company = hasObjectCompany ? (obj['company'] as FlatRecord) : null;\n const person = hasObjectPerson ? (obj['person'] as FlatRecord) : null;\n\n const extra: FlatRecord = {};\n for (const [k, v] of Object.entries(obj)) {\n if (k === 'company' || k === 'person') continue;\n const nested = flatten({ [k]: v });\n Object.assign(extra, nested);\n }\n\n return { type: 'structured', company, person, extra };\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok } from '../result';\nimport { detectStructure, flatten } from '../flattener';\n\nexport class FlattenStage implements PipelineStage {\n readonly name = 'flatten';\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n const structure = detectStructure(ctx.rawPayload);\n\n if (structure.type === 'structured') {\n // For structured payloads (pipeline app format), company and person are\n // already in Twenty's native format. Only normalize the extra fields\n // (pipeline-specific data: ratings, scores, analysis, etc.)\n const extraFlat = flatten(structure.extra ?? {});\n\n return ok({\n ...ctx,\n structuredCompany: structure.company ?? undefined,\n structuredPerson: structure.person ?? undefined,\n flat: extraFlat,\n });\n }\n\n // Flat format \u2014 already a top-level key\u2192value record\n return ok({ ...ctx, flat: structure.data });\n }\n}\n", "export type TwentyFieldType =\n | 'TEXT'\n | 'NUMBER'\n | 'BOOLEAN'\n | 'DATE'\n | 'DATE_TIME'\n | 'EMAILS'\n | 'PHONES'\n | 'LINKS'\n | 'FULL_NAME'\n | 'ADDRESS'\n | 'SELECT'\n | 'CURRENCY'\n | 'RATING'\n | 'RICH_TEXT'\n | 'RAW_JSON';\n\nexport type FieldAction = 'field' | 'note' | 'skip';\n\nexport type FieldMapEntry = {\n canonicalName: string;\n twentyType: TwentyFieldType;\n action: FieldAction;\n};\n\n/**\n * Normalise an incoming key to its lookup form:\n * camelCase \u2192 snake_case, hyphens/spaces \u2192 underscores, lowercase.\n * e.g. \"phoneNumber\" \u2192 \"phone_number\", \"E-Mail\" \u2192 \"e_mail\"\n */\nexport function normaliseKey(key: string): string {\n return key\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/[-\\s.]/g, '_')\n .replace(/_{2,}/g, '_');\n}\n\nexport const FIELD_MAP: Record<string, FieldMapEntry> = {\n // \u2500\u2500 Phone \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n phone: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n phone_number: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n tel: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n telephone: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n mobile: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n mobile_number: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n cell: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n cell_phone: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n contact_phone: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n phone1: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n primary_phone: { canonicalName: 'phone', twentyType: 'PHONES', action: 'field' },\n\n // \u2500\u2500 Email \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n email: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n email_address: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n e_mail: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n contact_email: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n email1: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n user_email: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n primary_email: { canonicalName: 'email', twentyType: 'EMAILS', action: 'field' },\n\n // \u2500\u2500 First name \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n first_name: { canonicalName: 'firstName', twentyType: 'TEXT', action: 'field' },\n fname: { canonicalName: 'firstName', twentyType: 'TEXT', action: 'field' },\n given_name: { canonicalName: 'firstName', twentyType: 'TEXT', action: 'field' },\n forename: { canonicalName: 'firstName', twentyType: 'TEXT', action: 'field' },\n\n // \u2500\u2500 Last name \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n last_name: { canonicalName: 'lastName', twentyType: 'TEXT', action: 'field' },\n lname: { canonicalName: 'lastName', twentyType: 'TEXT', action: 'field' },\n surname: { canonicalName: 'lastName', twentyType: 'TEXT', action: 'field' },\n family_name: { canonicalName: 'lastName', twentyType: 'TEXT', action: 'field' },\n\n // \u2500\u2500 Full name (will be split on ingest) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n name: { canonicalName: 'fullName', twentyType: 'FULL_NAME', action: 'field' },\n full_name: { canonicalName: 'fullName', twentyType: 'FULL_NAME', action: 'field' },\n contact_name: { canonicalName: 'fullName', twentyType: 'FULL_NAME', action: 'field' },\n your_name: { canonicalName: 'fullName', twentyType: 'FULL_NAME', action: 'field' },\n\n // \u2500\u2500 Company \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n company: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n company_name: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n business: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n business_name: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n organization: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n organisation: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n employer: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n firm: { canonicalName: 'companyName', twentyType: 'TEXT', action: 'field' },\n\n // \u2500\u2500 Website / Domain \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n website: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n website_url: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n url: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n domain: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n homepage: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n web: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n site: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n site_url: { canonicalName: 'domainName', twentyType: 'LINKS', action: 'field' },\n\n // \u2500\u2500 Address \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n street: { canonicalName: 'addressStreet1', twentyType: 'TEXT', action: 'field' },\n street_address: { canonicalName: 'addressStreet1', twentyType: 'TEXT', action: 'field' },\n address_line_1: { canonicalName: 'addressStreet1', twentyType: 'TEXT', action: 'field' },\n address1: { canonicalName: 'addressStreet1', twentyType: 'TEXT', action: 'field' },\n address_line_2: { canonicalName: 'addressStreet2', twentyType: 'TEXT', action: 'field' },\n address2: { canonicalName: 'addressStreet2', twentyType: 'TEXT', action: 'field' },\n city: { canonicalName: 'addressCity', twentyType: 'TEXT', action: 'field' },\n address_city: { canonicalName: 'addressCity', twentyType: 'TEXT', action: 'field' },\n town: { canonicalName: 'addressCity', twentyType: 'TEXT', action: 'field' },\n state: { canonicalName: 'addressState', twentyType: 'TEXT', action: 'field' },\n province: { canonicalName: 'addressState', twentyType: 'TEXT', action: 'field' },\n region: { canonicalName: 'addressState', twentyType: 'TEXT', action: 'field' },\n address_state: { canonicalName: 'addressState', twentyType: 'TEXT', action: 'field' },\n zip: { canonicalName: 'addressPostcode', twentyType: 'TEXT', action: 'field' },\n zip_code: { canonicalName: 'addressPostcode', twentyType: 'TEXT', action: 'field' },\n postal_code: { canonicalName: 'addressPostcode', twentyType: 'TEXT', action: 'field' },\n postcode: { canonicalName: 'addressPostcode', twentyType: 'TEXT', action: 'field' },\n country: { canonicalName: 'addressCountry', twentyType: 'TEXT', action: 'field' },\n address_country: { canonicalName: 'addressCountry', twentyType: 'TEXT', action: 'field' },\n\n // \u2500\u2500 Social \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n linkedin: { canonicalName: 'linkedInLink', twentyType: 'LINKS', action: 'field' },\n linkedin_url: { canonicalName: 'linkedInLink', twentyType: 'LINKS', action: 'field' },\n linkedin_profile: { canonicalName: 'linkedInLink', twentyType: 'LINKS', action: 'field' },\n twitter: { canonicalName: 'xLink', twentyType: 'LINKS', action: 'field' },\n twitter_url: { canonicalName: 'xLink', twentyType: 'LINKS', action: 'field' },\n x_profile: { canonicalName: 'xLink', twentyType: 'LINKS', action: 'field' },\n\n // \u2500\u2500 Pipeline-specific (Google / business intel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n google_places_url: { canonicalName: 'extGooglePlacesUrl', twentyType: 'LINKS', action: 'field' },\n places_url: { canonicalName: 'extGooglePlacesUrl', twentyType: 'LINKS', action: 'field' },\n google_maps_url: { canonicalName: 'extGooglePlacesUrl', twentyType: 'LINKS', action: 'field' },\n maps_url: { canonicalName: 'extGooglePlacesUrl', twentyType: 'LINKS', action: 'field' },\n rating: { canonicalName: 'extGoogleRating', twentyType: 'NUMBER', action: 'field' },\n google_rating: { canonicalName: 'extGoogleRating', twentyType: 'NUMBER', action: 'field' },\n stars: { canonicalName: 'extGoogleRating', twentyType: 'NUMBER', action: 'field' },\n review_count: { canonicalName: 'extReviewCount', twentyType: 'NUMBER', action: 'field' },\n reviews_count: { canonicalName: 'extReviewCount', twentyType: 'NUMBER', action: 'field' },\n total_reviews: { canonicalName: 'extReviewCount', twentyType: 'NUMBER', action: 'field' },\n num_reviews: { canonicalName: 'extReviewCount', twentyType: 'NUMBER', action: 'field' },\n marketing_score: { canonicalName: 'extMarketingScore', twentyType: 'NUMBER', action: 'field' },\n lead_score: { canonicalName: 'extLeadScore', twentyType: 'NUMBER', action: 'field' },\n analyzed_url: { canonicalName: 'extAnalyzedUrl', twentyType: 'LINKS', action: 'field' },\n\n // \u2500\u2500 UTM \u2014 always captured in note \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n utm_source: { canonicalName: 'utm_source', twentyType: 'TEXT', action: 'note' },\n utm_medium: { canonicalName: 'utm_medium', twentyType: 'TEXT', action: 'note' },\n utm_campaign: { canonicalName: 'utm_campaign', twentyType: 'TEXT', action: 'note' },\n utm_content: { canonicalName: 'utm_content', twentyType: 'TEXT', action: 'note' },\n utm_term: { canonicalName: 'utm_term', twentyType: 'TEXT', action: 'note' },\n ref: { canonicalName: 'ref', twentyType: 'TEXT', action: 'note' },\n referrer: { canonicalName: 'referrer', twentyType: 'TEXT', action: 'note' },\n source_page: { canonicalName: 'source_page', twentyType: 'TEXT', action: 'note' },\n landing_page: { canonicalName: 'landing_page', twentyType: 'TEXT', action: 'note' },\n\n // \u2500\u2500 Known note fields \u2014 always prose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n message: { canonicalName: 'message', twentyType: 'RICH_TEXT', action: 'note' },\n description: { canonicalName: 'description', twentyType: 'RICH_TEXT', action: 'note' },\n analysis: { canonicalName: 'analysis', twentyType: 'RICH_TEXT', action: 'note' },\n notes: { canonicalName: 'notes', twentyType: 'RICH_TEXT', action: 'note' },\n comments: { canonicalName: 'comments', twentyType: 'RICH_TEXT', action: 'note' },\n summary: { canonicalName: 'summary', twentyType: 'RICH_TEXT', action: 'note' },\n inquiry: { canonicalName: 'inquiry', twentyType: 'RICH_TEXT', action: 'note' },\n body: { canonicalName: 'body', twentyType: 'RICH_TEXT', action: 'note' },\n details: { canonicalName: 'details', twentyType: 'RICH_TEXT', action: 'note' },\n content: { canonicalName: 'content', twentyType: 'RICH_TEXT', action: 'note' },\n text: { canonicalName: 'text', twentyType: 'RICH_TEXT', action: 'note' },\n feedback: { canonicalName: 'feedback', twentyType: 'RICH_TEXT', action: 'note' },\n about: { canonicalName: 'about', twentyType: 'RICH_TEXT', action: 'note' },\n additional_info: { canonicalName: 'additional_info', twentyType: 'RICH_TEXT', action: 'note' },\n\n // \u2500\u2500 System / internal \u2014 skip entirely \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n _id: { canonicalName: '_id', twentyType: 'TEXT', action: 'skip' },\n __v: { canonicalName: '__v', twentyType: 'TEXT', action: 'skip' },\n created_at: { canonicalName: 'createdAt', twentyType: 'DATE_TIME', action: 'skip' },\n updated_at: { canonicalName: 'updatedAt', twentyType: 'DATE_TIME', action: 'skip' },\n form_id: { canonicalName: 'form_id', twentyType: 'TEXT', action: 'skip' },\n submission_id: { canonicalName: 'submission_id', twentyType: 'TEXT', action: 'skip' },\n token: { canonicalName: 'token', twentyType: 'TEXT', action: 'skip' },\n password: { canonicalName: 'password', twentyType: 'TEXT', action: 'skip' },\n secret: { canonicalName: 'secret', twentyType: 'TEXT', action: 'skip' },\n} as const;\n", "import type { TwentyFieldType } from '../constants/field-map';\n\nconst URL_RE = /^https?:\\/\\/[^\\s/$.?#].[^\\s]*$/i;\nconst EMAIL_RE = /^[^@\\s]+@[^@\\s]+\\.[^@\\s]{2,}$/;\nconst PHONE_RE = /^[+]?[(]?[0-9]{1,4}[)]?[-\\s.]?[(]?[0-9]{1,4}[)]?[-\\s.]?[0-9]{3,9}([-\\s.][0-9]{1,9})?$/;\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?)?)?$/;\n\nexport function detectType(value: unknown): TwentyFieldType {\n if (value === null || value === undefined) return 'TEXT';\n if (typeof value === 'boolean') return 'BOOLEAN';\n if (typeof value === 'number') return 'NUMBER';\n\n if (typeof value === 'string') {\n const s = value.trim();\n if (!s) return 'TEXT';\n if (URL_RE.test(s)) return 'LINKS';\n if (EMAIL_RE.test(s)) return 'EMAILS';\n if (PHONE_RE.test(s)) return 'PHONES';\n if (DATE_RE.test(s)) return 'DATE_TIME';\n if (!isNaN(Number(s)) && s !== '') return 'NUMBER';\n return 'TEXT';\n }\n\n if (Array.isArray(value)) return 'RAW_JSON';\n if (typeof value === 'object') return 'RAW_JSON';\n\n return 'TEXT';\n}\n", "const PROSE_KEYS = new Set([\n 'message', 'description', 'analysis', 'notes', 'comments',\n 'summary', 'inquiry', 'body', 'details', 'content', 'text',\n 'feedback', 'about', 'additional_info', 'info', 'context',\n 'requirements', 'goals', 'challenges', 'question', 'request',\n]);\n\nconst NOTE_KEY_PREFIXES = ['utm_', 'ga_', 'fb_', 'gclid', 'msclkid'];\n\nconst SENTENCE_RE = /[.!?]\\s+[A-Z]/g;\nconst LINE_BREAK_RE = /\\n|\\r/;\n\nexport type Classification = 'field' | 'note' | 'skip';\n\n/**\n * Decide whether a key+value pair belongs in a CRM field or the overflow note.\n *\n * Rules (in priority order):\n * 1. Arrays / objects \u2192 note (can't be a single field)\n * 2. Known note key names \u2192 note\n * 3. UTM / tracking prefix \u2192 note\n * 4. Contains line breaks \u2192 note\n * 5. Looks like prose (2+ sentences) \u2192 note\n * 6. Everything else \u2192 field\n */\nexport function classify(key: string, value: unknown): Classification {\n const normKey = key.toLowerCase().replace(/[-\\s]/g, '_');\n\n if (Array.isArray(value)) return 'note';\n if (value !== null && typeof value === 'object') return 'note';\n\n if (PROSE_KEYS.has(normKey)) return 'note';\n if (NOTE_KEY_PREFIXES.some((p) => normKey.startsWith(p))) return 'note';\n\n if (typeof value === 'string') {\n if (LINE_BREAK_RE.test(value)) return 'note';\n const matches = value.match(SENTENCE_RE);\n if (matches && matches.length >= 2) return 'note';\n }\n\n return 'field';\n}\n", "import { FIELD_MAP, normaliseKey, type FieldAction, type TwentyFieldType } from '../constants/field-map';\nimport { detectType } from './type-detector';\nimport { classify } from './classifier';\n\nexport type NormalizedField = {\n originalKey: string;\n canonicalName: string;\n twentyType: TwentyFieldType;\n action: FieldAction;\n value: unknown;\n source: 'builtin' | 'rule' | 'passthrough';\n};\n\nexport type DatabaseRule = {\n inputPattern: string;\n canonicalName: string;\n fieldType: string;\n action: FieldAction;\n priority: number;\n};\n\n/**\n * Normalize a flat record of incoming key\u2192value pairs into typed,\n * canonically-named fields ready for classification and schema sync.\n *\n * Strategy priority:\n * 1. Built-in field map (highest \u2014 covers known common variations)\n * 2. Database rules (user-configured per source or global)\n * 3. Passthrough (unknown fields get ext_ prefix + auto type detection)\n */\nexport function normalizeFields(\n flat: Record<string, unknown>,\n rules: DatabaseRule[] = [],\n): NormalizedField[] {\n const sorted = [...rules].sort((a, b) => b.priority - a.priority);\n\n return Object.entries(flat).map(([key, value]) =>\n normalizeField(key, value, sorted),\n );\n}\n\nfunction normalizeField(\n key: string,\n value: unknown,\n rules: DatabaseRule[],\n): NormalizedField {\n const lookupKey = normaliseKey(key);\n\n // 1. Built-in map\n const builtIn = FIELD_MAP[lookupKey];\n if (builtIn) {\n return {\n originalKey: key,\n canonicalName: builtIn.canonicalName,\n twentyType: builtIn.twentyType,\n action: builtIn.action,\n value,\n source: 'builtin',\n };\n }\n\n // 2. Database rules (exact match or regex)\n for (const rule of rules) {\n let matches = false;\n try {\n matches =\n rule.inputPattern === key ||\n rule.inputPattern === lookupKey ||\n new RegExp(rule.inputPattern, 'i').test(key);\n } catch {\n matches = rule.inputPattern === key;\n }\n\n if (matches) {\n return {\n originalKey: key,\n canonicalName: rule.canonicalName,\n twentyType: rule.fieldType as TwentyFieldType,\n action: rule.action,\n value,\n source: 'rule',\n };\n }\n }\n\n // 3. Passthrough \u2014 auto-detect type, classify, ext_ prefix\n const detectedType = detectType(value);\n const classification = classify(key, value);\n const canonicalName =\n classification === 'field'\n ? toExtFieldName(key)\n : lookupKey;\n\n return {\n originalKey: key,\n canonicalName,\n twentyType: detectedType,\n action: classification === 'field' ? 'field' : classification,\n value,\n source: 'passthrough',\n };\n}\n\n/** Convert any key to a valid Twenty custom field name: extPascalCase */\nfunction toExtFieldName(key: string): string {\n const cleaned = key\n .replace(/[-_\\s]+([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase())\n .replace(/[^a-zA-Z0-9]/g, '');\n return 'ext' + cleaned.charAt(0).toUpperCase() + cleaned.slice(1);\n}\n\n/**\n * Split normalised fields into those that become CRM fields\n * and those that go into the overflow note.\n */\nexport function partition(fields: NormalizedField[]): {\n crmFields: NormalizedField[];\n noteFields: NormalizedField[];\n skipped: NormalizedField[];\n} {\n const crmFields: NormalizedField[] = [];\n const noteFields: NormalizedField[] = [];\n const skipped: NormalizedField[] = [];\n\n for (const f of fields) {\n if (f.action === 'skip') skipped.push(f);\n else if (f.action === 'note') noteFields.push(f);\n else crmFields.push(f);\n }\n\n return { crmFields, noteFields, skipped };\n}\n\n/**\n * Assemble individual canonical field names into Twenty's composite\n * field structures (FULL_NAME, PHONES, EMAILS, ADDRESS, LINKS).\n */\nexport function assembleComposites(crmFields: NormalizedField[]): {\n assembled: Record<string, unknown>;\n remainder: NormalizedField[];\n} {\n const assembled: Record<string, unknown> = {};\n const consumed = new Set<string>();\n\n // \u2500\u2500 FULL_NAME \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const firstName = crmFields.find((f) => f.canonicalName === 'firstName');\n const lastName = crmFields.find((f) => f.canonicalName === 'lastName');\n const fullName = crmFields.find((f) => f.canonicalName === 'fullName');\n\n if (fullName && !firstName && !lastName) {\n const parts = splitFullName(String(fullName.value ?? ''));\n assembled['name'] = { firstName: parts[0], lastName: parts[1] };\n consumed.add('fullName');\n } else if (firstName || lastName) {\n assembled['name'] = {\n firstName: String(firstName?.value ?? ''),\n lastName: String(lastName?.value ?? ''),\n };\n if (firstName) consumed.add('firstName');\n if (lastName) consumed.add('lastName');\n }\n\n // \u2500\u2500 EMAILS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const email = crmFields.find((f) => f.canonicalName === 'email');\n if (email) {\n assembled['emails'] = { primaryEmail: String(email.value ?? '') };\n consumed.add('email');\n }\n\n // \u2500\u2500 PHONES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const phone = crmFields.find((f) => f.canonicalName === 'phone');\n if (phone) {\n const raw = String(phone.value ?? '');\n assembled['phones'] = {\n primaryPhoneNumber: raw.replace(/\\D/g, '').slice(-10),\n primaryPhoneCountryCode: 'US',\n primaryPhoneCallingCode: '+1',\n };\n consumed.add('phone');\n }\n\n // \u2500\u2500 LINKS (domainName / website) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const domain = crmFields.find((f) => f.canonicalName === 'domainName');\n if (domain) {\n assembled['domainName'] = {\n primaryLinkUrl: String(domain.value ?? ''),\n primaryLinkLabel: '',\n };\n consumed.add('domainName');\n }\n\n // \u2500\u2500 ADDRESS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const addressFields: Array<[string, string]> = [\n ['addressStreet1', 'addressStreet1'],\n ['addressStreet2', 'addressStreet2'],\n ['addressCity', 'addressCity'],\n ['addressState', 'addressState'],\n ['addressPostcode', 'addressPostcode'],\n ['addressCountry', 'addressCountry'],\n ];\n const addressParts: Record<string, unknown> = {};\n for (const [canonical, outKey] of addressFields) {\n const f = crmFields.find((x) => x.canonicalName === canonical);\n if (f) {\n addressParts[outKey] = f.value;\n consumed.add(canonical);\n }\n }\n if (Object.keys(addressParts).length > 0) {\n assembled['address'] = addressParts;\n }\n\n const remainder = crmFields.filter((f) => !consumed.has(f.canonicalName));\n return { assembled, remainder };\n}\n\nfunction splitFullName(fullName: string): [string, string] {\n const parts = fullName.trim().split(/\\s+/);\n if (parts.length === 0) return ['', ''];\n if (parts.length === 1) return [parts[0] ?? '', ''];\n const lastName = parts.pop() ?? '';\n return [parts.join(' '), lastName];\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok, err, ErrorCode } from '../result';\nimport { normalizeFields, partition, assembleComposites, type DatabaseRule } from '../normalizer';\nimport type { CoreApiClient } from 'twenty-client-sdk/core';\n\nexport class NormalizeStage implements PipelineStage {\n readonly name = 'normalize';\n\n constructor(private readonly client: CoreApiClient) {}\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n if (!ctx.flat) {\n return err(ErrorCode.INTERNAL_ERROR, 'FlattenStage must run before NormalizeStage');\n }\n\n const rules = await this.loadRules(ctx.source?.id);\n const normalized = normalizeFields(ctx.flat, rules);\n const { crmFields, noteFields } = partition(normalized);\n\n return ok({\n ...ctx,\n normalizedFields: normalized,\n crmFields,\n noteFields,\n });\n }\n\n private async loadRules(sourceId?: string): Promise<DatabaseRule[]> {\n try {\n const filter = sourceId\n ? { or: [{ intakeSource: { id: { eq: sourceId } } }, { intakeSource: { id: { is: 'NULL' } } }] }\n : { intakeSource: { id: { is: 'NULL' } } };\n\n const result = await this.client.query({\n intakeFieldRules: {\n __args: {\n filter: { and: [filter, { isActive: { eq: true } }] },\n orderBy: { priority: 'DescNullsLast' },\n },\n edges: {\n node: {\n inputPattern: true,\n canonicalName: true,\n fieldType: true,\n priority: true,\n },\n },\n },\n });\n\n return (result.intakeFieldRules?.edges ?? []).map((e: { node: DatabaseRule }) => e.node);\n } catch {\n return [];\n }\n }\n}\n", "/**\n * Minimal REST client for Twenty's Core and Metadata APIs.\n * Uses raw fetch so it works with dynamically created custom fields\n * that the typed SDK client doesn't know about at build time.\n */\n\nconst apiUrl = () => process.env['TWENTY_API_URL'] ?? '';\nconst token = () => process.env['TWENTY_APP_ACCESS_TOKEN'] ?? '';\n\nasync function request<T>(\n base: string,\n method: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const res = await fetch(`${base}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token()}`,\n 'Content-Type': 'application/json',\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const text = await res.text();\n if (!res.ok) {\n throw new Error(`${method} ${path} \u2192 ${res.status}: ${text}`);\n }\n return JSON.parse(text) as T;\n}\n\nexport const coreApi = {\n get: <T>(path: string) => request<T>(`${apiUrl()}/rest`, 'GET', path),\n post: <T>(path: string, body: unknown) => request<T>(`${apiUrl()}/rest`, 'POST', path, body),\n patch: <T>(path: string, body: unknown) => request<T>(`${apiUrl()}/rest`, 'PATCH', path, body),\n};\n\nexport const metaApi = {\n get: <T>(path: string) => request<T>(`${apiUrl()}/rest/metadata`, 'GET', path),\n post: <T>(path: string, body: unknown) => request<T>(`${apiUrl()}/rest/metadata`, 'POST', path, body),\n};\n\n/** Run a raw GraphQL query against the /graphql endpoint. */\nexport async function gql<T = unknown>(\n query: string,\n variables?: Record<string, unknown>,\n): Promise<T> {\n return request<T>(`${apiUrl()}`, 'POST', '/graphql', { query, variables });\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok } from '../result';\nimport { metaApi } from '../rest-client';\n\nconst STANDARD_FIELDS = new Set([\n 'name', 'emails', 'phones', 'domainName', 'address',\n 'linkedInLink', 'xLink', 'companyName', 'firstName', 'lastName', 'fullName',\n 'jobTitle', 'city', 'employees', 'annualRecurringRevenue', 'idealCustomerProfile',\n]);\n\nexport class SyncSchemaStage implements PipelineStage {\n readonly name = 'sync-schema';\n\n private objectCache = new Map<string, { id: string; fields: Set<string>; at: number }>();\n private readonly TTL = 5 * 60 * 1000;\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n if (!ctx.crmFields || ctx.crmFields.length === 0) return ok(ctx);\n\n // Respect global field creation toggle\n if (process.env['INTAKE_FIELD_CREATION_ENABLED'] === 'false') {\n ctx.warnings.push('Field creation disabled by INTAKE_FIELD_CREATION_ENABLED setting \u2014 ext fields skipped');\n return ok(ctx);\n }\n\n const targets = this.targetObjects(ctx);\n let fieldsCreated = 0;\n let fieldsMatched = 0;\n\n for (const objectName of targets) {\n const meta = await this.getObjectMeta(objectName);\n if (!meta) continue;\n\n const maxExt = parseInt(process.env['INTAKE_MAX_EXT_FIELDS'] ?? '50', 10);\n const currentExtCount = [...meta.fields].filter(f => /^ext[A-Z]/.test(f)).length;\n\n for (const field of ctx.crmFields) {\n if (STANDARD_FIELDS.has(field.canonicalName)) { fieldsMatched++; continue; }\n if (!/^ext[A-Z]/.test(field.canonicalName)) { fieldsMatched++; continue; }\n\n if (meta.fields.has(field.canonicalName)) { fieldsMatched++; continue; }\n\n if (currentExtCount >= maxExt) {\n ctx.warnings.push(`ext field limit (${maxExt}) reached for ${objectName} \u2014 \"${field.canonicalName}\" goes to note`);\n continue;\n }\n\n const created = await this.createField(meta.id, field.canonicalName, field.twentyType);\n if (created) {\n meta.fields.add(field.canonicalName);\n this.objectCache.get(objectName)?.fields.add(field.canonicalName);\n fieldsCreated++;\n } else {\n ctx.warnings.push(`Could not create field \"${field.canonicalName}\" on ${objectName} \u2014 will go to note`);\n }\n }\n }\n\n return ok({ ...ctx, fieldsCreated, fieldsMatched });\n }\n\n private targetObjects(ctx: PipelineContext): string[] {\n const t = ctx.source?.targetObject ?? 'AUTO';\n if (t === 'PERSON') return ['person'];\n if (t === 'COMPANY') return ['company'];\n\n // For structured payloads (pipeline app), extras are company-level data\n if (ctx.structuredCompany) return ['company'];\n\n // For flat payloads, extras belong on the primary record (person if available)\n const hasPersonData = ctx.crmFields?.some(f =>\n ['firstName', 'lastName', 'email', 'phone', 'fullName', 'emails', 'phones', 'name'].includes(f.canonicalName));\n const hasCompanyData = ctx.crmFields?.some(f =>\n ['companyName', 'domainName'].includes(f.canonicalName));\n\n const out: string[] = [];\n if (hasPersonData) out.push('person');\n else if (hasCompanyData) out.push('company');\n return out.length > 0 ? out : ['person'];\n }\n\n private async getObjectMeta(objectName: string): Promise<{ id: string; fields: Set<string> } | null> {\n const cached = this.objectCache.get(objectName);\n if (cached && Date.now() - cached.at < this.TTL) return cached;\n\n try {\n // Metadata API returns all objects \u2014 filter client-side by nameSingular\n const res = await metaApi.get<Array<{ id: string; nameSingular: string; fields: Array<{ name: string }> }>>('/objects');\n const objects = Array.isArray(res) ? res : (res as { data: typeof res }).data ?? [];\n const node = (objects as Array<{ id: string; nameSingular: string; fields: Array<{ name: string }> }>)\n .find(o => o.nameSingular === objectName);\n if (!node) return null;\n const fields = new Set<string>((node.fields ?? []).map((f: { name: string }) => f.name));\n const entry = { id: node.id, fields, at: Date.now() };\n this.objectCache.set(objectName, entry);\n return entry;\n } catch {\n return null;\n }\n }\n\n private async createField(objectMetadataId: string, name: string, type: string): Promise<boolean> {\n try {\n await metaApi.post('/fields', {\n objectMetadataId,\n name,\n label: toLabel(name),\n type,\n description: 'Auto-created by Intake',\n icon: 'IconPlug',\n });\n return true;\n } catch {\n return false;\n }\n }\n}\n\nfunction toLabel(name: string): string {\n return name.replace(/^ext_/, '').replace(/_/g, ' ')\n .replace(/([A-Z])/g, ' $1').split(' ')\n .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join(' ').trim();\n}\n", "type NoteField = { label: string; value: unknown };\n\n/**\n * Format the overflow data as a readable markdown note body.\n *\n * Output example:\n * **Source:** contact-form\n * **Message:** Need a new website, SEO help\n * **UTM Source:** google\n * **Marketing Score:** 72\n */\nexport function formatNote(\n sourceName: string,\n fields: Record<string, unknown>,\n): string {\n const lines: string[] = [];\n\n lines.push(`**Source:** ${sourceName}`);\n\n const entries = buildEntries(fields);\n\n for (const { label, value } of entries) {\n const formatted = formatValue(value);\n if (formatted !== null) {\n lines.push(`**${label}:** ${formatted}`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction buildEntries(fields: Record<string, unknown>): NoteField[] {\n return Object.entries(fields).map(([key, value]) => ({\n label: toLabel(key),\n value,\n }));\n}\n\nfunction toLabel(key: string): string {\n return key\n .replace(/^ext_/, '')\n .replace(/_/g, ' ')\n .replace(/([A-Z])/g, ' $1')\n .split(' ')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join(' ')\n .trim();\n}\n\nfunction formatValue(value: unknown): string | null {\n if (value === null || value === undefined || value === '') return null;\n if (Array.isArray(value)) return value.join(', ');\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok, err, ErrorCode } from '../result';\nimport { assembleComposites } from '../normalizer';\nimport { formatNote } from '../note-formatter';\nimport { coreApi, gql } from '../rest-client';\n\nexport class UpsertRecordStage implements PipelineStage {\n readonly name = 'upsert-record';\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n if (!ctx.crmFields) return err(ErrorCode.INTERNAL_ERROR, 'No CRM fields to upsert');\n\n // Strip internal __company_ routing keys from crmFields before assembly\n const cleanFields = ctx.crmFields.filter(f => !f.originalKey.startsWith('__'));\n const { assembled, remainder } = assembleComposites(cleanFields);\n for (const f of remainder) assembled[f.canonicalName] = f.value;\n\n // For structured payloads, company/person objects are already in Twenty format\n const structuredCompany = ctx.structuredCompany;\n const structuredPerson = ctx.structuredPerson;\n\n const rawCompanyName = (structuredCompany?.['name'] as string | undefined)\n ?? (assembled['companyName'] as string | undefined);\n\n // Build a map of ext field canonical names \u2192 their Twenty type for value formatting\n const extFieldTypes = new Map<string, string>();\n for (const f of (ctx.crmFields ?? [])) {\n if (/^ext[A-Z]/.test(f.canonicalName)) extFieldTypes.set(f.canonicalName, f.twentyType);\n }\n\n try {\n let companyId: string | undefined;\n let personId: string | undefined;\n\n // \u2500\u2500 1. Upsert Company \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const needsCompany = rawCompanyName || ctx.source?.targetObject === 'COMPANY';\n if (needsCompany) {\n companyId = await this.upsertCompany(assembled, structuredCompany ?? {}, rawCompanyName, extFieldTypes, ctx);\n }\n\n // \u2500\u2500 2. Upsert Person \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const personData = structuredPerson ?? assembled;\n const hasPersonData = personData['emails'] || personData['name'] || assembled['emails'] || assembled['name'];\n if (hasPersonData || ctx.source?.targetObject === 'PERSON') {\n personId = await this.upsertPerson(assembled, structuredPerson, companyId, extFieldTypes, ctx);\n }\n\n // \u2500\u2500 3. Create Opportunity \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let opportunityId: string | undefined;\n if (ctx.source?.createOpportunity && (personId || companyId)) {\n opportunityId = await this.createOpportunity(assembled, personId, companyId, ctx);\n }\n\n // \u2500\u2500 4. Create Note + link targets \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let noteId: string | undefined;\n const noteFields = ctx.noteFields ?? [];\n if (noteFields.length > 0) {\n const overflow: Record<string, unknown> = {};\n for (const f of noteFields) overflow[f.canonicalName] = f.value;\n noteId = await this.createNote(overflow, personId, companyId, ctx);\n }\n\n return ok({\n ...ctx,\n personId,\n companyId,\n opportunityId,\n noteId,\n recordType: personId ? 'PERSON' : 'COMPANY',\n });\n } catch (e) {\n return err(ErrorCode.RECORD_UPSERT_FAILED, `Failed to upsert record: ${String(e)}`);\n }\n }\n\n private async upsertCompany(\n assembled: Record<string, unknown>,\n structuredCompany: Record<string, unknown>,\n companyName: string | undefined,\n extFieldTypes: Map<string, string>,\n ctx: PipelineContext,\n ): Promise<string> {\n // Standard fields only for the initial create/update\n const standard: Record<string, unknown> = { ...structuredCompany };\n if (companyName && !standard['name']) standard['name'] = companyName;\n if (!standard['domainName'] && assembled['domainName']) standard['domainName'] = assembled['domainName'];\n if (!standard['address'] && assembled['address']) standard['address'] = assembled['address'];\n\n // Dedup by domain\n const domain = (standard['domainName'] as Record<string, unknown> | undefined)?.['primaryLinkUrl'] as string | undefined;\n let companyId: string | undefined;\n if (domain) {\n const host = extractHost(domain);\n try {\n const found = await coreApi.get<{ data: { companies: { edges: Array<{ node: { id: string } }> } } }>(\n `/companies?filter=domainName.primaryLinkUrl[like]:%25${encodeURIComponent(host)}%25&first=1`,\n );\n const existing = found.data?.companies?.edges?.[0]?.node;\n if (existing) {\n await coreApi.patch(`/companies/${existing.id}`, standard);\n companyId = existing.id;\n }\n } catch { /* proceed to create */ }\n }\n\n if (!companyId) {\n try {\n const created = await coreApi.post<{ data: { createCompany: { id: string } } }>('/companies', standard);\n companyId = created.data.createCompany.id;\n } catch (e) {\n // Duplicate \u2014 find by name via GraphQL\n if (String(e).toLowerCase().includes('duplicate') && standard['name']) {\n try {\n const found = await gql<{ data: { companies: { edges: Array<{ node: { id: string } }> } } }>(\n `query FindCompany($name: String!) { companies(filter: { name: { eq: $name } }) { edges { node { id } } } }`,\n { name: String(standard['name']) },\n );\n companyId = found.data?.companies?.edges?.[0]?.node?.id;\n } catch { /* ignore */ }\n }\n if (!companyId) throw e;\n }\n }\n\n // Step 2: PATCH ext fields separately (non-fatal)\n if (Object.keys(structuredCompany).length > 0) {\n const extData: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(assembled)) {\n if (/^ext[A-Z]/.test(k)) extData[k] = formatExtValue(v, extFieldTypes.get(k));\n }\n if (Object.keys(extData).length > 0) {\n await coreApi.patch(`/companies/${companyId}`, extData).catch((e: Error) => {\n ctx.warnings.push(`Could not set ext fields on company: ${e.message.slice(0, 120)}`);\n });\n }\n }\n\n return companyId;\n }\n\n private async upsertPerson(\n assembled: Record<string, unknown>,\n structuredPerson: Record<string, unknown> | undefined,\n companyId: string | undefined,\n extFieldTypes: Map<string, string>,\n ctx: PipelineContext,\n ): Promise<string> {\n // Standard fields only for initial create/update\n const standard: Record<string, unknown> = structuredPerson ? { ...structuredPerson } : {};\n if (!standard['name'] && assembled['name']) standard['name'] = assembled['name'];\n if (!standard['emails'] && assembled['emails']) standard['emails'] = assembled['emails'];\n if (!standard['phones'] && assembled['phones']) standard['phones'] = assembled['phones'];\n if (companyId) standard['companyId'] = companyId;\n\n // Dedup by email\n const emails = (standard['emails'] ?? assembled['emails']) as Record<string, string> | undefined;\n const email = emails?.['primaryEmail'];\n let personId: string | undefined;\n if (email) {\n try {\n const found = await coreApi.get<{ data: { people: { edges: Array<{ node: { id: string } }> } } }>(\n `/people?filter=emails.primaryEmail[eq]:${encodeURIComponent(email)}&first=1`,\n );\n const existing = found.data?.people?.edges?.[0]?.node;\n if (existing) {\n await coreApi.patch(`/people/${existing.id}`, standard);\n personId = existing.id;\n }\n } catch { /* proceed to create */ }\n }\n\n if (!personId) {\n const created = await coreApi.post<{ data: { createPerson: { id: string } } }>('/people', standard);\n personId = created.data.createPerson.id;\n }\n\n // Step 2: PATCH ext fields for flat/contact-form payloads (non-fatal)\n if (!structuredPerson) {\n const extData: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(assembled)) {\n if (/^ext[A-Z]/.test(k)) extData[k] = formatExtValue(v, extFieldTypes.get(k));\n }\n if (Object.keys(extData).length > 0) {\n await coreApi.patch(`/people/${personId}`, extData).catch((e: Error) => {\n ctx.warnings.push(`Could not set ext fields on person: ${e.message.slice(0, 120)}`);\n });\n }\n }\n\n return personId;\n }\n\n private async createOpportunity(\n assembled: Record<string, unknown>,\n personId: string | undefined,\n companyId: string | undefined,\n ctx: PipelineContext,\n ): Promise<string | undefined> {\n try {\n const name = buildOpportunityName(ctx, assembled);\n const stage = process.env['INTAKE_DEFAULT_OPP_STAGE'] ?? 'NEW';\n const data: Record<string, unknown> = { name, stage };\n if (personId) data['pointOfContactId'] = personId;\n if (companyId) data['companyId'] = companyId;\n\n const created = await coreApi.post<{ data: { createOpportunity: { id: string } } }>('/opportunities', data);\n return created.data.createOpportunity.id;\n } catch {\n ctx.warnings.push('Opportunity creation failed \u2014 record was still created');\n return undefined;\n }\n }\n\n private async createNote(\n overflow: Record<string, unknown>,\n personId: string | undefined,\n companyId: string | undefined,\n ctx: PipelineContext,\n ): Promise<string | undefined> {\n try {\n const markdown = formatNote(ctx.source?.name ?? ctx.sourceSlug, overflow);\n const appLabel = process.env['INTAKE_APP_LABEL'] ?? 'Intake';\n const created = await coreApi.post<{ data: { createNote: { id: string } } }>('/notes', {\n title: `${ctx.source?.name ?? appLabel} \u2014 Lead`,\n bodyV2: { markdown },\n });\n const noteId = created.data.createNote.id;\n\n if (personId) {\n await coreApi.post('/noteTargets', { noteId, personId }).catch(() => null);\n }\n if (companyId) {\n await coreApi.post('/noteTargets', { noteId, companyId }).catch(() => null);\n }\n return noteId;\n } catch {\n ctx.warnings.push('Note creation failed \u2014 record was still created');\n return undefined;\n }\n }\n}\n\nfunction buildOpportunityName(ctx: PipelineContext, assembled: Record<string, unknown>): string {\n const appLabel = process.env['INTAKE_APP_LABEL'] ?? 'Intake';\n const defaultTemplate = `{{source}} \u2014 {{firstName}} {{lastName}}`;\n const template = ctx.source?.opportunityNameTemplate ?? defaultTemplate;\n const name = assembled['name'] as Record<string, string> | undefined;\n return template\n .replace('{{source}}', ctx.source?.name ?? appLabel)\n .replace('{{firstName}}', name?.['firstName'] ?? '')\n .replace('{{lastName}}', name?.['lastName'] ?? '')\n .replace('{{email}}', (assembled['emails'] as Record<string, string> | undefined)?.['primaryEmail'] ?? '')\n .replace('{{company}}', assembled['companyName'] as string ?? '')\n .trim().replace(/\\s+/g, ' ').replace(/\\s*\u2014\\s*$/, '');\n}\n\nfunction extractHost(url: string): string {\n try { return new URL(url).hostname.replace(/^www\\./, ''); }\n catch { return url; }\n}\n\n/** Format a custom field value to match Twenty's expected composite types. */\nfunction formatExtValue(value: unknown, type?: string): unknown {\n if (type === 'LINKS' && typeof value === 'string') {\n return { primaryLinkUrl: value, primaryLinkLabel: '' };\n }\n return value;\n}\n", "import type { PipelineStage, PipelineContext } from '../pipeline';\nimport type { Result } from '../result';\nimport { ok } from '../result';\nimport { coreApi, gql } from '../rest-client';\n\nexport class WriteLogStage implements PipelineStage {\n readonly name = 'write-log';\n\n async execute(ctx: PipelineContext): Promise<Result<PipelineContext>> {\n try {\n const status = ctx.personId || ctx.companyId ? 'SUCCESS' : 'PARTIAL';\n\n await coreApi.post('/intakeLogs', {\n intakeSourceId: ctx.source?.id ?? null,\n status,\n payloadHash: ctx.payloadHash ?? '',\n rawPayload: JSON.stringify(ctx.rawPayload).slice(0, 65000), // cap at 65k chars\n recordId: ctx.personId ?? ctx.companyId ?? null,\n recordType: ctx.recordType ?? null,\n fieldsCreated: ctx.fieldsCreated,\n fieldsMatched: ctx.fieldsMatched,\n overflowCount: ctx.noteFields?.length ?? 0,\n processingMs: Date.now() - ctx.startedAt,\n processedAt: new Date().toISOString(),\n });\n } catch {\n ctx.warnings.push('Intake log write failed');\n }\n\n // Update source counters (non-fatal, fire-and-forget)\n if (ctx.source) {\n try {\n const current = await coreApi.get<{ data: { intakeSource: { totalIngested: number } } }>(\n `/intakeSources/${ctx.source.id}`,\n );\n const current_count = current.data?.intakeSource?.totalIngested ?? 0;\n await coreApi.patch(`/intakeSources/${ctx.source.id}`, {\n totalIngested: current_count + 1,\n lastIngestedAt: new Date().toISOString(),\n });\n } catch { /* non-fatal */ }\n }\n\n return ok(ctx);\n }\n}\n", "import type { CoreApiClient } from 'twenty-client-sdk/core';\nimport type { MetadataApiClient } from 'twenty-client-sdk/metadata';\nimport { Pipeline } from './pipeline';\nimport { LoadSourceStage } from './stages/load-source.stage';\nimport { VerifySignatureStage } from './stages/verify-signature.stage';\nimport { IdempotencyStage } from './stages/idempotency.stage';\nimport { FlattenStage } from './stages/flatten.stage';\nimport { NormalizeStage } from './stages/normalize.stage';\nimport { SyncSchemaStage } from './stages/sync-schema.stage';\nimport { UpsertRecordStage } from './stages/upsert-record.stage';\nimport { WriteLogStage } from './stages/write-log.stage';\n\n/**\n * Assemble the 8-stage ingestion pipeline.\n *\n * Stage order is intentional:\n * 1. LoadSource \u2014 resolve source config (needed by all later stages)\n * 2. VerifySignature \u2014 auth check (needs source's webhookSecret)\n * 3. Idempotency \u2014 dedup before any expensive work\n * 4. Flatten \u2014 normalise nested structure to flat record\n * 5. Normalize \u2014 map field names, detect types\n * 6. SyncSchema \u2014 create missing fields in Twenty via Metadata API\n * 7. UpsertRecord \u2014 create/update Person, Company, Opportunity, Note\n * 8. WriteLog \u2014 persist IntakeLog (always runs, even on partial)\n */\nexport function createPipeline(\n coreClient: CoreApiClient,\n metadataClient: MetadataApiClient,\n): Pipeline {\n return new Pipeline()\n .use(new LoadSourceStage(coreClient))\n .use(new VerifySignatureStage())\n .use(new IdempotencyStage(coreClient))\n .use(new FlattenStage())\n .use(new NormalizeStage(coreClient))\n .use(new SyncSchemaStage(metadataClient))\n .use(new UpsertRecordStage(coreClient))\n .use(new WriteLogStage(coreClient));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["toLabel"]
|
|
7
|
+
}
|