@memberjunction/connector-eventbrite 1.0.0 → 2.0.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/dist/EventbriteConnector.d.ts +173 -147
- package/dist/EventbriteConnector.js +543 -389
- package/dist/EventbriteConnector.js.map +1 -1
- package/package.json +6 -3
|
@@ -1,178 +1,204 @@
|
|
|
1
1
|
import { type UserInfo } from '@memberjunction/core';
|
|
2
2
|
import type { MJCompanyIntegrationEntity, MJIntegrationObjectEntity } from '@memberjunction/core-entities';
|
|
3
|
-
import { BaseRESTIntegrationConnector, type RESTAuthContext, type RESTResponse, type PaginationState, type PaginationType, type ConnectionTestResult, type FetchContext, type FetchBatchResult, type RateLimitPolicy } from '@memberjunction/integration-engine';
|
|
3
|
+
import { BaseRESTIntegrationConnector, type RESTAuthContext, type RESTResponse, type PaginationState, type PaginationType, type ConnectionTestResult, type FetchContext, type FetchBatchResult, type RateLimitPolicy, type CreateRecordContext, type UpdateRecordContext, type DeleteRecordContext, type CRUDResult, type SourceSchemaInfo } from '@memberjunction/integration-engine';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Eventbrite events/ticketing connector — extends BaseRESTIntegrationConnector (REST/JSON over HTTP).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* (the resolved token lives in the credential store).
|
|
7
|
+
* Discovery, template-var parent traversal, and the paginated GET loop are inherited. This class supplies
|
|
8
|
+
* only the Eventbrite-specific protocol surface: Bearer auth, the continuation-token cursor, the
|
|
9
|
+
* `changed_since` incremental pull, connection testing, the write path (vendor-named path vars), and the
|
|
10
|
+
* §7/§10 sync-efficiency hooks the frozen contract evidences.
|
|
12
11
|
*/
|
|
13
|
-
export
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
* store (keys PrivateToken / Token / AccessToken / apiKey). Secrets never live in code.
|
|
17
|
-
*/
|
|
18
|
-
Token?: string;
|
|
12
|
+
export declare class EventbriteConnector extends BaseRESTIntegrationConnector {
|
|
13
|
+
/** Cached auth for the lifetime of a single sync run (Eventbrite tokens are long-lived, no refresh). */
|
|
14
|
+
private cachedAuth;
|
|
19
15
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
16
|
+
* The active incremental watermark for the object currently being fetched, stashed by the FetchChanges
|
|
17
|
+
* override so the (ctx-less) BuildPaginatedURL can append `changed_since`. Set at the top of an
|
|
18
|
+
* incremental FetchChanges, cleared in its finally. Safe because the engine drives one FetchChanges per
|
|
19
|
+
* object at a time (single-threaded async; no concurrent BuildPaginatedURL for a different watermark).
|
|
23
20
|
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
RequestTimeoutMs?: number;
|
|
27
|
-
/** Maximum retries for rate-limited / transient failures. Default: 4. */
|
|
28
|
-
MaxRetries?: number;
|
|
29
|
-
/** Minimum interval between outbound requests (ms). Default: 100. */
|
|
30
|
-
MinRequestIntervalMs?: number;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Connector for the Eventbrite Platform REST API v3.
|
|
34
|
-
*
|
|
35
|
-
* Authenticates via a Bearer token (private token or OAuth2 access token, resolved
|
|
36
|
-
* upstream and held in the credential store). Reads ride the base
|
|
37
|
-
* {@link BaseRESTIntegrationConnector} pull path; this class overrides only the
|
|
38
|
-
* genuinely Eventbrite-specific bits:
|
|
39
|
-
* - {@link BuildHeaders}: `Authorization: Bearer <token>` + `Accept: application/json`.
|
|
40
|
-
* - {@link GetBaseURL}: the shared `https://www.eventbriteapi.com/v3` host (or a
|
|
41
|
-
* non-secret `ApiBaseUrl` override for mock testing).
|
|
42
|
-
* - {@link NormalizeResponse}: unwraps the named-key list envelope (the IO's
|
|
43
|
-
* `ResponseDataKey`, e.g. `events`/`attendees`/`orders`) which sits alongside a
|
|
44
|
-
* `pagination` object; a bare object is a one-record detail; null → [].
|
|
45
|
-
* - {@link ExtractPaginationInfo} / {@link BuildPaginatedURL}: Eventbrite continuation-cursor
|
|
46
|
-
* pagination (`?continuation=<token>` + `pagination.has_more_items`/`.continuation`),
|
|
47
|
-
* plus the `changed_since=<watermark>` param for incremental objects (Order/Attendee) —
|
|
48
|
-
* fully metadata-driven (read `obj.IncrementalWatermarkField` + `obj.SupportsIncrementalSync`),
|
|
49
|
-
* NEVER keyed off a hardcoded object name.
|
|
50
|
-
* - {@link FetchChanges}: sets the watermark context, delegates to the base, then advances
|
|
51
|
-
* the watermark from the records' `changed` field on the final batch only (HasMore=false)
|
|
52
|
-
* so a partial-failure mid-pagination leaves the watermark unchanged.
|
|
53
|
-
*
|
|
54
|
-
* Create/Update/Delete use the generic per-operation column path
|
|
55
|
-
* (CreateAPIPath/Method/BodyShape/BodyKey/IDLocation, Update*, Delete*) driven entirely
|
|
56
|
-
* by the IO metadata — no per-verb override. Eventbrite uses POST for update (its
|
|
57
|
-
* convention) and wrapped bodies for most resources (CreateBodyKey =
|
|
58
|
-
* event|ticket_class|venue|discount|question|webhook|...). Parent template vars
|
|
59
|
-
* ({organization_id}/{event_id}) are resolved by the engine's parent-iteration from each
|
|
60
|
-
* IO's `Configuration.parentObjectName`.
|
|
61
|
-
*/
|
|
62
|
-
export declare class EventbriteConnector extends BaseRESTIntegrationConnector {
|
|
63
|
-
/** Cached auth context (token + resolved host). */
|
|
64
|
-
private authState;
|
|
65
|
-
/** Timestamp of the last outbound request, used for throttling. */
|
|
66
|
-
private lastRequestTime;
|
|
67
|
-
/** Watermark for the current FetchChanges cycle, emitted as the IO's incremental param. */
|
|
68
|
-
private currentWatermark;
|
|
69
|
-
/** Verbatim from the metadata Integration row — part of the three-way name invariant. */
|
|
21
|
+
private activeChangedSince;
|
|
22
|
+
/** Verbatim `MJ: Integrations.Name`. Load-bearing: the T1 three-way name check compares this === metadata Name. */
|
|
70
23
|
get IntegrationName(): string;
|
|
71
24
|
get SupportsCreate(): boolean;
|
|
72
25
|
get SupportsUpdate(): boolean;
|
|
73
26
|
get SupportsDelete(): boolean;
|
|
74
27
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
28
|
+
* Discovery is NON-authoritative: DiscoverObjects / IntrospectSchema are cache-driven (they re-read
|
|
29
|
+
* persisted ACTIVE Declared metadata, NOT a live full-gamut enumeration). Eventbrite publishes no
|
|
30
|
+
* schema/describe/introspection endpoint enumerating everything a credential can access, so absence in a
|
|
31
|
+
* refresh proves nothing → never deactivate. Matches Configuration.DiscoveryIsAuthoritative=false.
|
|
77
32
|
*/
|
|
78
|
-
get
|
|
33
|
+
get DiscoveryIsAuthoritative(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* IntrospectSchema — pure WIRING of MJ's existing sampler into the declared catalog (the connector
|
|
36
|
+
* sample-union standard; see CONNECTOR_DISCOVERY_STANDARD.md). This connector adds NO discovery,
|
|
37
|
+
* merge, or sync logic — it only wires `DiscoverFieldsViaFetch` (MJ's sampler) into IntrospectSchema.
|
|
38
|
+
*
|
|
39
|
+
* `super.IntrospectSchema` yields the cache-driven Declared catalog (no measured widths). For each
|
|
40
|
+
* object we then call MJ's `DiscoverFieldsViaFetch` — MJ's own read-path sampler that measures real
|
|
41
|
+
* field widths and surfaces custom columns — and the shared PURE `mergeDeclaredWithSampledFields`
|
|
42
|
+
* unions the two by field name (adopt MJ's measured width; append MJ-discovered custom columns). MJ
|
|
43
|
+
* owns everything else (measurement, type/PK inference, persistence, reconcile, sync).
|
|
44
|
+
*
|
|
45
|
+
* Recursion note: `DiscoverFieldsViaFetch` falls back to the UNCHANGED `DiscoverFields` (cache-driven)
|
|
46
|
+
* when the read path can't run — never back into THIS method — so there is no infinite recursion.
|
|
47
|
+
* This connector does NOT override `DiscoverFields` to call any ViaFetch/ViaStream.
|
|
48
|
+
*
|
|
49
|
+
* Robustness: objects are sampled IN PARALLEL under a small bounded pool; any per-object failure
|
|
50
|
+
* keeps that object's declared fields, so a single bad sample never breaks introspection.
|
|
51
|
+
*/
|
|
52
|
+
IntrospectSchema(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<SourceSchemaInfo>;
|
|
79
53
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* the same sync), the base default of 10 parents costs ~37 s and blows the 30 s FetchChanges
|
|
84
|
-
* op-timeout — the batch is then abandoned and the object syncs 0 records for any org with that
|
|
85
|
-
* many events. A batch of 4 costs ~15 s (well under 30 s) and the engine resumes the remaining
|
|
86
|
-
* parents via HasMore/keyset, so a high-event-count org still syncs completely.
|
|
54
|
+
* From Configuration.RateLimitPolicy: 2,000 calls/hour per token (blueprint ## Errors, 429
|
|
55
|
+
* HIT_RATE_LIMIT). 2000/3600 ≈ 0.556 tokens/sec sustained. Burst kept small (the hourly ceiling is the
|
|
56
|
+
* real constraint; there is no documented per-second burst allowance).
|
|
87
57
|
*/
|
|
88
|
-
|
|
89
|
-
/** Parse Eventbrite's Retry-After header (delta-seconds or HTTP-date) into milliseconds. */
|
|
90
|
-
ExtractRetryAfterMs(error: unknown): number | undefined;
|
|
58
|
+
get RateLimitPolicy(): RateLimitPolicy | null;
|
|
91
59
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
60
|
+
* The frozen contract records NO Retry-After header shape for Eventbrite's 429 (HIT_RATE_LIMIT)
|
|
61
|
+
* (Configuration.RateLimitPolicy.retryAfterHeaderDocumented=false), so there is nothing to parse
|
|
62
|
+
* reliably. Left as the base default (undefined) rather than guessing a header name — the engine's AIMD
|
|
63
|
+
* bucket backs off on the 429 regardless. Documented as a soft gap for live-probe confirmation.
|
|
94
64
|
*/
|
|
95
|
-
|
|
65
|
+
/** Conservative in-flight cap. The 2,000/hour ceiling is the real limiter; a low cap avoids bursts. */
|
|
66
|
+
get MaxConcurrencyHint(): number | null;
|
|
96
67
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* `changed` field on the FINAL batch only (HasMore=false) so a partial-failure
|
|
101
|
-
* mid-pagination leaves the watermark unchanged.
|
|
68
|
+
* No-watermark objects resume by their StableOrderingKey — read from the IO metadata when the extractor
|
|
69
|
+
* emitted one, else the object's PK (Eventbrite's universal `id`). Returns null when the object has no
|
|
70
|
+
* stable key or the cache is unavailable (unit-test context).
|
|
102
71
|
*/
|
|
103
|
-
|
|
72
|
+
StableOrderingKey(objectName: string): string | null;
|
|
104
73
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* the IO's `IncrementalWatermarkField`); we take the max so the next run's `changed_since`
|
|
108
|
-
* resumes from there.
|
|
74
|
+
* Resolves the pre-minted Bearer token from the linked Credential entity (preferred) or the
|
|
75
|
+
* CompanyIntegration Configuration JSON (fallback). Cached for the run.
|
|
109
76
|
*/
|
|
110
|
-
private ExtractLatestWatermark;
|
|
111
77
|
protected Authenticate(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<RESTAuthContext>;
|
|
112
|
-
/**
|
|
78
|
+
/** Eventbrite OAuth2 auth: a pre-minted Bearer token. No signing, no crypto. */
|
|
113
79
|
protected BuildHeaders(auth: RESTAuthContext): Record<string, string>;
|
|
80
|
+
/** HTTP transport (fetch). Owns the wire boundary; test subclasses override this to capture requests. */
|
|
81
|
+
protected MakeHTTPRequest(_auth: RESTAuthContext, url: string, method: string, headers: Record<string, string>, body?: unknown): Promise<RESTResponse>;
|
|
114
82
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
83
|
+
* Strips the Eventbrite list envelope. Each list endpoint nests records under a plural snake_case
|
|
84
|
+
* resource key (`events`, `attendees`, `orders`, …), stored per-IO as ResponseDataKey. When
|
|
85
|
+
* ResponseDataKey is unset (the extractor left it null), the key is DERIVED from the last non-templated
|
|
86
|
+
* path segment of the APIPath — but NormalizeResponse doesn't have the IO here, so the fallback scans the
|
|
87
|
+
* envelope for the sole array-valued key alongside `pagination`. A bare-array or single-object body (the
|
|
88
|
+
* get-one / non-paginated shape) is handled directly.
|
|
121
89
|
*/
|
|
122
90
|
protected NormalizeResponse(rawBody: unknown, responseDataKey: string | null): Record<string, unknown>[];
|
|
123
|
-
private coerceToArray;
|
|
124
|
-
private isRecord;
|
|
125
91
|
/**
|
|
126
|
-
*
|
|
127
|
-
* `has_more_items`
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
|
|
92
|
+
* Eventbrite pagination is the CONTINUATION-TOKEN scheme (NOT page-number/offset). Read
|
|
93
|
+
* `pagination.has_more_items` and `pagination.continuation` from the envelope. When has_more_items is
|
|
94
|
+
* true AND a continuation token is present, the next page is requested with that token; otherwise the set
|
|
95
|
+
* is exhausted. Source: Configuration.PaginationDefaults.advanceProtocol.
|
|
96
|
+
* currentPage/offset/pageSize are unused for continuation pagination.
|
|
97
|
+
*/
|
|
98
|
+
protected ExtractPaginationInfo(rawBody: unknown, _paginationType: PaginationType, _currentPage: number, _currentOffset: number, _pageSize: number): PaginationState;
|
|
99
|
+
/**
|
|
100
|
+
* Eventbrite v3 host. Defaults to the fixed `https://www.eventbriteapi.com/v3` host (the version
|
|
101
|
+
* segment is part of the base URL; metadata APIPaths are relative). Honors a
|
|
102
|
+
* `CompanyIntegration.Configuration.BaseURL` override when present — used for region redirects and
|
|
103
|
+
* for pointing the connector at a mock ORIGIN server in credential-free e2e testing without touching
|
|
104
|
+
* the vendor's real endpoint. Falls back to the fixed host on absence or malformed Configuration.
|
|
105
|
+
*/
|
|
106
|
+
protected GetBaseURL(companyIntegration?: MJCompanyIntegrationEntity): string;
|
|
107
|
+
/**
|
|
108
|
+
* Eventbrite pages via the `continuation` query param (NOT the base default `cursor=`). The first page
|
|
109
|
+
* sends no continuation token; subsequent pages send `continuation=<token>`. When an incremental
|
|
110
|
+
* watermark is active (Attendee/Order this run), `changed_since=<watermark>` is appended so the API
|
|
111
|
+
* returns only records changed after the watermark. Eventbrite has no client-controlled page-size param
|
|
112
|
+
* on these list endpoints (page_size is server-fixed and reported in the envelope), so no limit is sent.
|
|
132
113
|
*/
|
|
133
|
-
protected
|
|
114
|
+
protected BuildPaginatedURL(basePath: string, _obj: MJIntegrationObjectEntity, _page: number, _offset: number, cursor?: string, _effectivePageSize?: number): string;
|
|
134
115
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
116
|
+
* OVERRIDDEN to (1) inject the `changed_since` param for the two incremental objects (Attendee, Order —
|
|
117
|
+
* SupportsIncrementalSync + a watermark this run) and (2) EMIT the new watermark. The base flat/template
|
|
118
|
+
* fetch path threads no watermark into the URL and returns no NewWatermarkValue, so the connector owns
|
|
119
|
+
* both. All fetching (continuation pagination, template-var parent traversal) is delegated to the base;
|
|
120
|
+
* this override only sets activeChangedSince around the super call and computes the watermark on a fully
|
|
121
|
+
* drained batch.
|
|
141
122
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
*
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
123
|
+
* Partial-failure safety: NewWatermarkValue is emitted ONLY when the whole object is drained
|
|
124
|
+
* (HasMore=false). A mid-stream batch (HasMore=true — more parents to iterate) advances no watermark, so a
|
|
125
|
+
* failure between batches resumes from the unchanged prior watermark. When the final batch's max `changed`
|
|
126
|
+
* is below an earlier batch's, the watermark under-advances (worst case re-fetches already-seen records
|
|
127
|
+
* next run — idempotent, safe) rather than skipping records (data loss).
|
|
128
|
+
*/
|
|
129
|
+
FetchChanges(ctx: FetchContext): Promise<FetchBatchResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Create: substitutes the create path's parent vars from Attributes/Relationships (create paths carry
|
|
132
|
+
* only parent vars — the record has no id yet), POSTs the body shaped per CreateBodyShape/CreateBodyKey,
|
|
133
|
+
* and routes the result through BuildCreatedResult so a 2xx with no usable id FAILS LOUDLY.
|
|
134
|
+
*/
|
|
135
|
+
CreateRecord(ctx: CreateRecordContext): Promise<CRUDResult>;
|
|
136
|
+
/**
|
|
137
|
+
* Update: substitutes the record's own id (ExternalID) into the LAST path var and any parent vars from
|
|
138
|
+
* Attributes/Relationships, then POSTs the wrapped body (Eventbrite uses POST, not PATCH/PUT, for update).
|
|
139
|
+
*/
|
|
140
|
+
UpdateRecord(ctx: UpdateRecordContext): Promise<CRUDResult>;
|
|
141
|
+
/**
|
|
142
|
+
* Delete: substitutes the record's own id (ExternalID) into the last path var and any parent vars, then
|
|
143
|
+
* issues DeleteMethod (metadata-driven — Eventbrite uses hard DELETE, but the verb is read from metadata,
|
|
144
|
+
* not assumed).
|
|
145
|
+
*/
|
|
146
|
+
DeleteRecord(ctx: DeleteRecordContext): Promise<CRUDResult>;
|
|
147
|
+
/**
|
|
148
|
+
* Tests the connection by hitting the current-user endpoint (`/users/me/`). A 2xx confirms the Bearer
|
|
149
|
+
* token is valid; 401/403 → auth failure; anything else → error.
|
|
150
|
+
*/
|
|
151
|
+
TestConnection(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<ConnectionTestResult>;
|
|
152
|
+
/** Reads the Bearer token from the linked Credential entity, or the Configuration JSON fallback. */
|
|
153
|
+
private LoadCredentials;
|
|
154
|
+
/** Loads a credential row and parses its Values JSON. */
|
|
155
|
+
private LoadFromCredentialEntity;
|
|
156
|
+
/** Extracts an Eventbrite token from a credential/config JSON string. Returns null when no token is present. */
|
|
157
|
+
private ParseCredentialJson;
|
|
158
|
+
/**
|
|
159
|
+
* Substitutes EVERY `{var}` in a write path. The record's own id (recordID, when provided) fills the
|
|
160
|
+
* generic `{ID}`/`{id}`/`{ExternalID}` placeholders AND the LAST vendor-named var in the path (the
|
|
161
|
+
* record's own id segment for update/delete, e.g. `{ticket_class_id}` in
|
|
162
|
+
* `/events/{event_id}/ticket_classes/{ticket_class_id}/`). Every OTHER var is a parent id resolved from
|
|
163
|
+
* the resolution map (Attributes ∪ Relationships), matched case-insensitively. Returns the resolved path
|
|
164
|
+
* plus the list of vars that could NOT be resolved (caller fails loudly on a non-empty list).
|
|
165
|
+
*/
|
|
166
|
+
private SubstituteAllPathVars;
|
|
167
|
+
/**
|
|
168
|
+
* A delete carries no Attributes, so a child-object delete path with a parent var (e.g.
|
|
169
|
+
* `/events/{event_id}/ticket_classes/{...}`) has no place to source the parent id — EXCEPT the composite
|
|
170
|
+
* ExternalID. When the path has >1 var, the ExternalID is expected as `parentId|...|recordId` (the base's
|
|
171
|
+
* composite-PK ExternalID form): the trailing segment is the record id, the leading segments fill the
|
|
172
|
+
* parent vars in path order. When the path has ≤1 var, the whole ExternalID is the record id.
|
|
173
|
+
*/
|
|
174
|
+
private SplitCompositeExternalID;
|
|
175
|
+
/** Detects `{var}` placeholders in a path. */
|
|
176
|
+
private DetectPathVars;
|
|
177
|
+
/** Builds a case-insensitive lookup map of parent-id candidates from Attributes ∪ Relationships. */
|
|
178
|
+
private BuildResolutionMap;
|
|
179
|
+
/** Builds a consistent unresolved-var CRUD failure result (never a broken URL to the wire). */
|
|
180
|
+
private UnresolvedVarError;
|
|
181
|
+
/**
|
|
182
|
+
* Formats a watermark value into the `changed_since` datetime the API expects (UTC ISO-8601). Accepts an
|
|
183
|
+
* ISO string (passed through) or an epoch-ms string (converted). Eventbrite documents `changed_since` as
|
|
184
|
+
* a UTC datetime; passing an unparseable value through unchanged lets the API reject it loudly rather than
|
|
185
|
+
* silently widening the window.
|
|
186
|
+
*/
|
|
187
|
+
private FormatChangedSince;
|
|
188
|
+
/**
|
|
189
|
+
* Computes the new watermark = the max `changed` timestamp across the fetched records, floored at the
|
|
190
|
+
* incoming watermark so it never regresses. Records that don't carry the field are skipped. Returns the
|
|
191
|
+
* incoming watermark unchanged when no record advances it (idempotent no-op next run).
|
|
192
|
+
*/
|
|
193
|
+
private MaxWatermark;
|
|
194
|
+
/** Parses a watermark (ISO datetime or epoch-ms string) to epoch ms; 0 when unparseable/empty. */
|
|
195
|
+
private ToMs;
|
|
196
|
+
/** Returns the first present, non-empty string value among the given keys. */
|
|
197
|
+
private FirstString;
|
|
198
|
+
/**
|
|
199
|
+
* Resolves an IO by name from the engine cache (via this integration's id) without throwing. Returns null
|
|
200
|
+
* when the cache is unavailable (unit-test context) or the object isn't found — StableOrderingKey then
|
|
201
|
+
* degrades to null, a safe default (the engine simply doesn't use keyset resume for that object).
|
|
202
|
+
*/
|
|
203
|
+
private TryGetActiveObject;
|
|
176
204
|
}
|
|
177
|
-
/** Tree-shaking prevention function — import and call from the package entry point. */
|
|
178
|
-
export declare function LoadEventbriteConnector(): void;
|