lakesync 0.1.5 → 0.1.8
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/dist/adapter.d.ts +199 -19
- package/dist/adapter.js +19 -3
- package/dist/analyst.js +2 -2
- package/dist/{base-poller-CBvhdvcj.d.ts → base-poller-Bj9kX9dv.d.ts} +76 -19
- package/dist/catalogue.d.ts +1 -1
- package/dist/catalogue.js +3 -3
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-PWGQ3PXE.js → chunk-JI4C4R5H.js} +280 -140
- package/dist/chunk-JI4C4R5H.js.map +1 -0
- package/dist/{chunk-L4ZL5JA7.js → chunk-KVSWLIJR.js} +2 -2
- package/dist/{chunk-7UBS6MFH.js → chunk-LDFFCG2K.js} +377 -247
- package/dist/chunk-LDFFCG2K.js.map +1 -0
- package/dist/{chunk-Z7FGLEQU.js → chunk-LPWXOYNS.js} +376 -287
- package/dist/chunk-LPWXOYNS.js.map +1 -0
- package/dist/{chunk-SZSGSTVZ.js → chunk-PYRS74YP.js} +15 -4
- package/dist/{chunk-SZSGSTVZ.js.map → chunk-PYRS74YP.js.map} +1 -1
- package/dist/{chunk-TVLTXHW6.js → chunk-QNITY4F6.js} +30 -7
- package/dist/{chunk-TVLTXHW6.js.map → chunk-QNITY4F6.js.map} +1 -1
- package/dist/{chunk-46CKACNC.js → chunk-SSICS5KI.js} +2 -2
- package/dist/{chunk-B3QEUG6E.js → chunk-TMLG32QV.js} +2 -2
- package/dist/client.d.ts +164 -13
- package/dist/client.js +310 -163
- package/dist/client.js.map +1 -1
- package/dist/compactor.d.ts +1 -1
- package/dist/compactor.js +4 -4
- package/dist/connector-jira.d.ts +2 -2
- package/dist/connector-jira.js +3 -3
- package/dist/connector-salesforce.d.ts +2 -2
- package/dist/connector-salesforce.js +3 -3
- package/dist/{coordinator-DN8D8C7W.d.ts → coordinator-NXy6tA0h.d.ts} +23 -16
- package/dist/{db-types-B6_JKQWK.d.ts → db-types-CfLMUBfW.d.ts} +1 -1
- package/dist/gateway-server.d.ts +158 -64
- package/dist/gateway-server.js +482 -4003
- package/dist/gateway-server.js.map +1 -1
- package/dist/gateway.d.ts +61 -104
- package/dist/gateway.js +12 -6
- package/dist/index.d.ts +45 -10
- package/dist/index.js +14 -2
- package/dist/parquet.d.ts +1 -1
- package/dist/parquet.js +3 -3
- package/dist/proto.d.ts +1 -1
- package/dist/proto.js +3 -3
- package/dist/react.d.ts +47 -10
- package/dist/react.js +88 -40
- package/dist/react.js.map +1 -1
- package/dist/{registry-BN_9spxE.d.ts → registry-BcspAtZI.d.ts} +19 -4
- package/dist/{gateway-CvO7Xy3T.d.ts → request-handler-pUvL7ozF.d.ts} +139 -10
- package/dist/{resolver-BZURzdlL.d.ts → resolver-CXxmC0jR.d.ts} +1 -1
- package/dist/{src-RR7I76OL.js → src-B6NLV3FP.js} +4 -4
- package/dist/{src-SLVE5567.js → src-ROW4XLO7.js} +15 -3
- package/dist/{src-V2CTPR7V.js → src-ZRHKG42A.js} +4 -4
- package/dist/{types-GGBfZBKQ.d.ts → types-BdGBv2ba.d.ts} +23 -2
- package/dist/{types-D-E0VrfS.d.ts → types-BrcD1oJg.d.ts} +26 -19
- package/package.json +1 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-7UBS6MFH.js.map +0 -1
- package/dist/chunk-PWGQ3PXE.js.map +0 -1
- package/dist/chunk-Z7FGLEQU.js.map +0 -1
- /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
- /package/dist/{chunk-L4ZL5JA7.js.map → chunk-KVSWLIJR.js.map} +0 -0
- /package/dist/{chunk-46CKACNC.js.map → chunk-SSICS5KI.js.map} +0 -0
- /package/dist/{chunk-B3QEUG6E.js.map → chunk-TMLG32QV.js.map} +0 -0
- /package/dist/{src-RR7I76OL.js.map → src-B6NLV3FP.js.map} +0 -0
- /package/dist/{src-SLVE5567.js.map → src-ROW4XLO7.js.map} +0 -0
- /package/dist/{src-V2CTPR7V.js.map → src-ZRHKG42A.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../connector-salesforce/src/errors.ts","../../connector-salesforce/src/client.ts","../../connector-salesforce/src/mapping.ts","../../connector-salesforce/src/poller.ts","../../connector-salesforce/src/schemas.ts","../../connector-salesforce/src/test-connection.ts","../../connector-salesforce/src/index.ts"],"sourcesContent":["import { LakeSyncError } from \"@lakesync/core\";\n\n/** HTTP error from the Salesforce REST API. */\nexport class SalesforceApiError extends LakeSyncError {\n\t/** HTTP status code returned by Salesforce. */\n\treadonly statusCode: number;\n\t/** Raw response body from Salesforce. */\n\treadonly responseBody: string;\n\n\tconstructor(statusCode: number, responseBody: string, cause?: Error) {\n\t\tsuper(`Salesforce API error (${statusCode}): ${responseBody}`, \"SALESFORCE_API_ERROR\", cause);\n\t\tthis.statusCode = statusCode;\n\t\tthis.responseBody = responseBody;\n\t}\n}\n\n/** Authentication failure from the Salesforce OAuth token endpoint. */\nexport class SalesforceAuthError extends LakeSyncError {\n\tconstructor(message: string, cause?: Error) {\n\t\tsuper(message, \"SALESFORCE_AUTH_ERROR\", cause);\n\t}\n}\n","// ---------------------------------------------------------------------------\n// SalesforceClient — HTTP wrapper for Salesforce REST API\n// ---------------------------------------------------------------------------\n\nimport { Err, Ok, type Result } from \"@lakesync/core\";\nimport { SalesforceApiError, SalesforceAuthError } from \"./errors\";\nimport type {\n\tSalesforceAuthResponse,\n\tSalesforceConnectorConfig,\n\tSalesforceQueryResponse,\n} from \"./types\";\n\nconst DEFAULT_API_VERSION = \"v62.0\";\nconst MAX_RETRY_ATTEMPTS = 3;\nconst DEFAULT_RETRY_AFTER_MS = 10_000;\n\n/**\n * HTTP client for the Salesforce REST API.\n *\n * Uses OAuth 2.0 Username-Password flow for authentication and global `fetch`.\n * All public methods return `Result<T, SalesforceApiError | SalesforceAuthError>`.\n */\nexport class SalesforceClient {\n\tprivate readonly config: SalesforceConnectorConfig;\n\tprivate readonly apiVersion: string;\n\tprivate readonly loginUrl: string;\n\n\tprivate accessToken: string | null = null;\n\tprivate instanceUrl: string;\n\n\tconstructor(config: SalesforceConnectorConfig) {\n\t\tthis.config = config;\n\t\tthis.apiVersion = config.apiVersion ?? DEFAULT_API_VERSION;\n\t\tthis.loginUrl = config.isSandbox\n\t\t\t? \"https://test.salesforce.com\"\n\t\t\t: \"https://login.salesforce.com\";\n\t\tthis.instanceUrl = config.instanceUrl;\n\t}\n\n\t/**\n\t * Authenticate via OAuth 2.0 Username-Password flow.\n\t *\n\t * Stores access token and updates instance URL from the response.\n\t */\n\tasync authenticate(): Promise<Result<void, SalesforceAuthError>> {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"password\",\n\t\t\tclient_id: this.config.clientId,\n\t\t\tclient_secret: this.config.clientSecret,\n\t\t\tusername: this.config.username,\n\t\t\tpassword: this.config.password,\n\t\t});\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(`${this.loginUrl}/services/oauth2/token`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\t\tbody: body.toString(),\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn Err(\n\t\t\t\tnew SalesforceAuthError(\n\t\t\t\t\t`Failed to connect to Salesforce auth endpoint: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t\terr instanceof Error ? err : undefined,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text();\n\t\t\treturn Err(\n\t\t\t\tnew SalesforceAuthError(`Salesforce authentication failed (${response.status}): ${text}`),\n\t\t\t);\n\t\t}\n\n\t\tconst data = (await response.json()) as SalesforceAuthResponse;\n\t\tthis.accessToken = data.access_token;\n\t\tthis.instanceUrl = data.instance_url;\n\n\t\treturn Ok(undefined);\n\t}\n\n\t/**\n\t * Execute a SOQL query with auto-pagination.\n\t *\n\t * Automatically authenticates on first call and re-authenticates on 401.\n\t */\n\tasync query<T>(soql: string): Promise<Result<T[], SalesforceApiError | SalesforceAuthError>> {\n\t\t// Ensure we have a token\n\t\tif (!this.accessToken) {\n\t\t\tconst authResult = await this.authenticate();\n\t\t\tif (!authResult.ok) return authResult;\n\t\t}\n\n\t\tconst allRecords: T[] = [];\n\t\tlet url = `${this.instanceUrl}/services/data/${this.apiVersion}/query?q=${encodeURIComponent(soql)}`;\n\n\t\twhile (true) {\n\t\t\tconst result = await this.request<SalesforceQueryResponse<T>>(url);\n\n\t\t\t// Re-auth on 401 and retry once\n\t\t\tif (\n\t\t\t\t!result.ok &&\n\t\t\t\tresult.error instanceof SalesforceApiError &&\n\t\t\t\tresult.error.statusCode === 401\n\t\t\t) {\n\t\t\t\tconst authResult = await this.authenticate();\n\t\t\t\tif (!authResult.ok) return authResult;\n\n\t\t\t\tconst retryResult = await this.request<SalesforceQueryResponse<T>>(url);\n\t\t\t\tif (!retryResult.ok) return retryResult;\n\n\t\t\t\tfor (const record of retryResult.value.records) {\n\t\t\t\t\tallRecords.push(record);\n\t\t\t\t}\n\n\t\t\t\tif (retryResult.value.done || !retryResult.value.nextRecordsUrl) break;\n\t\t\t\turl = `${this.instanceUrl}${retryResult.value.nextRecordsUrl}`;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!result.ok) return result;\n\n\t\t\tfor (const record of result.value.records) {\n\t\t\t\tallRecords.push(record);\n\t\t\t}\n\n\t\t\tif (result.value.done || !result.value.nextRecordsUrl) break;\n\t\t\turl = `${this.instanceUrl}${result.value.nextRecordsUrl}`;\n\t\t}\n\n\t\treturn Ok(allRecords);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Internal HTTP helpers\n\t// -----------------------------------------------------------------------\n\n\t/** Make an HTTP request with rate-limit retry logic. */\n\tprivate async request<T>(\n\t\turl: string,\n\t): Promise<Result<T, SalesforceApiError | SalesforceAuthError>> {\n\t\tfor (let attempt = 0; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\tAuthorization: `Bearer ${this.accessToken}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t};\n\n\t\t\tconst response = await fetch(url, { method: \"GET\", headers });\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as T;\n\t\t\t\treturn Ok(data);\n\t\t\t}\n\n\t\t\t// Rate limit: 503 with Retry-After\n\t\t\tif (response.status === 503) {\n\t\t\t\tconst retryAfter = response.headers.get(\"Retry-After\");\n\t\t\t\tconst waitMs = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : DEFAULT_RETRY_AFTER_MS;\n\n\t\t\t\tif (attempt < MAX_RETRY_ATTEMPTS) {\n\t\t\t\t\tawait sleep(waitMs);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst responseBody = await response.text();\n\t\t\t\treturn Err(new SalesforceApiError(503, responseBody));\n\t\t\t}\n\n\t\t\tconst responseBody = await response.text();\n\t\t\treturn Err(new SalesforceApiError(response.status, responseBody));\n\t\t}\n\n\t\treturn Err(new SalesforceApiError(0, \"Unknown error after retries\"));\n\t}\n}\n\n/** Sleep for the given number of milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// ---------------------------------------------------------------------------\n// Salesforce Entity → Flat LakeSync Row Mapping\n// ---------------------------------------------------------------------------\n\nimport type { SfAccount, SfContact, SfLead, SfOpportunity } from \"./types\";\n\n/**\n * Map a Salesforce Account to a flat row for the `sf_accounts` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapAccount(account: SfAccount): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: account.Id,\n\t\trow: {\n\t\t\tsf_id: account.Id,\n\t\t\tname: account.Name ?? null,\n\t\t\ttype: account.Type ?? null,\n\t\t\tindustry: account.Industry ?? null,\n\t\t\twebsite: account.Website ?? null,\n\t\t\tphone: account.Phone ?? null,\n\t\t\tbilling_city: account.BillingCity ?? null,\n\t\t\tbilling_state: account.BillingState ?? null,\n\t\t\tbilling_country: account.BillingCountry ?? null,\n\t\t\tannual_revenue: account.AnnualRevenue ?? null,\n\t\t\tnumber_of_employees: account.NumberOfEmployees ?? null,\n\t\t\towner_name: account.Owner?.Name ?? null,\n\t\t\tcreated_date: account.CreatedDate ?? null,\n\t\t\tlast_modified_date: account.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Contact to a flat row for the `sf_contacts` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapContact(contact: SfContact): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: contact.Id,\n\t\trow: {\n\t\t\tsf_id: contact.Id,\n\t\t\tfirst_name: contact.FirstName ?? null,\n\t\t\tlast_name: contact.LastName ?? null,\n\t\t\temail: contact.Email ?? null,\n\t\t\tphone: contact.Phone ?? null,\n\t\t\ttitle: contact.Title ?? null,\n\t\t\taccount_id: contact.AccountId ?? null,\n\t\t\taccount_name: contact.Account?.Name ?? null,\n\t\t\tmailing_city: contact.MailingCity ?? null,\n\t\t\tmailing_state: contact.MailingState ?? null,\n\t\t\tmailing_country: contact.MailingCountry ?? null,\n\t\t\towner_name: contact.Owner?.Name ?? null,\n\t\t\tcreated_date: contact.CreatedDate ?? null,\n\t\t\tlast_modified_date: contact.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Opportunity to a flat row for the `sf_opportunities` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapOpportunity(opportunity: SfOpportunity): {\n\trowId: string;\n\trow: Record<string, unknown>;\n} {\n\treturn {\n\t\trowId: opportunity.Id,\n\t\trow: {\n\t\t\tsf_id: opportunity.Id,\n\t\t\tname: opportunity.Name ?? null,\n\t\t\tstage_name: opportunity.StageName ?? null,\n\t\t\tamount: opportunity.Amount ?? null,\n\t\t\tclose_date: opportunity.CloseDate ?? null,\n\t\t\tprobability: opportunity.Probability ?? null,\n\t\t\taccount_id: opportunity.AccountId ?? null,\n\t\t\taccount_name: opportunity.Account?.Name ?? null,\n\t\t\ttype: opportunity.Type ?? null,\n\t\t\tlead_source: opportunity.LeadSource ?? null,\n\t\t\tis_closed: opportunity.IsClosed ?? null,\n\t\t\tis_won: opportunity.IsWon ?? null,\n\t\t\towner_name: opportunity.Owner?.Name ?? null,\n\t\t\tcreated_date: opportunity.CreatedDate ?? null,\n\t\t\tlast_modified_date: opportunity.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Lead to a flat row for the `sf_leads` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapLead(lead: SfLead): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: lead.Id,\n\t\trow: {\n\t\t\tsf_id: lead.Id,\n\t\t\tfirst_name: lead.FirstName ?? null,\n\t\t\tlast_name: lead.LastName ?? null,\n\t\t\tcompany: lead.Company ?? null,\n\t\t\temail: lead.Email ?? null,\n\t\t\tphone: lead.Phone ?? null,\n\t\t\ttitle: lead.Title ?? null,\n\t\t\tstatus: lead.Status ?? null,\n\t\t\tlead_source: lead.LeadSource ?? null,\n\t\t\tis_converted: lead.IsConverted ?? null,\n\t\t\tconverted_account_id: lead.ConvertedAccountId ?? null,\n\t\t\tconverted_contact_id: lead.ConvertedContactId ?? null,\n\t\t\tconverted_opportunity_id: lead.ConvertedOpportunityId ?? null,\n\t\t\towner_name: lead.Owner?.Name ?? null,\n\t\t\tcreated_date: lead.CreatedDate ?? null,\n\t\t\tlast_modified_date: lead.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n","// ---------------------------------------------------------------------------\n// SalesforceSourcePoller — polls Salesforce CRM and pushes deltas to SyncGateway\n// ---------------------------------------------------------------------------\n\nimport { BaseSourcePoller, extractDelta, type PushTarget } from \"@lakesync/core\";\nimport { SalesforceClient } from \"./client\";\nimport { mapAccount, mapContact, mapLead, mapOpportunity } from \"./mapping\";\nimport type {\n\tSalesforceConnectorConfig,\n\tSalesforceIngestConfig,\n\tSfAccount,\n\tSfContact,\n\tSfLead,\n\tSfOpportunity,\n} from \"./types\";\n\nconst DEFAULT_INTERVAL_MS = 30_000;\n\n// ---------------------------------------------------------------------------\n// SOQL field lists\n// ---------------------------------------------------------------------------\n\nconst ACCOUNT_FIELDS = [\n\t\"Id\",\n\t\"Name\",\n\t\"Type\",\n\t\"Industry\",\n\t\"Website\",\n\t\"Phone\",\n\t\"BillingCity\",\n\t\"BillingState\",\n\t\"BillingCountry\",\n\t\"AnnualRevenue\",\n\t\"NumberOfEmployees\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst CONTACT_FIELDS = [\n\t\"Id\",\n\t\"FirstName\",\n\t\"LastName\",\n\t\"Email\",\n\t\"Phone\",\n\t\"Title\",\n\t\"AccountId\",\n\t\"Account.Name\",\n\t\"MailingCity\",\n\t\"MailingState\",\n\t\"MailingCountry\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst OPPORTUNITY_FIELDS = [\n\t\"Id\",\n\t\"Name\",\n\t\"StageName\",\n\t\"Amount\",\n\t\"CloseDate\",\n\t\"Probability\",\n\t\"AccountId\",\n\t\"Account.Name\",\n\t\"Type\",\n\t\"LeadSource\",\n\t\"IsClosed\",\n\t\"IsWon\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst LEAD_FIELDS = [\n\t\"Id\",\n\t\"FirstName\",\n\t\"LastName\",\n\t\"Company\",\n\t\"Email\",\n\t\"Phone\",\n\t\"Title\",\n\t\"Status\",\n\t\"LeadSource\",\n\t\"IsConverted\",\n\t\"ConvertedAccountId\",\n\t\"ConvertedContactId\",\n\t\"ConvertedOpportunityId\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\n/**\n * Polls Salesforce CRM for accounts, contacts, opportunities, and leads\n * and pushes detected changes into a gateway via streaming accumulation.\n *\n * Uses {@link BaseSourcePoller.accumulateDelta} to push deltas in\n * memory-bounded chunks instead of collecting all deltas in a single array.\n */\nexport class SalesforceSourcePoller extends BaseSourcePoller {\n\tprivate readonly connectionConfig: SalesforceConnectorConfig;\n\tprivate readonly client: SalesforceClient;\n\n\t/** Per-entity cursors: max LastModifiedDate from the last poll. */\n\tprivate cursors: Record<string, string | undefined> = {\n\t\taccounts: undefined,\n\t\tcontacts: undefined,\n\t\topportunities: undefined,\n\t\tleads: undefined,\n\t};\n\n\t/** Export cursor state as a JSON-serialisable object for external persistence. */\n\toverride getCursorState(): Record<string, unknown> {\n\t\treturn { ...this.cursors };\n\t}\n\n\t/** Restore cursor state from a previously exported snapshot. */\n\toverride setCursorState(state: Record<string, unknown>): void {\n\t\tconst incoming = state as Record<string, string | undefined>;\n\t\tthis.cursors = {\n\t\t\taccounts: incoming.accounts,\n\t\t\tcontacts: incoming.contacts,\n\t\t\topportunities: incoming.opportunities,\n\t\t\tleads: incoming.leads,\n\t\t};\n\t}\n\n\tconstructor(\n\t\tconnectionConfig: SalesforceConnectorConfig,\n\t\tingestConfig: SalesforceIngestConfig | undefined,\n\t\tname: string,\n\t\tgateway: PushTarget,\n\t\tclient?: SalesforceClient,\n\t) {\n\t\tsuper({\n\t\t\tname,\n\t\t\tintervalMs: ingestConfig?.intervalMs ?? DEFAULT_INTERVAL_MS,\n\t\t\tgateway,\n\t\t\tmemory: {\n\t\t\t\tchunkSize: ingestConfig?.chunkSize,\n\t\t\t\tmemoryBudgetBytes: ingestConfig?.memoryBudgetBytes,\n\t\t\t},\n\t\t});\n\t\tthis.connectionConfig = connectionConfig;\n\t\tthis.client = client ?? new SalesforceClient(connectionConfig);\n\t}\n\n\t/** Execute a single poll cycle across all enabled entity types. */\n\tasync poll(): Promise<void> {\n\t\tconst includeAccounts = this.connectionConfig.includeAccounts ?? true;\n\t\tif (includeAccounts) {\n\t\t\tawait this.pollEntity<SfAccount>(\n\t\t\t\t\"Account\",\n\t\t\t\tACCOUNT_FIELDS,\n\t\t\t\t\"accounts\",\n\t\t\t\t\"sf_accounts\",\n\t\t\t\tmapAccount,\n\t\t\t);\n\t\t}\n\n\t\tconst includeContacts = this.connectionConfig.includeContacts ?? true;\n\t\tif (includeContacts) {\n\t\t\tawait this.pollEntity<SfContact>(\n\t\t\t\t\"Contact\",\n\t\t\t\tCONTACT_FIELDS,\n\t\t\t\t\"contacts\",\n\t\t\t\t\"sf_contacts\",\n\t\t\t\tmapContact,\n\t\t\t);\n\t\t}\n\n\t\tconst includeOpportunities = this.connectionConfig.includeOpportunities ?? true;\n\t\tif (includeOpportunities) {\n\t\t\tawait this.pollEntity<SfOpportunity>(\n\t\t\t\t\"Opportunity\",\n\t\t\t\tOPPORTUNITY_FIELDS,\n\t\t\t\t\"opportunities\",\n\t\t\t\t\"sf_opportunities\",\n\t\t\t\tmapOpportunity,\n\t\t\t);\n\t\t}\n\n\t\tconst includeLeads = this.connectionConfig.includeLeads ?? true;\n\t\tif (includeLeads) {\n\t\t\tawait this.pollEntity<SfLead>(\"Lead\", LEAD_FIELDS, \"leads\", \"sf_leads\", mapLead);\n\t\t}\n\n\t\tawait this.flushAccumulator();\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Generic entity polling via LastModifiedDate cursor\n\t// -----------------------------------------------------------------------\n\n\tprivate async pollEntity<T extends { Id: string; LastModifiedDate: string | null }>(\n\t\tsObjectType: string,\n\t\tfields: string,\n\t\tcursorKey: string,\n\t\ttable: string,\n\t\tmapFn: (record: T) => { rowId: string; row: Record<string, unknown> },\n\t): Promise<void> {\n\t\tconst cursor = this.cursors[cursorKey];\n\t\tconst soql = this.buildSoql(sObjectType, fields, cursor);\n\n\t\tconst result = await this.client.query<T>(soql);\n\t\tif (!result.ok) return;\n\n\t\tconst records = result.value;\n\t\tif (records.length === 0) return;\n\n\t\tlet maxLastModified = cursor;\n\n\t\tfor (const record of records) {\n\t\t\tconst { rowId, row } = mapFn(record);\n\n\t\t\tconst delta = await extractDelta(null, row, {\n\t\t\t\ttable,\n\t\t\t\trowId,\n\t\t\t\tclientId: this.clientId,\n\t\t\t\thlc: this.hlc.now(),\n\t\t\t});\n\n\t\t\tif (delta) {\n\t\t\t\tawait this.accumulateDelta(delta);\n\t\t\t}\n\n\t\t\tconst lastModified = record.LastModifiedDate;\n\t\t\tif (lastModified && (!maxLastModified || lastModified > maxLastModified)) {\n\t\t\t\tmaxLastModified = lastModified;\n\t\t\t}\n\t\t}\n\n\t\tthis.cursors[cursorKey] = maxLastModified;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// SOQL query builder\n\t// -----------------------------------------------------------------------\n\n\tprivate buildSoql(sObjectType: string, fields: string, cursor: string | undefined): string {\n\t\tconst clauses: string[] = [];\n\n\t\tif (cursor) {\n\t\t\tclauses.push(`LastModifiedDate > ${cursor}`);\n\t\t}\n\n\t\tif (this.connectionConfig.soqlFilter) {\n\t\t\tclauses.push(this.connectionConfig.soqlFilter);\n\t\t}\n\n\t\tconst where = clauses.length > 0 ? ` WHERE ${clauses.join(\" AND \")}` : \"\";\n\t\treturn `SELECT ${fields} FROM ${sObjectType}${where} ORDER BY LastModifiedDate ASC`;\n\t}\n}\n","// ---------------------------------------------------------------------------\n// Salesforce Table Schemas — column definitions for each synced entity\n// ---------------------------------------------------------------------------\n\nimport type { TableSchema } from \"@lakesync/core\";\n\n/** Column helper — all Salesforce columns are mapped to string. */\nfunction textCol(name: string): { name: string; type: \"string\" } {\n\treturn { name, type: \"string\" };\n}\n\n/** Table schemas for all Salesforce entity types synced by the connector. */\nexport const SALESFORCE_TABLE_SCHEMAS: ReadonlyArray<TableSchema> = [\n\t{\n\t\ttable: \"sf_accounts\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"name\"),\n\t\t\ttextCol(\"type\"),\n\t\t\ttextCol(\"industry\"),\n\t\t\ttextCol(\"website\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"billing_city\"),\n\t\t\ttextCol(\"billing_state\"),\n\t\t\ttextCol(\"billing_country\"),\n\t\t\ttextCol(\"annual_revenue\"),\n\t\t\ttextCol(\"number_of_employees\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_contacts\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"first_name\"),\n\t\t\ttextCol(\"last_name\"),\n\t\t\ttextCol(\"email\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"title\"),\n\t\t\ttextCol(\"account_id\"),\n\t\t\ttextCol(\"account_name\"),\n\t\t\ttextCol(\"mailing_city\"),\n\t\t\ttextCol(\"mailing_state\"),\n\t\t\ttextCol(\"mailing_country\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_opportunities\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"name\"),\n\t\t\ttextCol(\"stage_name\"),\n\t\t\ttextCol(\"amount\"),\n\t\t\ttextCol(\"close_date\"),\n\t\t\ttextCol(\"probability\"),\n\t\t\ttextCol(\"account_id\"),\n\t\t\ttextCol(\"account_name\"),\n\t\t\ttextCol(\"type\"),\n\t\t\ttextCol(\"lead_source\"),\n\t\t\ttextCol(\"is_closed\"),\n\t\t\ttextCol(\"is_won\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_leads\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"first_name\"),\n\t\t\ttextCol(\"last_name\"),\n\t\t\ttextCol(\"company\"),\n\t\t\ttextCol(\"email\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"title\"),\n\t\t\ttextCol(\"status\"),\n\t\t\ttextCol(\"lead_source\"),\n\t\t\ttextCol(\"is_converted\"),\n\t\t\ttextCol(\"converted_account_id\"),\n\t\t\ttextCol(\"converted_contact_id\"),\n\t\t\ttextCol(\"converted_opportunity_id\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n];\n","import type { Result } from \"@lakesync/core\";\nimport { SalesforceClient } from \"./client\";\nimport type { SalesforceAuthError } from \"./errors\";\nimport type { SalesforceConnectorConfig } from \"./types\";\n\n/**\n * Test a Salesforce connection by attempting OAuth authentication.\n *\n * Creates a `SalesforceClient` internally and calls `authenticate()` —\n * if the OAuth flow succeeds, the connection is valid.\n */\nexport async function testConnection(\n\tconfig: SalesforceConnectorConfig,\n): Promise<Result<void, SalesforceAuthError>> {\n\tconst client = new SalesforceClient(config);\n\treturn client.authenticate();\n}\n","import { registerOutputSchemas, registerPollerFactory } from \"@lakesync/core\";\nimport { SalesforceSourcePoller } from \"./poller\";\nimport { SALESFORCE_TABLE_SCHEMAS } from \"./schemas\";\nimport type { SalesforceIngestConfig } from \"./types\";\n\nexport { SalesforceClient } from \"./client\";\nexport { SalesforceApiError, SalesforceAuthError } from \"./errors\";\nexport { mapAccount, mapContact, mapLead, mapOpportunity } from \"./mapping\";\nexport { SalesforceSourcePoller } from \"./poller\";\nexport { SALESFORCE_TABLE_SCHEMAS } from \"./schemas\";\nexport { testConnection } from \"./test-connection\";\nexport type {\n\tSalesforceAuthResponse,\n\tSalesforceConnectorConfig,\n\tSalesforceIngestConfig,\n\tSalesforceQueryResponse,\n\tSfAccount,\n\tSfContact,\n\tSfLead,\n\tSfOpportunity,\n} from \"./types\";\n\n// Auto-register output schemas so listConnectorDescriptors() includes table info.\nregisterOutputSchemas(\"salesforce\", SALESFORCE_TABLE_SCHEMAS);\n\n// Auto-register poller factory so createPoller(\"salesforce\", ...) works.\nregisterPollerFactory(\"salesforce\", (config, gateway) => {\n\tconst ingest: SalesforceIngestConfig | undefined = config.ingest\n\t\t? {\n\t\t\t\tintervalMs: config.ingest.intervalMs,\n\t\t\t\tchunkSize: config.ingest.chunkSize,\n\t\t\t\tmemoryBudgetBytes: config.ingest.memoryBudgetBytes,\n\t\t\t}\n\t\t: undefined;\n\treturn new SalesforceSourcePoller(config.salesforce!, ingest, config.name, gateway);\n});\n"],"mappings":"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","names":["responseBody"]}
|
|
1
|
+
{"version":3,"sources":["../../connector-salesforce/src/errors.ts","../../connector-salesforce/src/client.ts","../../connector-salesforce/src/mapping.ts","../../connector-salesforce/src/poller.ts","../../connector-salesforce/src/schemas.ts","../../connector-salesforce/src/test-connection.ts","../../connector-salesforce/src/index.ts"],"sourcesContent":["import { LakeSyncError } from \"@lakesync/core\";\n\n/** HTTP error from the Salesforce REST API. */\nexport class SalesforceApiError extends LakeSyncError {\n\t/** HTTP status code returned by Salesforce. */\n\treadonly statusCode: number;\n\t/** Raw response body from Salesforce. */\n\treadonly responseBody: string;\n\n\tconstructor(statusCode: number, responseBody: string, cause?: Error) {\n\t\tsuper(`Salesforce API error (${statusCode}): ${responseBody}`, \"SALESFORCE_API_ERROR\", cause);\n\t\tthis.statusCode = statusCode;\n\t\tthis.responseBody = responseBody;\n\t}\n}\n\n/** Authentication failure from the Salesforce OAuth token endpoint. */\nexport class SalesforceAuthError extends LakeSyncError {\n\tconstructor(message: string, cause?: Error) {\n\t\tsuper(message, \"SALESFORCE_AUTH_ERROR\", cause);\n\t}\n}\n","// ---------------------------------------------------------------------------\n// SalesforceClient — HTTP wrapper for Salesforce REST API\n// ---------------------------------------------------------------------------\n\nimport { Err, Ok, type Result } from \"@lakesync/core\";\nimport { SalesforceApiError, SalesforceAuthError } from \"./errors\";\nimport type {\n\tSalesforceAuthResponse,\n\tSalesforceConnectorConfig,\n\tSalesforceQueryResponse,\n} from \"./types\";\n\nconst DEFAULT_API_VERSION = \"v62.0\";\nconst MAX_RETRY_ATTEMPTS = 3;\nconst DEFAULT_RETRY_AFTER_MS = 10_000;\n\n/**\n * HTTP client for the Salesforce REST API.\n *\n * Uses OAuth 2.0 Username-Password flow for authentication and global `fetch`.\n * All public methods return `Result<T, SalesforceApiError | SalesforceAuthError>`.\n */\nexport class SalesforceClient {\n\tprivate readonly config: SalesforceConnectorConfig;\n\tprivate readonly apiVersion: string;\n\tprivate readonly loginUrl: string;\n\n\tprivate accessToken: string | null = null;\n\tprivate instanceUrl: string;\n\n\tconstructor(config: SalesforceConnectorConfig) {\n\t\tthis.config = config;\n\t\tthis.apiVersion = config.apiVersion ?? DEFAULT_API_VERSION;\n\t\tthis.loginUrl = config.isSandbox\n\t\t\t? \"https://test.salesforce.com\"\n\t\t\t: \"https://login.salesforce.com\";\n\t\tthis.instanceUrl = config.instanceUrl;\n\t}\n\n\t/**\n\t * Authenticate via OAuth 2.0 Username-Password flow.\n\t *\n\t * Stores access token and updates instance URL from the response.\n\t */\n\tasync authenticate(): Promise<Result<void, SalesforceAuthError>> {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"password\",\n\t\t\tclient_id: this.config.clientId,\n\t\t\tclient_secret: this.config.clientSecret,\n\t\t\tusername: this.config.username,\n\t\t\tpassword: this.config.password,\n\t\t});\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(`${this.loginUrl}/services/oauth2/token`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\t\tbody: body.toString(),\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn Err(\n\t\t\t\tnew SalesforceAuthError(\n\t\t\t\t\t`Failed to connect to Salesforce auth endpoint: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t\terr instanceof Error ? err : undefined,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text();\n\t\t\treturn Err(\n\t\t\t\tnew SalesforceAuthError(`Salesforce authentication failed (${response.status}): ${text}`),\n\t\t\t);\n\t\t}\n\n\t\tconst data = (await response.json()) as SalesforceAuthResponse;\n\t\tthis.accessToken = data.access_token;\n\t\tthis.instanceUrl = data.instance_url;\n\n\t\treturn Ok(undefined);\n\t}\n\n\t/**\n\t * Execute a SOQL query with auto-pagination.\n\t *\n\t * Automatically authenticates on first call and re-authenticates on 401.\n\t */\n\tasync query<T>(soql: string): Promise<Result<T[], SalesforceApiError | SalesforceAuthError>> {\n\t\t// Ensure we have a token\n\t\tif (!this.accessToken) {\n\t\t\tconst authResult = await this.authenticate();\n\t\t\tif (!authResult.ok) return authResult;\n\t\t}\n\n\t\tconst allRecords: T[] = [];\n\t\tlet url = `${this.instanceUrl}/services/data/${this.apiVersion}/query?q=${encodeURIComponent(soql)}`;\n\n\t\twhile (true) {\n\t\t\tconst result = await this.request<SalesforceQueryResponse<T>>(url);\n\n\t\t\t// Re-auth on 401 and retry once\n\t\t\tif (\n\t\t\t\t!result.ok &&\n\t\t\t\tresult.error instanceof SalesforceApiError &&\n\t\t\t\tresult.error.statusCode === 401\n\t\t\t) {\n\t\t\t\tconst authResult = await this.authenticate();\n\t\t\t\tif (!authResult.ok) return authResult;\n\n\t\t\t\tconst retryResult = await this.request<SalesforceQueryResponse<T>>(url);\n\t\t\t\tif (!retryResult.ok) return retryResult;\n\n\t\t\t\tfor (const record of retryResult.value.records) {\n\t\t\t\t\tallRecords.push(record);\n\t\t\t\t}\n\n\t\t\t\tif (retryResult.value.done || !retryResult.value.nextRecordsUrl) break;\n\t\t\t\turl = `${this.instanceUrl}${retryResult.value.nextRecordsUrl}`;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!result.ok) return result;\n\n\t\t\tfor (const record of result.value.records) {\n\t\t\t\tallRecords.push(record);\n\t\t\t}\n\n\t\t\tif (result.value.done || !result.value.nextRecordsUrl) break;\n\t\t\turl = `${this.instanceUrl}${result.value.nextRecordsUrl}`;\n\t\t}\n\n\t\treturn Ok(allRecords);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Internal HTTP helpers\n\t// -----------------------------------------------------------------------\n\n\t/** Make an HTTP request with rate-limit retry logic. */\n\tprivate async request<T>(\n\t\turl: string,\n\t): Promise<Result<T, SalesforceApiError | SalesforceAuthError>> {\n\t\tfor (let attempt = 0; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\tAuthorization: `Bearer ${this.accessToken}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t};\n\n\t\t\tconst response = await fetch(url, { method: \"GET\", headers });\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data = (await response.json()) as T;\n\t\t\t\treturn Ok(data);\n\t\t\t}\n\n\t\t\t// Rate limit: 503 with Retry-After\n\t\t\tif (response.status === 503) {\n\t\t\t\tconst retryAfter = response.headers.get(\"Retry-After\");\n\t\t\t\tconst waitMs = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : DEFAULT_RETRY_AFTER_MS;\n\n\t\t\t\tif (attempt < MAX_RETRY_ATTEMPTS) {\n\t\t\t\t\tawait sleep(waitMs);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst responseBody = await response.text();\n\t\t\t\treturn Err(new SalesforceApiError(503, responseBody));\n\t\t\t}\n\n\t\t\tconst responseBody = await response.text();\n\t\t\treturn Err(new SalesforceApiError(response.status, responseBody));\n\t\t}\n\n\t\treturn Err(new SalesforceApiError(0, \"Unknown error after retries\"));\n\t}\n}\n\n/** Sleep for the given number of milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// ---------------------------------------------------------------------------\n// Salesforce Entity → Flat LakeSync Row Mapping\n// ---------------------------------------------------------------------------\n\nimport type { SfAccount, SfContact, SfLead, SfOpportunity } from \"./types\";\n\n/**\n * Map a Salesforce Account to a flat row for the `sf_accounts` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapAccount(account: SfAccount): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: account.Id,\n\t\trow: {\n\t\t\tsf_id: account.Id,\n\t\t\tname: account.Name ?? null,\n\t\t\ttype: account.Type ?? null,\n\t\t\tindustry: account.Industry ?? null,\n\t\t\twebsite: account.Website ?? null,\n\t\t\tphone: account.Phone ?? null,\n\t\t\tbilling_city: account.BillingCity ?? null,\n\t\t\tbilling_state: account.BillingState ?? null,\n\t\t\tbilling_country: account.BillingCountry ?? null,\n\t\t\tannual_revenue: account.AnnualRevenue ?? null,\n\t\t\tnumber_of_employees: account.NumberOfEmployees ?? null,\n\t\t\towner_name: account.Owner?.Name ?? null,\n\t\t\tcreated_date: account.CreatedDate ?? null,\n\t\t\tlast_modified_date: account.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Contact to a flat row for the `sf_contacts` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapContact(contact: SfContact): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: contact.Id,\n\t\trow: {\n\t\t\tsf_id: contact.Id,\n\t\t\tfirst_name: contact.FirstName ?? null,\n\t\t\tlast_name: contact.LastName ?? null,\n\t\t\temail: contact.Email ?? null,\n\t\t\tphone: contact.Phone ?? null,\n\t\t\ttitle: contact.Title ?? null,\n\t\t\taccount_id: contact.AccountId ?? null,\n\t\t\taccount_name: contact.Account?.Name ?? null,\n\t\t\tmailing_city: contact.MailingCity ?? null,\n\t\t\tmailing_state: contact.MailingState ?? null,\n\t\t\tmailing_country: contact.MailingCountry ?? null,\n\t\t\towner_name: contact.Owner?.Name ?? null,\n\t\t\tcreated_date: contact.CreatedDate ?? null,\n\t\t\tlast_modified_date: contact.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Opportunity to a flat row for the `sf_opportunities` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapOpportunity(opportunity: SfOpportunity): {\n\trowId: string;\n\trow: Record<string, unknown>;\n} {\n\treturn {\n\t\trowId: opportunity.Id,\n\t\trow: {\n\t\t\tsf_id: opportunity.Id,\n\t\t\tname: opportunity.Name ?? null,\n\t\t\tstage_name: opportunity.StageName ?? null,\n\t\t\tamount: opportunity.Amount ?? null,\n\t\t\tclose_date: opportunity.CloseDate ?? null,\n\t\t\tprobability: opportunity.Probability ?? null,\n\t\t\taccount_id: opportunity.AccountId ?? null,\n\t\t\taccount_name: opportunity.Account?.Name ?? null,\n\t\t\ttype: opportunity.Type ?? null,\n\t\t\tlead_source: opportunity.LeadSource ?? null,\n\t\t\tis_closed: opportunity.IsClosed ?? null,\n\t\t\tis_won: opportunity.IsWon ?? null,\n\t\t\towner_name: opportunity.Owner?.Name ?? null,\n\t\t\tcreated_date: opportunity.CreatedDate ?? null,\n\t\t\tlast_modified_date: opportunity.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n\n/**\n * Map a Salesforce Lead to a flat row for the `sf_leads` table.\n *\n * The row ID is the Salesforce record Id.\n */\nexport function mapLead(lead: SfLead): { rowId: string; row: Record<string, unknown> } {\n\treturn {\n\t\trowId: lead.Id,\n\t\trow: {\n\t\t\tsf_id: lead.Id,\n\t\t\tfirst_name: lead.FirstName ?? null,\n\t\t\tlast_name: lead.LastName ?? null,\n\t\t\tcompany: lead.Company ?? null,\n\t\t\temail: lead.Email ?? null,\n\t\t\tphone: lead.Phone ?? null,\n\t\t\ttitle: lead.Title ?? null,\n\t\t\tstatus: lead.Status ?? null,\n\t\t\tlead_source: lead.LeadSource ?? null,\n\t\t\tis_converted: lead.IsConverted ?? null,\n\t\t\tconverted_account_id: lead.ConvertedAccountId ?? null,\n\t\t\tconverted_contact_id: lead.ConvertedContactId ?? null,\n\t\t\tconverted_opportunity_id: lead.ConvertedOpportunityId ?? null,\n\t\t\towner_name: lead.Owner?.Name ?? null,\n\t\t\tcreated_date: lead.CreatedDate ?? null,\n\t\t\tlast_modified_date: lead.LastModifiedDate ?? null,\n\t\t},\n\t};\n}\n","// ---------------------------------------------------------------------------\n// SalesforceSourcePoller — polls Salesforce CRM and pushes deltas to SyncGateway\n// ---------------------------------------------------------------------------\n\nimport { BaseSourcePoller, extractDelta, type PushTarget } from \"@lakesync/core\";\nimport { SalesforceClient } from \"./client\";\nimport { mapAccount, mapContact, mapLead, mapOpportunity } from \"./mapping\";\nimport type {\n\tSalesforceConnectorConfig,\n\tSalesforceIngestConfig,\n\tSfAccount,\n\tSfContact,\n\tSfLead,\n\tSfOpportunity,\n} from \"./types\";\n\nconst DEFAULT_INTERVAL_MS = 30_000;\n\n// ---------------------------------------------------------------------------\n// SOQL field lists\n// ---------------------------------------------------------------------------\n\nconst ACCOUNT_FIELDS = [\n\t\"Id\",\n\t\"Name\",\n\t\"Type\",\n\t\"Industry\",\n\t\"Website\",\n\t\"Phone\",\n\t\"BillingCity\",\n\t\"BillingState\",\n\t\"BillingCountry\",\n\t\"AnnualRevenue\",\n\t\"NumberOfEmployees\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst CONTACT_FIELDS = [\n\t\"Id\",\n\t\"FirstName\",\n\t\"LastName\",\n\t\"Email\",\n\t\"Phone\",\n\t\"Title\",\n\t\"AccountId\",\n\t\"Account.Name\",\n\t\"MailingCity\",\n\t\"MailingState\",\n\t\"MailingCountry\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst OPPORTUNITY_FIELDS = [\n\t\"Id\",\n\t\"Name\",\n\t\"StageName\",\n\t\"Amount\",\n\t\"CloseDate\",\n\t\"Probability\",\n\t\"AccountId\",\n\t\"Account.Name\",\n\t\"Type\",\n\t\"LeadSource\",\n\t\"IsClosed\",\n\t\"IsWon\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\nconst LEAD_FIELDS = [\n\t\"Id\",\n\t\"FirstName\",\n\t\"LastName\",\n\t\"Company\",\n\t\"Email\",\n\t\"Phone\",\n\t\"Title\",\n\t\"Status\",\n\t\"LeadSource\",\n\t\"IsConverted\",\n\t\"ConvertedAccountId\",\n\t\"ConvertedContactId\",\n\t\"ConvertedOpportunityId\",\n\t\"Owner.Name\",\n\t\"CreatedDate\",\n\t\"LastModifiedDate\",\n].join(\", \");\n\n/**\n * Polls Salesforce CRM for accounts, contacts, opportunities, and leads\n * and pushes detected changes into a gateway via streaming accumulation.\n *\n * Uses {@link BaseSourcePoller.accumulateDelta} to push deltas in\n * memory-bounded chunks instead of collecting all deltas in a single array.\n */\nexport class SalesforceSourcePoller extends BaseSourcePoller {\n\tprivate readonly connectionConfig: SalesforceConnectorConfig;\n\tprivate readonly client: SalesforceClient;\n\n\t/** Per-entity cursors: max LastModifiedDate from the last poll. */\n\tprivate cursors: Record<string, string | undefined> = {\n\t\taccounts: undefined,\n\t\tcontacts: undefined,\n\t\topportunities: undefined,\n\t\tleads: undefined,\n\t};\n\n\t/** Export cursor state as a JSON-serialisable object for external persistence. */\n\toverride getCursorState(): Record<string, unknown> {\n\t\treturn { ...this.cursors };\n\t}\n\n\t/** Restore cursor state from a previously exported snapshot. */\n\toverride setCursorState(state: Record<string, unknown>): void {\n\t\tconst incoming = state as Record<string, string | undefined>;\n\t\tthis.cursors = {\n\t\t\taccounts: incoming.accounts,\n\t\t\tcontacts: incoming.contacts,\n\t\t\topportunities: incoming.opportunities,\n\t\t\tleads: incoming.leads,\n\t\t};\n\t}\n\n\tconstructor(\n\t\tconnectionConfig: SalesforceConnectorConfig,\n\t\tingestConfig: SalesforceIngestConfig | undefined,\n\t\tname: string,\n\t\tgateway: PushTarget,\n\t\tclient?: SalesforceClient,\n\t) {\n\t\tsuper({\n\t\t\tname,\n\t\t\tintervalMs: ingestConfig?.intervalMs ?? DEFAULT_INTERVAL_MS,\n\t\t\tgateway,\n\t\t\tmemory: {\n\t\t\t\tchunkSize: ingestConfig?.chunkSize,\n\t\t\t\tmemoryBudgetBytes: ingestConfig?.memoryBudgetBytes,\n\t\t\t},\n\t\t});\n\t\tthis.connectionConfig = connectionConfig;\n\t\tthis.client = client ?? new SalesforceClient(connectionConfig);\n\t}\n\n\t/** Execute a single poll cycle across all enabled entity types. */\n\tasync poll(): Promise<void> {\n\t\tconst includeAccounts = this.connectionConfig.includeAccounts ?? true;\n\t\tif (includeAccounts) {\n\t\t\tawait this.pollEntity<SfAccount>(\n\t\t\t\t\"Account\",\n\t\t\t\tACCOUNT_FIELDS,\n\t\t\t\t\"accounts\",\n\t\t\t\t\"sf_accounts\",\n\t\t\t\tmapAccount,\n\t\t\t);\n\t\t}\n\n\t\tconst includeContacts = this.connectionConfig.includeContacts ?? true;\n\t\tif (includeContacts) {\n\t\t\tawait this.pollEntity<SfContact>(\n\t\t\t\t\"Contact\",\n\t\t\t\tCONTACT_FIELDS,\n\t\t\t\t\"contacts\",\n\t\t\t\t\"sf_contacts\",\n\t\t\t\tmapContact,\n\t\t\t);\n\t\t}\n\n\t\tconst includeOpportunities = this.connectionConfig.includeOpportunities ?? true;\n\t\tif (includeOpportunities) {\n\t\t\tawait this.pollEntity<SfOpportunity>(\n\t\t\t\t\"Opportunity\",\n\t\t\t\tOPPORTUNITY_FIELDS,\n\t\t\t\t\"opportunities\",\n\t\t\t\t\"sf_opportunities\",\n\t\t\t\tmapOpportunity,\n\t\t\t);\n\t\t}\n\n\t\tconst includeLeads = this.connectionConfig.includeLeads ?? true;\n\t\tif (includeLeads) {\n\t\t\tawait this.pollEntity<SfLead>(\"Lead\", LEAD_FIELDS, \"leads\", \"sf_leads\", mapLead);\n\t\t}\n\n\t\tawait this.flushAccumulator();\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Generic entity polling via LastModifiedDate cursor\n\t// -----------------------------------------------------------------------\n\n\tprivate async pollEntity<T extends { Id: string; LastModifiedDate: string | null }>(\n\t\tsObjectType: string,\n\t\tfields: string,\n\t\tcursorKey: string,\n\t\ttable: string,\n\t\tmapFn: (record: T) => { rowId: string; row: Record<string, unknown> },\n\t): Promise<void> {\n\t\tconst cursor = this.cursors[cursorKey];\n\t\tconst soql = this.buildSoql(sObjectType, fields, cursor);\n\n\t\tconst result = await this.client.query<T>(soql);\n\t\tif (!result.ok) return;\n\n\t\tconst records = result.value;\n\t\tif (records.length === 0) return;\n\n\t\tlet maxLastModified = cursor;\n\n\t\tfor (const record of records) {\n\t\t\tconst { rowId, row } = mapFn(record);\n\n\t\t\tconst delta = await extractDelta(null, row, {\n\t\t\t\ttable,\n\t\t\t\trowId,\n\t\t\t\tclientId: this.clientId,\n\t\t\t\thlc: this.hlc.now(),\n\t\t\t});\n\n\t\t\tif (delta) {\n\t\t\t\tawait this.accumulateDelta(delta);\n\t\t\t}\n\n\t\t\tconst lastModified = record.LastModifiedDate;\n\t\t\tif (lastModified && (!maxLastModified || lastModified > maxLastModified)) {\n\t\t\t\tmaxLastModified = lastModified;\n\t\t\t}\n\t\t}\n\n\t\tthis.cursors[cursorKey] = maxLastModified;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// SOQL query builder\n\t// -----------------------------------------------------------------------\n\n\tprivate buildSoql(sObjectType: string, fields: string, cursor: string | undefined): string {\n\t\tconst clauses: string[] = [];\n\n\t\tif (cursor) {\n\t\t\tclauses.push(`LastModifiedDate > ${cursor}`);\n\t\t}\n\n\t\tif (this.connectionConfig.soqlFilter) {\n\t\t\tclauses.push(this.connectionConfig.soqlFilter);\n\t\t}\n\n\t\tconst where = clauses.length > 0 ? ` WHERE ${clauses.join(\" AND \")}` : \"\";\n\t\treturn `SELECT ${fields} FROM ${sObjectType}${where} ORDER BY LastModifiedDate ASC`;\n\t}\n}\n","// ---------------------------------------------------------------------------\n// Salesforce Table Schemas — column definitions for each synced entity\n// ---------------------------------------------------------------------------\n\nimport type { TableSchema } from \"@lakesync/core\";\n\n/** Column helper — all Salesforce columns are mapped to string. */\nfunction textCol(name: string): { name: string; type: \"string\" } {\n\treturn { name, type: \"string\" };\n}\n\n/** Table schemas for all Salesforce entity types synced by the connector. */\nexport const SALESFORCE_TABLE_SCHEMAS: ReadonlyArray<TableSchema> = [\n\t{\n\t\ttable: \"sf_accounts\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"name\"),\n\t\t\ttextCol(\"type\"),\n\t\t\ttextCol(\"industry\"),\n\t\t\ttextCol(\"website\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"billing_city\"),\n\t\t\ttextCol(\"billing_state\"),\n\t\t\ttextCol(\"billing_country\"),\n\t\t\ttextCol(\"annual_revenue\"),\n\t\t\ttextCol(\"number_of_employees\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_contacts\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"first_name\"),\n\t\t\ttextCol(\"last_name\"),\n\t\t\ttextCol(\"email\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"title\"),\n\t\t\t{\n\t\t\t\tname: \"account_id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: { table: \"sf_accounts\", column: \"sf_id\", cardinality: \"many-to-one\" },\n\t\t\t},\n\t\t\ttextCol(\"account_name\"),\n\t\t\ttextCol(\"mailing_city\"),\n\t\t\ttextCol(\"mailing_state\"),\n\t\t\ttextCol(\"mailing_country\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_opportunities\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"name\"),\n\t\t\ttextCol(\"stage_name\"),\n\t\t\ttextCol(\"amount\"),\n\t\t\ttextCol(\"close_date\"),\n\t\t\ttextCol(\"probability\"),\n\t\t\t{\n\t\t\t\tname: \"account_id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: { table: \"sf_accounts\", column: \"sf_id\", cardinality: \"many-to-one\" },\n\t\t\t},\n\t\t\ttextCol(\"account_name\"),\n\t\t\ttextCol(\"type\"),\n\t\t\ttextCol(\"lead_source\"),\n\t\t\ttextCol(\"is_closed\"),\n\t\t\ttextCol(\"is_won\"),\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n\t{\n\t\ttable: \"sf_leads\",\n\t\tcolumns: [\n\t\t\ttextCol(\"sf_id\"),\n\t\t\ttextCol(\"first_name\"),\n\t\t\ttextCol(\"last_name\"),\n\t\t\ttextCol(\"company\"),\n\t\t\ttextCol(\"email\"),\n\t\t\ttextCol(\"phone\"),\n\t\t\ttextCol(\"title\"),\n\t\t\ttextCol(\"status\"),\n\t\t\ttextCol(\"lead_source\"),\n\t\t\ttextCol(\"is_converted\"),\n\t\t\t{\n\t\t\t\tname: \"converted_account_id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: { table: \"sf_accounts\", column: \"sf_id\", cardinality: \"many-to-one\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"converted_contact_id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: { table: \"sf_contacts\", column: \"sf_id\", cardinality: \"many-to-one\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"converted_opportunity_id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: { table: \"sf_opportunities\", column: \"sf_id\", cardinality: \"many-to-one\" },\n\t\t\t},\n\t\t\ttextCol(\"owner_name\"),\n\t\t\ttextCol(\"created_date\"),\n\t\t\ttextCol(\"last_modified_date\"),\n\t\t],\n\t},\n];\n","import type { Result } from \"@lakesync/core\";\nimport { SalesforceClient } from \"./client\";\nimport type { SalesforceAuthError } from \"./errors\";\nimport type { SalesforceConnectorConfig } from \"./types\";\n\n/**\n * Test a Salesforce connection by attempting OAuth authentication.\n *\n * Creates a `SalesforceClient` internally and calls `authenticate()` —\n * if the OAuth flow succeeds, the connection is valid.\n */\nexport async function testConnection(\n\tconfig: SalesforceConnectorConfig,\n): Promise<Result<void, SalesforceAuthError>> {\n\tconst client = new SalesforceClient(config);\n\treturn client.authenticate();\n}\n","import { registerOutputSchemas, registerPollerFactory } from \"@lakesync/core\";\nimport { SalesforceSourcePoller } from \"./poller\";\nimport { SALESFORCE_TABLE_SCHEMAS } from \"./schemas\";\nimport type { SalesforceIngestConfig } from \"./types\";\n\nexport { SalesforceClient } from \"./client\";\nexport { SalesforceApiError, SalesforceAuthError } from \"./errors\";\nexport { mapAccount, mapContact, mapLead, mapOpportunity } from \"./mapping\";\nexport { SalesforceSourcePoller } from \"./poller\";\nexport { SALESFORCE_TABLE_SCHEMAS } from \"./schemas\";\nexport { testConnection } from \"./test-connection\";\nexport type {\n\tSalesforceAuthResponse,\n\tSalesforceConnectorConfig,\n\tSalesforceIngestConfig,\n\tSalesforceQueryResponse,\n\tSfAccount,\n\tSfContact,\n\tSfLead,\n\tSfOpportunity,\n} from \"./types\";\n\n// Auto-register output schemas so listConnectorDescriptors() includes table info.\nregisterOutputSchemas(\"salesforce\", SALESFORCE_TABLE_SCHEMAS);\n\n// Auto-register poller factory so createPoller(\"salesforce\", ...) works.\nregisterPollerFactory(\"salesforce\", (config, gateway) => {\n\tif (config.type !== \"salesforce\") {\n\t\tthrow new Error(`Expected connector type \"salesforce\", got \"${config.type}\"`);\n\t}\n\tconst ingest: SalesforceIngestConfig | undefined = config.ingest\n\t\t? {\n\t\t\t\tintervalMs: config.ingest.intervalMs,\n\t\t\t\tchunkSize: config.ingest.chunkSize,\n\t\t\t\tmemoryBudgetBytes: config.ingest.memoryBudgetBytes,\n\t\t\t}\n\t\t: undefined;\n\treturn new SalesforceSourcePoller(config.salesforce, ingest, config.name, gateway);\n});\n"],"mappings":"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","names":["responseBody"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
Err,
|
|
3
3
|
FlushError,
|
|
4
4
|
Ok
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LDFFCG2K.js";
|
|
6
6
|
|
|
7
7
|
// ../parquet/src/arrow-schema.ts
|
|
8
8
|
import * as arrow from "apache-arrow";
|
|
@@ -254,4 +254,4 @@ export {
|
|
|
254
254
|
readParquetToDeltas,
|
|
255
255
|
writeDeltasToParquet
|
|
256
256
|
};
|
|
257
|
-
//# sourceMappingURL=chunk-
|
|
257
|
+
//# sourceMappingURL=chunk-SSICS5KI.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
Err,
|
|
3
3
|
LakeSyncError,
|
|
4
4
|
Ok
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LDFFCG2K.js";
|
|
6
6
|
|
|
7
7
|
// ../catalogue/src/types.ts
|
|
8
8
|
var CatalogueError = class extends LakeSyncError {
|
|
@@ -410,4 +410,4 @@ export {
|
|
|
410
410
|
buildPartitionSpec,
|
|
411
411
|
lakeSyncTableName
|
|
412
412
|
};
|
|
413
|
-
//# sourceMappingURL=chunk-
|
|
413
|
+
//# sourceMappingURL=chunk-TMLG32QV.js.map
|
package/dist/client.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { R as Result, S as SchemaError, L as LakeSyncError, H as HLCTimestamp } from './result-CojzlFE2.js';
|
|
2
2
|
export { u as unwrapOrThrow } from './result-CojzlFE2.js';
|
|
3
|
-
import { T as TableSchema, R as RowDelta, S as SyncPush,
|
|
4
|
-
import { S as SyncQueue, a as SyncCoordinatorConfig, b as SyncCoordinator, L as LocalDB, c as SyncTransport, D as DbError, A as ActionQueue, d as ActionQueueEntry, Q as QueueEntry, C as CheckpointResponse } from './coordinator-
|
|
5
|
-
export { e as ActionQueueEntryStatus, f as DbConfig, g as QueueEntryStatus, h as SyncEvents, i as SyncMode, j as SyncTracker, T as Transaction } from './coordinator-
|
|
6
|
-
import { A as Action,
|
|
7
|
-
import {
|
|
8
|
-
import { a as ConnectorDescriptor } from './registry-
|
|
9
|
-
import './
|
|
10
|
-
import './types-
|
|
3
|
+
import { T as TableSchema, R as RowDelta, S as SyncPush, e as SyncPull, f as SyncResponse } from './types-BdGBv2ba.js';
|
|
4
|
+
import { S as SyncQueue, a as SyncCoordinatorConfig, b as SyncCoordinator, L as LocalDB, c as SyncTransport, D as DbError, A as ActionQueue, d as ActionQueueEntry, Q as QueueEntry, C as CheckpointResponse } from './coordinator-NXy6tA0h.js';
|
|
5
|
+
export { e as ActionQueueEntryStatus, f as DbConfig, g as QueueEntryStatus, h as SyncEvents, i as SyncMode, j as SyncState, k as SyncTracker, T as Transaction } from './coordinator-NXy6tA0h.js';
|
|
6
|
+
import { A as Action, k as ActionResult, e as ActionErrorResult, d as ActionDiscovery, i as ActionPush, j as ActionResponse, l as AuthContext, a as ActionValidationError } from './types-Bs-QyOe-.js';
|
|
7
|
+
import { H as HLC } from './hlc-DiD8QNG3.js';
|
|
8
|
+
import { a as ConnectorDescriptor } from './registry-BcspAtZI.js';
|
|
9
|
+
import { C as ConflictResolver } from './resolver-CXxmC0jR.js';
|
|
10
|
+
import './types-BrcD1oJg.js';
|
|
11
11
|
|
|
12
12
|
/** Configuration for creating a LakeSync client via {@link createClient}. */
|
|
13
13
|
interface CreateClientConfig {
|
|
@@ -212,10 +212,12 @@ declare class IDBQueue implements SyncQueue {
|
|
|
212
212
|
/**
|
|
213
213
|
* In-memory action queue implementation.
|
|
214
214
|
* Suitable for testing and server-side use.
|
|
215
|
+
*
|
|
216
|
+
* Delegates to {@link MemoryOutbox} for the generic outbox logic and
|
|
217
|
+
* adapts the entry shape to the {@link ActionQueue} interface.
|
|
215
218
|
*/
|
|
216
219
|
declare class MemoryActionQueue implements ActionQueue {
|
|
217
|
-
private
|
|
218
|
-
private counter;
|
|
220
|
+
private readonly outbox;
|
|
219
221
|
/** Add an action to the queue. */
|
|
220
222
|
push(action: Action): Promise<Result<ActionQueueEntry, LakeSyncError>>;
|
|
221
223
|
/** Peek at pending entries (ordered by createdAt), skipping entries with future retryAfter. */
|
|
@@ -230,15 +232,80 @@ declare class MemoryActionQueue implements ActionQueue {
|
|
|
230
232
|
depth(): Promise<Result<number, LakeSyncError>>;
|
|
231
233
|
/** Remove all entries. */
|
|
232
234
|
clear(): Promise<Result<void, LakeSyncError>>;
|
|
235
|
+
/** Convert a generic OutboxEntry to the ActionQueue-specific ActionQueueEntry shape. */
|
|
236
|
+
private toActionEntry;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Status of an outbox entry. */
|
|
240
|
+
type OutboxEntryStatus = "pending" | "sending" | "acked";
|
|
241
|
+
/** A single entry in a generic outbox queue. */
|
|
242
|
+
interface OutboxEntry<T> {
|
|
243
|
+
/** Unique entry identifier. */
|
|
244
|
+
id: string;
|
|
245
|
+
/** The payload item. */
|
|
246
|
+
item: T;
|
|
247
|
+
/** Current processing status. */
|
|
248
|
+
status: OutboxEntryStatus;
|
|
249
|
+
/** Timestamp when the entry was created. */
|
|
250
|
+
createdAt: number;
|
|
251
|
+
/** Number of times this entry has been retried. */
|
|
252
|
+
retryCount: number;
|
|
253
|
+
/** Earliest time (ms since epoch) this entry should be retried. Undefined = immediately. */
|
|
254
|
+
retryAfter?: number;
|
|
255
|
+
}
|
|
256
|
+
/** Generic outbox queue interface. */
|
|
257
|
+
interface Outbox<T> {
|
|
258
|
+
/** Add an item to the queue. */
|
|
259
|
+
push(item: T): Promise<Result<OutboxEntry<T>, LakeSyncError>>;
|
|
260
|
+
/** Peek at pending entries (ordered by createdAt). */
|
|
261
|
+
peek(limit: number): Promise<Result<OutboxEntry<T>[], LakeSyncError>>;
|
|
262
|
+
/** Mark entries as currently being sent. */
|
|
263
|
+
markSending(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
264
|
+
/** Acknowledge successful delivery (removes entries). */
|
|
265
|
+
ack(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
266
|
+
/** Negative acknowledge — reset to pending with incremented retryCount. */
|
|
267
|
+
nack(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
268
|
+
/** Get the number of pending + sending entries. */
|
|
269
|
+
depth(): Promise<Result<number, LakeSyncError>>;
|
|
270
|
+
/** Remove all entries. */
|
|
271
|
+
clear(): Promise<Result<void, LakeSyncError>>;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Generic in-memory outbox queue.
|
|
275
|
+
*
|
|
276
|
+
* Suitable for testing and server-side use. Parameterised over the
|
|
277
|
+
* payload type so the same logic can back both delta and action queues.
|
|
278
|
+
*/
|
|
279
|
+
declare class MemoryOutbox<T> implements Outbox<T> {
|
|
280
|
+
private entries;
|
|
281
|
+
private counter;
|
|
282
|
+
private readonly prefix;
|
|
283
|
+
constructor(prefix?: string);
|
|
284
|
+
/** Add an item to the queue. */
|
|
285
|
+
push(item: T): Promise<Result<OutboxEntry<T>, LakeSyncError>>;
|
|
286
|
+
/** Peek at pending entries (ordered by createdAt), skipping entries with future retryAfter. */
|
|
287
|
+
peek(limit: number): Promise<Result<OutboxEntry<T>[], LakeSyncError>>;
|
|
288
|
+
/** Mark entries as currently being sent. */
|
|
289
|
+
markSending(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
290
|
+
/** Acknowledge successful delivery (removes entries). */
|
|
291
|
+
ack(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
292
|
+
/** Negative acknowledge — reset to pending with incremented retryCount and exponential backoff. */
|
|
293
|
+
nack(ids: string[]): Promise<Result<void, LakeSyncError>>;
|
|
294
|
+
/** Get the number of pending + sending entries. */
|
|
295
|
+
depth(): Promise<Result<number, LakeSyncError>>;
|
|
296
|
+
/** Remove all entries. */
|
|
297
|
+
clear(): Promise<Result<void, LakeSyncError>>;
|
|
233
298
|
}
|
|
234
299
|
|
|
235
300
|
/**
|
|
236
301
|
* In-memory sync queue implementation.
|
|
237
302
|
* Suitable for testing and server-side use.
|
|
303
|
+
*
|
|
304
|
+
* Delegates to {@link MemoryOutbox} for the generic outbox logic and
|
|
305
|
+
* adapts the entry shape to the {@link SyncQueue} interface.
|
|
238
306
|
*/
|
|
239
307
|
declare class MemoryQueue implements SyncQueue {
|
|
240
|
-
private
|
|
241
|
-
private counter;
|
|
308
|
+
private readonly outbox;
|
|
242
309
|
/** Add a delta to the queue */
|
|
243
310
|
push(delta: RowDelta): Promise<Result<QueueEntry, LakeSyncError>>;
|
|
244
311
|
/** Peek at pending entries (ordered by createdAt), skipping entries with future retryAfter */
|
|
@@ -253,6 +320,67 @@ declare class MemoryQueue implements SyncQueue {
|
|
|
253
320
|
depth(): Promise<Result<number, LakeSyncError>>;
|
|
254
321
|
/** Remove all entries */
|
|
255
322
|
clear(): Promise<Result<void, LakeSyncError>>;
|
|
323
|
+
/** Convert a generic OutboxEntry to the SyncQueue-specific QueueEntry shape. */
|
|
324
|
+
private toQueueEntry;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Callback for action completion events. */
|
|
328
|
+
type ActionCompleteCallback = (actionId: string, result: ActionResult | ActionErrorResult) => void;
|
|
329
|
+
/**
|
|
330
|
+
* Manages the action queue: enqueue, process, dead-letter, and discovery.
|
|
331
|
+
*
|
|
332
|
+
* Extracted from SyncCoordinator to isolate action concerns from
|
|
333
|
+
* push/pull sync orchestration.
|
|
334
|
+
*/
|
|
335
|
+
declare class ActionProcessor {
|
|
336
|
+
private readonly actionQueue;
|
|
337
|
+
private readonly transport;
|
|
338
|
+
private readonly clientId;
|
|
339
|
+
private readonly hlc;
|
|
340
|
+
private readonly maxRetries;
|
|
341
|
+
private onComplete;
|
|
342
|
+
constructor(config: {
|
|
343
|
+
actionQueue: ActionQueue;
|
|
344
|
+
transport: SyncTransport;
|
|
345
|
+
clientId: string;
|
|
346
|
+
hlc: HLC;
|
|
347
|
+
maxRetries: number;
|
|
348
|
+
});
|
|
349
|
+
/** Register a callback for action completion events. */
|
|
350
|
+
setOnComplete(cb: ActionCompleteCallback): void;
|
|
351
|
+
/**
|
|
352
|
+
* Submit an action for execution.
|
|
353
|
+
*
|
|
354
|
+
* Pushes the action to the ActionQueue and triggers immediate processing.
|
|
355
|
+
*/
|
|
356
|
+
enqueue(params: {
|
|
357
|
+
connector: string;
|
|
358
|
+
actionType: string;
|
|
359
|
+
params: Record<string, unknown>;
|
|
360
|
+
idempotencyKey?: string;
|
|
361
|
+
}): Promise<void>;
|
|
362
|
+
/**
|
|
363
|
+
* Process pending actions from the action queue.
|
|
364
|
+
*
|
|
365
|
+
* Peeks at pending entries, sends them to the gateway via
|
|
366
|
+
* `transport.executeAction()`, and acks/nacks based on the result.
|
|
367
|
+
* Dead-letters entries after `maxRetries` failures.
|
|
368
|
+
*/
|
|
369
|
+
processQueue(): Promise<void>;
|
|
370
|
+
/**
|
|
371
|
+
* Discover available connectors and their supported action types.
|
|
372
|
+
*
|
|
373
|
+
* Delegates to the transport's `describeActions()` method. Returns
|
|
374
|
+
* empty connectors when the transport does not support discovery.
|
|
375
|
+
*/
|
|
376
|
+
describeActions(): Promise<Result<ActionDiscovery, LakeSyncError>>;
|
|
377
|
+
/**
|
|
378
|
+
* List available connector types and their configuration schemas.
|
|
379
|
+
*
|
|
380
|
+
* Delegates to the transport's `listConnectorTypes()` method. Returns
|
|
381
|
+
* an empty array when the transport does not support it.
|
|
382
|
+
*/
|
|
383
|
+
listConnectorTypes(): Promise<Result<ConnectorDescriptor[], LakeSyncError>>;
|
|
256
384
|
}
|
|
257
385
|
|
|
258
386
|
/**
|
|
@@ -277,6 +405,29 @@ declare class MemoryQueue implements SyncQueue {
|
|
|
277
405
|
*/
|
|
278
406
|
declare function applyRemoteDeltas(db: LocalDB, deltas: RowDelta[], resolver: ConflictResolver, pendingQueue: SyncQueue): Promise<Result<number, LakeSyncError>>;
|
|
279
407
|
|
|
408
|
+
/**
|
|
409
|
+
* Manages the auto-sync lifecycle: periodic interval timer and
|
|
410
|
+
* visibility change handler.
|
|
411
|
+
*
|
|
412
|
+
* Extracted from SyncCoordinator to isolate timer/visibility concerns
|
|
413
|
+
* from sync orchestration logic.
|
|
414
|
+
*/
|
|
415
|
+
declare class AutoSyncScheduler {
|
|
416
|
+
private intervalId;
|
|
417
|
+
private visibilityHandler;
|
|
418
|
+
private readonly syncFn;
|
|
419
|
+
private readonly intervalMs;
|
|
420
|
+
constructor(syncFn: () => Promise<void>, intervalMs: number);
|
|
421
|
+
/** Whether auto-sync is currently running. */
|
|
422
|
+
get isRunning(): boolean;
|
|
423
|
+
/** Start periodic syncing and visibility-change-triggered sync. */
|
|
424
|
+
start(): void;
|
|
425
|
+
/** Stop periodic syncing and remove the visibility listener. */
|
|
426
|
+
stop(): void;
|
|
427
|
+
/** Register a visibility change listener to sync when the tab becomes visible. */
|
|
428
|
+
private setupVisibilitySync;
|
|
429
|
+
}
|
|
430
|
+
|
|
280
431
|
/**
|
|
281
432
|
* Synchronises local table schemas with server-provided schema versions.
|
|
282
433
|
*
|
|
@@ -498,4 +649,4 @@ declare class WebSocketTransport implements SyncTransport {
|
|
|
498
649
|
private sendAndAwaitResponse;
|
|
499
650
|
}
|
|
500
651
|
|
|
501
|
-
export { ActionQueue, ActionQueueEntry, CheckpointResponse, type CreateClientConfig, DbError, HttpTransport, type HttpTransportConfig, IDBActionQueue, IDBQueue, type LakeSyncClient, LocalDB, type LocalGateway, LocalTransport, MemoryActionQueue, MemoryQueue, QueueEntry, SchemaSynchroniser, SyncCoordinator, SyncCoordinatorConfig, SyncQueue, SyncTransport, WebSocketTransport, type WebSocketTransportConfig, applyRemoteDeltas, createClient, deleteSnapshot, getSchema, loadSnapshot, migrateSchema, registerSchema, saveSnapshot };
|
|
652
|
+
export { type ActionCompleteCallback, ActionProcessor, ActionQueue, ActionQueueEntry, AutoSyncScheduler, CheckpointResponse, type CreateClientConfig, DbError, HttpTransport, type HttpTransportConfig, IDBActionQueue, IDBQueue, type LakeSyncClient, LocalDB, type LocalGateway, LocalTransport, MemoryActionQueue, MemoryOutbox, MemoryQueue, type Outbox, type OutboxEntry, type OutboxEntryStatus, QueueEntry, SchemaSynchroniser, SyncCoordinator, SyncCoordinatorConfig, SyncQueue, SyncTransport, WebSocketTransport, type WebSocketTransportConfig, applyRemoteDeltas, createClient, deleteSnapshot, getSchema, loadSnapshot, migrateSchema, registerSchema, saveSnapshot };
|