@memberjunction/connector-openwater 1.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.
@@ -0,0 +1,172 @@
1
+ import { type UserInfo } from '@memberjunction/core';
2
+ import type { MJCompanyIntegrationEntity, MJIntegrationObjectEntity } from '@memberjunction/core-entities';
3
+ import { BaseRESTIntegrationConnector, type RESTAuthContext, type RESTResponse, type PaginationState, type PaginationType, type ConnectionTestResult, type DefaultIntegrationConfig, type FetchContext, type FetchBatchResult, type RateLimitPolicy, type CreateRecordContext, type UpdateRecordContext, type DeleteRecordContext, type CRUDResult } from '@memberjunction/integration-engine';
4
+ /**
5
+ * Resolved OpenWater connection configuration. ClientKey + ApiKey are required;
6
+ * OrganizationCode + BaseURL are optional.
7
+ */
8
+ export interface OpenWaterConnectionConfig {
9
+ /** X-ClientKey header value. */
10
+ ClientKey: string;
11
+ /** X-ApiKey header value (the secret). */
12
+ ApiKey: string;
13
+ /** X-OrganizationCode header value (optional, multi-org tenants). */
14
+ OrganizationCode?: string;
15
+ /** API base URL. Defaults to the OpenWater public API host. */
16
+ BaseURL?: string;
17
+ /** Maximum retries for rate-limited / transient failures. Default 3. */
18
+ MaxRetries?: number;
19
+ /** HTTP request timeout in milliseconds. Default 30000. */
20
+ RequestTimeoutMs?: number;
21
+ }
22
+ export declare class OpenWaterConnector extends BaseRESTIntegrationConnector {
23
+ private authState;
24
+ get IntegrationName(): string;
25
+ get SupportsCreate(): boolean;
26
+ get SupportsUpdate(): boolean;
27
+ get SupportsDelete(): boolean;
28
+ /** OpenWater's modest enterprise throughput; engine runs an AIMD token bucket from this. */
29
+ get RateLimitPolicy(): RateLimitPolicy;
30
+ /** Parse a Retry-After header (seconds, or an HTTP-date) into milliseconds. */
31
+ ExtractRetryAfterMs(error: unknown): number | undefined;
32
+ private ReadRetryAfterHeader;
33
+ protected Authenticate(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<RESTAuthContext>;
34
+ /** Dual custom-header auth: X-ClientKey + X-ApiKey on every request; X-OrganizationCode when present. */
35
+ protected BuildHeaders(auth: RESTAuthContext): Record<string, string>;
36
+ protected MakeHTTPRequest(auth: RESTAuthContext, url: string, method: string, headers: Record<string, string>, body?: unknown): Promise<RESTResponse>;
37
+ /**
38
+ * OpenWater v2 list endpoints return a paged envelope { records: [...], pageIndex, pageSize,
39
+ * totalRecords } or a bare array. NormalizeResponse unwraps to the record array.
40
+ */
41
+ protected NormalizeResponse(rawBody: unknown, responseDataKey: string | null): Record<string, unknown>[];
42
+ /**
43
+ * PageNumber pagination over OpenWater's pageIndex/pageSize. Advances pageIndex until a
44
+ * short/empty page (records.length < requested pageSize) signals the last page.
45
+ */
46
+ protected ExtractPaginationInfo(rawBody: unknown, paginationType: PaginationType, currentPage: number, currentOffset: number, pageSize: number): PaginationState;
47
+ private ReadTotalRecords;
48
+ /**
49
+ * OpenWater uses page=/pageSize= by default in the base loop, but the API's param names are
50
+ * pageIndex/pageSize. Override to emit the vendor's actual param names.
51
+ */
52
+ protected BuildPaginatedURL(basePath: string, obj: MJIntegrationObjectEntity, page: number, offset: number, cursor?: string, effectivePageSize?: number): string;
53
+ protected GetBaseURL(_companyIntegration: MJCompanyIntegrationEntity, auth: RESTAuthContext): string;
54
+ TestConnection(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<ConnectionTestResult>;
55
+ FetchChanges(ctx: FetchContext): Promise<FetchBatchResult>;
56
+ CreateRecord(ctx: CreateRecordContext): Promise<CRUDResult>;
57
+ UpdateRecord(ctx: UpdateRecordContext): Promise<CRUDResult>;
58
+ DeleteRecord(ctx: DeleteRecordContext): Promise<CRUDResult>;
59
+ /**
60
+ * Session create — Models.Session.CreateRequest requires {programId, typeId, name}. The synced
61
+ * list-model carries typeName (string), not typeId (int). Resolve typeId from an explicit typeId
62
+ * attribute when supplied; otherwise look it up by name against the SessionType IO (which is
63
+ * program-scoped, so we match within the record's programId).
64
+ */
65
+ private CreateSession;
66
+ /**
67
+ * JudgeAssignment create — Models.JudgeAssignment.AssignJudgeToRoundRequest requires
68
+ * {judgeUserId, roundId}. judgeUserId <- the synced userId; roundId from the create attributes'
69
+ * round context (tagged onto the synced record by the AccessPath walk, or passed explicitly).
70
+ * CreateIDLocation='n/a' → there is no body id; the stable identity is the (roundId, judgeUserId)
71
+ * pair, so BuildCreatedResult is fed the synthetic composite id roundId|judgeUserId.
72
+ */
73
+ private CreateJudgeAssignment;
74
+ private DeleteJudgeAssignment;
75
+ /**
76
+ * ScheduleTimeSlot create — Models.ScheduleTimeSlot.CreateRequest requires
77
+ * {name, code, startTime, endTime, scheduleDayIds}. The read-side IOF is availableOnlyInDayIds;
78
+ * map it (or an explicit scheduleDayIds) into scheduleDayIds. The path is program-scoped, so the
79
+ * generic path is bypassed and the {programId} template is filled from the attributes.
80
+ */
81
+ private CreateScheduleTimeSlot;
82
+ /**
83
+ * ScheduleTimeSlot update — Models.ScheduleTimeSlot.UpdateRequest mirrors the create shape and
84
+ * also requires scheduleDayIds (mapped from availableOnlyInDayIds). The update path is keyed by
85
+ * the time-slot id (not program-scoped): PATCH /v2/Programs/Scheduler/TimeSlots/{scheduleTimeSlotId}.
86
+ */
87
+ private UpdateScheduleTimeSlot;
88
+ /** Shared body for ScheduleTimeSlot create/update: maps availableOnlyInDayIds -> scheduleDayIds. */
89
+ private BuildTimeSlotBody;
90
+ /** Resolve a SessionType id: explicit typeId attribute, else lookup by typeName in the SessionType IO. */
91
+ private ResolveSessionTypeId;
92
+ /** POST a hand-built create body and route the result through BuildCreatedResult (id from body). */
93
+ private PostCreate;
94
+ private RequireNumber;
95
+ /** First parseable number among candidate keys (case-tolerant), or null. */
96
+ private FirstNumber;
97
+ private CopyOptional;
98
+ private FailedResult;
99
+ /**
100
+ * Flat/door fetch with incremental watermark applied. Reuses the base pagination loop by
101
+ * temporarily folding the watermark param into the IO's DefaultQueryParams-equivalent via a
102
+ * one-shot manual paginated loop (so the watermark rides every page request).
103
+ */
104
+ private FetchDoor;
105
+ /**
106
+ * Walks the per-IO AccessPath: query the door, descend the nesting segments to the leaf parent
107
+ * ids, then fetch the entry path once per parent (id in path template or query param), unioning
108
+ * any alternativePaths. An `embedded-array` access path emits records straight from the door.
109
+ */
110
+ private FetchViaAccessPath;
111
+ /** Fetch all pages of a door collection (used to enumerate parent ids / embedded children). */
112
+ private FetchDoorRows;
113
+ /**
114
+ * Generic paginated leaf fetch. Loops pageIndex until a short/empty page (or the batch cap when
115
+ * `ctx` is supplied), tracking the max watermark seen across the IO's IncrementalWatermarkField.
116
+ * `forceFullScan` ignores the batch cap (used when enumerating door parents).
117
+ */
118
+ private PaginateLeaf;
119
+ /** Reads and validates AccessPath from the IO's Configuration JSON; null when absent. */
120
+ private ParseAccessPath;
121
+ /**
122
+ * Descends the door rows along the nesting segments to the list of parent ids that get injected
123
+ * into the leaf entry path. For `rounds[]` this yields each round's id; for a direct programId
124
+ * parent (no nesting) it yields each door row's `id`.
125
+ */
126
+ private DescendToParentIDs;
127
+ /** Walks the door rows down a chain of (array) field segments, returning the leaf object nodes. */
128
+ private WalkSegments;
129
+ /** For embedded-array access paths: emit the nested records directly from the door payload. */
130
+ private ExtractEmbedded;
131
+ /**
132
+ * Injects a parent id into an entry path: as a query param (?<parentParamName>=) when
133
+ * parentParamIn='query' (the roundId-gated endpoints, which 400 without it), otherwise into the
134
+ * {parentParamName} path template. Returns null when a path template var is present but unset
135
+ * (so an alternativePath that uses a different var is skipped, not mis-substituted).
136
+ */
137
+ private InjectParentID;
138
+ /** Builds the incremental watermark query fragment (e.g. lastModifiedSinceUtc=2026-01-01T...). */
139
+ private BuildWatermarkParam;
140
+ private AppendQuery;
141
+ /**
142
+ * Builds an ExternalRecord. Fields carries the FULL source record (custom-column pass-through);
143
+ * runs the TransformRecord-preserving pipeline; resolves the ExternalID from the declared PK
144
+ * (composite-aware) with a content-hash fallback for partial/missing keys.
145
+ */
146
+ private BuildExternalRecord;
147
+ private PrimaryKeyNames;
148
+ /** Deterministic fallback identity for partial/missing keys (FNV-1a over the canonical JSON). */
149
+ private ContentHash;
150
+ GetDefaultConfiguration(): DefaultIntegrationConfig;
151
+ private GetAuth;
152
+ private ParseConfig;
153
+ private ParseConfigFromCredential;
154
+ /** Overlay non-secret config (BaseURL / OrganizationCode) from the CompanyIntegration JSON onto a credential-derived config. */
155
+ private MergeConfigJson;
156
+ /**
157
+ * Resolves the connection config from a credential / configuration value bag. ClientKey + ApiKey
158
+ * are required unless `lenient` (used when overlaying optional config JSON onto a credential).
159
+ */
160
+ private ExtractConfig;
161
+ private ExecuteFetch;
162
+ private BuildRESTResponse;
163
+ private ParseJsonSafely;
164
+ private ShouldRetry;
165
+ private ComputeRetryDelay;
166
+ /** Wraps an error message with the response Status + Headers so ExtractRetryAfterMs can read them. */
167
+ private HttpError;
168
+ private Sleep;
169
+ private StripTrailingSlash;
170
+ }
171
+ /** Tree-shaking prevention — import and call from the module entry point. */
172
+ export declare function LoadOpenWaterConnector(): void;
@@ -0,0 +1,903 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * OpenWaterConnector — REST integration connector for OpenWater
9
+ * (https://www.getopenwater.com), an awards / grants / abstracts / fellowship
10
+ * submission-and-review platform. The connector targets OpenWater's v2 REST API.
11
+ *
12
+ * Auth — DUAL custom headers on EVERY request (no token exchange; the
13
+ * Account/Authenticate endpoint is out of scope):
14
+ * - X-ClientKey (config: ClientKey)
15
+ * - X-ApiKey (config secret: ApiKey)
16
+ * - X-OrganizationCode (config: OrganizationCode, OPTIONAL)
17
+ *
18
+ * Pagination — PageNumber (pageIndex / pageSize); advance pageIndex until a
19
+ * short/empty page.
20
+ *
21
+ * Incremental — per-IO IncrementalWatermarkField (lastModifiedSinceUtc /
22
+ * createdSinceUtc / deletedSinceUtc / lastModifiedUtc / mostRecentTransactionSinceUtc)
23
+ * formatted into the request query.
24
+ *
25
+ * Nested objects — OpenWater's object universe is larger than its directly-
26
+ * queryable doors. Each nested IO carries an AccessPath in its IntegrationObject
27
+ * Configuration { door, doorPath, parentParamName, nestingSegments[], entryPath,
28
+ * parentParamIn, extractionMode, alternativePaths[] }. FetchChanges WALKS that path:
29
+ * it queries the door, descends to the leaf parent IDs (e.g. Program -> rounds[] ->
30
+ * roundId), then calls the entry path once per parent — injecting the parent id either
31
+ * into the path template ({programId}/{fundId}) or as a query param (roundId-gated
32
+ * JudgeAssignments/Recusals, which 400 without it). An `embedded-array` AccessPath
33
+ * (Rounds) emits records directly from the door payload with no second call.
34
+ *
35
+ * Discovery — credential-free: DiscoverObjects/DiscoverFields/IntrospectSchema use the
36
+ * BaseRESTIntegrationConnector implementations, which read the Declared IO/IOF metadata
37
+ * from the IntegrationEngineBase cache. No catalog is baked into this file.
38
+ *
39
+ * Write — generic per-operation CRUD (Create/Update/Delete read from the IO's
40
+ * CreateAPIPath/Method/BodyShape/IDLocation, Update*, Delete* columns) for the FLAT-body
41
+ * write IOs (Application, JudgeTeam, User, Evaluation, ScheduleDay/Item/Room). THREE IOs
42
+ * declare CreateBodyShape='literal' because their create-request schema needs fields absent
43
+ * from the synced list-model, so CreateRecord is overridden for them (each still routes
44
+ * through BuildCreatedResult; each IO's Configuration.LiteralCreateReason documents the
45
+ * mapping):
46
+ * - Session → POST /v2/Sessions {programId, typeId, name, ...}; typeId resolved
47
+ * from the synced typeName via the SessionType IO (or a typeId input),
48
+ * per Models.Session.CreateRequest.
49
+ * - JudgeAssignment → POST /v2/JudgeAssignments/Round {judgeUserId, roundId}; judgeUserId
50
+ * <- record.userId, roundId from the create attributes' round context,
51
+ * per Models.JudgeAssignment.AssignJudgeToRoundRequest. CreateIDLocation
52
+ * /DeleteIDLocation = 'n/a' (no body id) → synthetic composite identity
53
+ * roundId|judgeUserId. Delete re-uses the same /Round endpoint with the
54
+ * pair as query params (DELETE has no path id).
55
+ * - ScheduleTimeSlot→ POST/PATCH supply scheduleDayIds (from the read-side availableOnlyInDayIds),
56
+ * per Models.ScheduleTimeSlot.Create/UpdateRequest. ScheduleTimeSlot also
57
+ * declares UpdateBodyShape='literal', so UpdateRecord is overridden too.
58
+ * All other write IOs (incl. the lifecycle PATCHes Forwarding/WinnerAssignment/Status, which
59
+ * are NOT in the frozen contract) use the generic per-operation path unchanged. These literal
60
+ * write paths are untestable credential-free → RequiresLiveVerification (T10).
61
+ */
62
+ import { RegisterClass } from '@memberjunction/global';
63
+ import { Metadata } from '@memberjunction/core';
64
+ import { BaseIntegrationConnector, BaseRESTIntegrationConnector, } from '@memberjunction/integration-engine';
65
+ // ─── Constants ──────────────────────────────────────────────────────────
66
+ // No DEFAULT_BASE_URL: OpenWater is tenant-specific (per-customer host on *.secure-platform.com);
67
+ // the legacy api.getopenwater.com host does NOT resolve. BaseURL is REQUIRED — see GetAuth().
68
+ const DEFAULT_PAGE_SIZE = 100;
69
+ const DEFAULT_MAX_RETRIES = 3;
70
+ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
71
+ /** OpenWater is a modest-throughput enterprise API — keep a conservative sustained rate. */
72
+ const RATE_LIMIT_TOKENS_PER_SEC = 3;
73
+ // ─── Connector ──────────────────────────────────────────────────────────
74
+ let OpenWaterConnector = class OpenWaterConnector extends BaseRESTIntegrationConnector {
75
+ constructor() {
76
+ super(...arguments);
77
+ this.authState = null;
78
+ }
79
+ // ── Identity (three-way invariant axis) ─────────────────────────
80
+ get IntegrationName() { return 'OpenWater'; }
81
+ // ── Capability flags ─────────────────────────────────────────────
82
+ // The per-IO write columns (SupportsCreate/Update/Delete + Create/Update/Delete*
83
+ // metadata) drive the generic CRUD path; these getters report that the connector
84
+ // CAN write so the engine attempts the per-IO verbs the metadata configures.
85
+ get SupportsCreate() { return true; }
86
+ get SupportsUpdate() { return true; }
87
+ get SupportsDelete() { return true; }
88
+ // ── Sync-efficiency hooks ────────────────────────────────────────
89
+ /** OpenWater's modest enterprise throughput; engine runs an AIMD token bucket from this. */
90
+ get RateLimitPolicy() {
91
+ return { TokensPerSec: RATE_LIMIT_TOKENS_PER_SEC };
92
+ }
93
+ /** Parse a Retry-After header (seconds, or an HTTP-date) into milliseconds. */
94
+ ExtractRetryAfterMs(error) {
95
+ const retryAfter = this.ReadRetryAfterHeader(error);
96
+ if (retryAfter == null)
97
+ return undefined;
98
+ const seconds = Number.parseInt(retryAfter, 10);
99
+ if (Number.isFinite(seconds) && seconds > 0)
100
+ return seconds * 1000;
101
+ const when = Date.parse(retryAfter);
102
+ if (Number.isFinite(when)) {
103
+ const delta = when - Date.now();
104
+ return delta > 0 ? delta : 0;
105
+ }
106
+ return undefined;
107
+ }
108
+ ReadRetryAfterHeader(error) {
109
+ if (!error || typeof error !== 'object')
110
+ return undefined;
111
+ const e = error;
112
+ const status = e.Status ?? e.status;
113
+ if (status != null && status !== 429 && status !== 503)
114
+ return undefined;
115
+ const headers = e.Headers ?? e.headers;
116
+ if (!headers)
117
+ return undefined;
118
+ return headers['retry-after'] ?? headers['Retry-After'];
119
+ }
120
+ // ── Auth + transport (abstract methods) ─────────────────────────
121
+ async Authenticate(companyIntegration, contextUser) {
122
+ return this.GetAuth(companyIntegration, contextUser);
123
+ }
124
+ /** Dual custom-header auth: X-ClientKey + X-ApiKey on every request; X-OrganizationCode when present. */
125
+ BuildHeaders(auth) {
126
+ const config = auth.Config;
127
+ const headers = {
128
+ 'X-ClientKey': config.ClientKey,
129
+ 'X-ApiKey': config.ApiKey,
130
+ 'Accept': 'application/json',
131
+ 'User-Agent': 'MemberJunction-Integration/1.0',
132
+ };
133
+ if (config.OrganizationCode)
134
+ headers['X-OrganizationCode'] = config.OrganizationCode;
135
+ return headers;
136
+ }
137
+ async MakeHTTPRequest(auth, url, method, headers, body) {
138
+ const config = auth.Config;
139
+ const maxRetries = config.MaxRetries ?? DEFAULT_MAX_RETRIES;
140
+ const timeoutMs = config.RequestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
141
+ const effectiveHeaders = { ...headers };
142
+ if (body !== undefined && method !== 'GET' && method !== 'DELETE' && !effectiveHeaders['Content-Type']) {
143
+ effectiveHeaders['Content-Type'] = 'application/json';
144
+ }
145
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
146
+ const response = await this.ExecuteFetch(url, method, effectiveHeaders, body, timeoutMs);
147
+ if (this.ShouldRetry(response.status) && attempt < maxRetries) {
148
+ await this.Sleep(this.ComputeRetryDelay(response, attempt));
149
+ continue;
150
+ }
151
+ return this.BuildRESTResponse(response);
152
+ }
153
+ throw new Error(`OpenWater API request failed after ${maxRetries} attempt(s): ${url}`);
154
+ }
155
+ /**
156
+ * OpenWater v2 list endpoints return a paged envelope { records: [...], pageIndex, pageSize,
157
+ * totalRecords } or a bare array. NormalizeResponse unwraps to the record array.
158
+ */
159
+ NormalizeResponse(rawBody, responseDataKey) {
160
+ if (rawBody == null)
161
+ return [];
162
+ if (Array.isArray(rawBody))
163
+ return rawBody;
164
+ const body = rawBody;
165
+ if (responseDataKey && Array.isArray(body[responseDataKey])) {
166
+ return body[responseDataKey];
167
+ }
168
+ for (const key of ['records', 'data', 'items', 'results']) {
169
+ if (Array.isArray(body[key]))
170
+ return body[key];
171
+ }
172
+ // A single-object response (e.g. a create echo) becomes a one-element array.
173
+ if (Object.keys(body).length > 0)
174
+ return [body];
175
+ return [];
176
+ }
177
+ /**
178
+ * PageNumber pagination over OpenWater's pageIndex/pageSize. Advances pageIndex until a
179
+ * short/empty page (records.length < requested pageSize) signals the last page.
180
+ */
181
+ ExtractPaginationInfo(rawBody, paginationType, currentPage, currentOffset, pageSize) {
182
+ if (paginationType === 'None')
183
+ return { HasMore: false };
184
+ const records = this.NormalizeResponse(rawBody, null);
185
+ const effectivePageSize = pageSize > 0 ? pageSize : DEFAULT_PAGE_SIZE;
186
+ const total = this.ReadTotalRecords(rawBody);
187
+ switch (paginationType) {
188
+ case 'PageNumber': {
189
+ // Short page ⇒ done. Otherwise honor a totalRecords hint when the API supplies one.
190
+ const moreByPageSize = records.length >= effectivePageSize;
191
+ // pageIndex is 0-based: after page `currentPage` we've fetched (currentPage+1) pages.
192
+ const fetchedSoFar = (currentPage + 1) * effectivePageSize;
193
+ const hasMore = total != null ? fetchedSoFar < total && records.length > 0 : moreByPageSize;
194
+ return { HasMore: hasMore, NextPage: currentPage + 1 };
195
+ }
196
+ case 'Offset':
197
+ return { HasMore: records.length >= effectivePageSize, NextOffset: currentOffset + records.length };
198
+ case 'Cursor': {
199
+ const body = rawBody;
200
+ const cursor = body?.['nextCursor'] ?? body?.['next_cursor'] ?? body?.['cursor'];
201
+ return { HasMore: typeof cursor === 'string' && cursor.length > 0, NextCursor: typeof cursor === 'string' ? cursor : undefined };
202
+ }
203
+ default:
204
+ return { HasMore: records.length >= effectivePageSize };
205
+ }
206
+ }
207
+ ReadTotalRecords(rawBody) {
208
+ if (!rawBody || typeof rawBody !== 'object' || Array.isArray(rawBody))
209
+ return null;
210
+ const b = rawBody;
211
+ for (const key of ['totalRecords', 'totalCount', 'total']) {
212
+ const v = b[key];
213
+ if (typeof v === 'number' && Number.isFinite(v))
214
+ return v;
215
+ }
216
+ return null;
217
+ }
218
+ /**
219
+ * OpenWater uses page=/pageSize= by default in the base loop, but the API's param names are
220
+ * pageIndex/pageSize. Override to emit the vendor's actual param names.
221
+ */
222
+ BuildPaginatedURL(basePath, obj, page, offset, cursor, effectivePageSize) {
223
+ const pageSize = effectivePageSize ?? obj.DefaultPageSize ?? DEFAULT_PAGE_SIZE;
224
+ const separator = basePath.includes('?') ? '&' : '?';
225
+ switch (obj.PaginationType) {
226
+ case 'PageNumber':
227
+ return `${basePath}${separator}pageIndex=${page}&pageSize=${pageSize}`;
228
+ case 'Offset':
229
+ return `${basePath}${separator}offset=${offset}&pageSize=${pageSize}`;
230
+ case 'Cursor':
231
+ return cursor
232
+ ? `${basePath}${separator}cursor=${encodeURIComponent(cursor)}&pageSize=${pageSize}`
233
+ : `${basePath}${separator}pageSize=${pageSize}`;
234
+ default:
235
+ return basePath;
236
+ }
237
+ }
238
+ GetBaseURL(_companyIntegration, auth) {
239
+ return auth.BaseURL;
240
+ }
241
+ // ── Connection test ──────────────────────────────────────────────
242
+ async TestConnection(companyIntegration, contextUser) {
243
+ try {
244
+ const auth = await this.GetAuth(companyIntegration, contextUser, true);
245
+ // Programs is a top-level door present in every OpenWater tenant.
246
+ const url = `${auth.BaseURL}/v2/Programs?pageIndex=0&pageSize=1`;
247
+ const response = await this.MakeHTTPRequest(auth, url, 'GET', this.BuildHeaders(auth));
248
+ if (response.Status >= 200 && response.Status < 300) {
249
+ return { Success: true, Message: `Connected to OpenWater at ${auth.BaseURL}` };
250
+ }
251
+ if (response.Status === 401 || response.Status === 403) {
252
+ return { Success: false, Message: `OpenWater rejected the credentials (HTTP ${response.Status}). Verify ClientKey / ApiKey / OrganizationCode.` };
253
+ }
254
+ return { Success: false, Message: `OpenWater responded HTTP ${response.Status}.` };
255
+ }
256
+ catch (err) {
257
+ const message = err instanceof Error ? err.message : String(err);
258
+ return { Success: false, Message: `OpenWater connection failed: ${message}` };
259
+ }
260
+ }
261
+ // NOTE: DiscoverObjects / DiscoverFields / IntrospectSchema are intentionally NOT
262
+ // overridden — the base implementations read the Declared IO/IOF metadata from the
263
+ // IntegrationEngineBase cache (credential-free, no baked catalog in this file).
264
+ // ── Fetch (incremental + nested-graph access-path walk) ─────────
265
+ async FetchChanges(ctx) {
266
+ const obj = this.GetCachedObject(ctx.CompanyIntegration.IntegrationID, ctx.ObjectName);
267
+ const accessPath = this.ParseAccessPath(obj);
268
+ // Depth-0 (directly-queryable door / flat top-level query): delegate to the base
269
+ // flat/pagination path, but layer the incremental watermark query param on top.
270
+ if (!accessPath) {
271
+ return this.FetchDoor(ctx, obj);
272
+ }
273
+ // Depth-N (nested): walk the access path from the door to the leaf records.
274
+ return this.FetchViaAccessPath(ctx, obj, accessPath);
275
+ }
276
+ // ── Literal-create / literal-update overrides (RequiresLiveVerification) ──────────
277
+ //
278
+ // Three IOs declare CreateBodyShape='literal' (Session, JudgeAssignment, ScheduleTimeSlot)
279
+ // because their create-request schema needs fields absent from the synced list-model — the
280
+ // generic flat body would 400/422. ScheduleTimeSlot additionally declares UpdateBodyShape=
281
+ // 'literal'. CreateRecord/UpdateRecord dispatch ONLY those IOs to a hand-built body (read from
282
+ // the OpenAPI create/update-request schema) and delegate every other IO to the generic
283
+ // per-operation column path on the base class. All creates route through BuildCreatedResult.
284
+ async CreateRecord(ctx) {
285
+ switch (ctx.ObjectName) {
286
+ case 'Session': return this.CreateSession(ctx);
287
+ case 'JudgeAssignment': return this.CreateJudgeAssignment(ctx);
288
+ case 'ScheduleTimeSlot': return this.CreateScheduleTimeSlot(ctx);
289
+ default: return super.CreateRecord(ctx);
290
+ }
291
+ }
292
+ async UpdateRecord(ctx) {
293
+ // Only ScheduleTimeSlot declares UpdateBodyShape='literal'; everything else is generic.
294
+ if (ctx.ObjectName === 'ScheduleTimeSlot')
295
+ return this.UpdateScheduleTimeSlot(ctx);
296
+ return super.UpdateRecord(ctx);
297
+ }
298
+ async DeleteRecord(ctx) {
299
+ // JudgeAssignment delete has no path id (DeleteIDLocation='n/a'): DELETE /v2/JudgeAssignments/Round
300
+ // with the {roundId, judgeUserId} pair as query params, recovered from the synthetic composite id.
301
+ if (ctx.ObjectName === 'JudgeAssignment')
302
+ return this.DeleteJudgeAssignment(ctx);
303
+ return super.DeleteRecord(ctx);
304
+ }
305
+ /**
306
+ * Session create — Models.Session.CreateRequest requires {programId, typeId, name}. The synced
307
+ * list-model carries typeName (string), not typeId (int). Resolve typeId from an explicit typeId
308
+ * attribute when supplied; otherwise look it up by name against the SessionType IO (which is
309
+ * program-scoped, so we match within the record's programId).
310
+ */
311
+ async CreateSession(ctx) {
312
+ const a = ctx.Attributes;
313
+ const programId = this.RequireNumber(a, 'programId');
314
+ const typeId = await this.ResolveSessionTypeId(ctx, a, programId);
315
+ if (typeId == null) {
316
+ return this.FailedResult(`Session create: could not resolve a SessionType id from typeId/typeName for programId ${programId}.`);
317
+ }
318
+ const body = {
319
+ programId,
320
+ typeId,
321
+ name: a['name'] ?? a['Name'] ?? '',
322
+ };
323
+ this.CopyOptional(a, body, ['chairUserIds', 'fieldValues']);
324
+ return this.PostCreate(ctx, '/v2/Sessions', body, 'body');
325
+ }
326
+ /**
327
+ * JudgeAssignment create — Models.JudgeAssignment.AssignJudgeToRoundRequest requires
328
+ * {judgeUserId, roundId}. judgeUserId <- the synced userId; roundId from the create attributes'
329
+ * round context (tagged onto the synced record by the AccessPath walk, or passed explicitly).
330
+ * CreateIDLocation='n/a' → there is no body id; the stable identity is the (roundId, judgeUserId)
331
+ * pair, so BuildCreatedResult is fed the synthetic composite id roundId|judgeUserId.
332
+ */
333
+ async CreateJudgeAssignment(ctx) {
334
+ const a = ctx.Attributes;
335
+ const judgeUserId = this.FirstNumber(a, ['judgeUserId', 'userId']);
336
+ const roundId = this.FirstNumber(a, ['roundId']);
337
+ if (judgeUserId == null)
338
+ return this.FailedResult('JudgeAssignment create: missing judgeUserId/userId.');
339
+ if (roundId == null)
340
+ return this.FailedResult('JudgeAssignment create: missing roundId (round context not available).');
341
+ const body = { judgeUserId, roundId };
342
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
343
+ const url = `${auth.BaseURL}/v2/JudgeAssignments/Round`;
344
+ const response = await this.MakeHTTPRequest(auth, url, 'POST', this.BuildHeaders(auth), body);
345
+ if (response.Status >= 200 && response.Status < 300) {
346
+ // No returned id (n/a) — the pair IS the identity. Synthesize it so the create is tracked.
347
+ return this.BuildCreatedResult(`${roundId}|${judgeUserId}`, response.Status, ctx.ObjectName);
348
+ }
349
+ return this.FailedResult(this.ExtractErrorMessage(response) ?? `HTTP ${response.Status} on JudgeAssignment create`, response.Status);
350
+ }
351
+ async DeleteJudgeAssignment(ctx) {
352
+ // Recover {roundId, judgeUserId} from the synthetic composite id roundId|judgeUserId.
353
+ const [roundId, judgeUserId] = String(ctx.ExternalID).split('|');
354
+ if (!roundId || !judgeUserId) {
355
+ return this.FailedResult(`JudgeAssignment delete: external id "${ctx.ExternalID}" is not a roundId|judgeUserId pair.`);
356
+ }
357
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
358
+ const url = `${auth.BaseURL}/v2/JudgeAssignments/Round?roundId=${encodeURIComponent(roundId)}&judgeUserId=${encodeURIComponent(judgeUserId)}`;
359
+ const response = await this.MakeHTTPRequest(auth, url, 'DELETE', this.BuildHeaders(auth));
360
+ if (response.Status >= 200 && response.Status < 300) {
361
+ return { Success: true, StatusCode: response.Status, ExternalID: ctx.ExternalID };
362
+ }
363
+ return this.FailedResult(this.ExtractErrorMessage(response) ?? `HTTP ${response.Status} on JudgeAssignment delete`, response.Status);
364
+ }
365
+ /**
366
+ * ScheduleTimeSlot create — Models.ScheduleTimeSlot.CreateRequest requires
367
+ * {name, code, startTime, endTime, scheduleDayIds}. The read-side IOF is availableOnlyInDayIds;
368
+ * map it (or an explicit scheduleDayIds) into scheduleDayIds. The path is program-scoped, so the
369
+ * generic path is bypassed and the {programId} template is filled from the attributes.
370
+ */
371
+ async CreateScheduleTimeSlot(ctx) {
372
+ const a = ctx.Attributes;
373
+ const programId = this.RequireNumber(a, 'programId');
374
+ const body = this.BuildTimeSlotBody(a);
375
+ return this.PostCreate(ctx, `/v2/Programs/${encodeURIComponent(String(programId))}/Scheduler/TimeSlots`, body, 'body');
376
+ }
377
+ /**
378
+ * ScheduleTimeSlot update — Models.ScheduleTimeSlot.UpdateRequest mirrors the create shape and
379
+ * also requires scheduleDayIds (mapped from availableOnlyInDayIds). The update path is keyed by
380
+ * the time-slot id (not program-scoped): PATCH /v2/Programs/Scheduler/TimeSlots/{scheduleTimeSlotId}.
381
+ */
382
+ async UpdateScheduleTimeSlot(ctx) {
383
+ const body = this.BuildTimeSlotBody(ctx.Attributes);
384
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
385
+ const url = `${auth.BaseURL}/v2/Programs/Scheduler/TimeSlots/${encodeURIComponent(ctx.ExternalID)}`;
386
+ const response = await this.MakeHTTPRequest(auth, url, 'PATCH', this.BuildHeaders(auth), body);
387
+ if (response.Status >= 200 && response.Status < 300) {
388
+ return { Success: true, StatusCode: response.Status, ExternalID: ctx.ExternalID };
389
+ }
390
+ return this.FailedResult(this.ExtractErrorMessage(response) ?? `HTTP ${response.Status} on ScheduleTimeSlot update`, response.Status);
391
+ }
392
+ /** Shared body for ScheduleTimeSlot create/update: maps availableOnlyInDayIds -> scheduleDayIds. */
393
+ BuildTimeSlotBody(a) {
394
+ const scheduleDayIds = a['scheduleDayIds'] ?? a['availableOnlyInDayIds'] ?? [];
395
+ return {
396
+ name: a['name'] ?? a['Name'] ?? '',
397
+ code: a['code'] ?? a['Code'] ?? '',
398
+ startTime: a['startTime'] ?? a['StartTime'],
399
+ endTime: a['endTime'] ?? a['EndTime'],
400
+ scheduleDayIds: Array.isArray(scheduleDayIds) ? scheduleDayIds : [],
401
+ };
402
+ }
403
+ /** Resolve a SessionType id: explicit typeId attribute, else lookup by typeName in the SessionType IO. */
404
+ async ResolveSessionTypeId(ctx, a, programId) {
405
+ const explicit = this.FirstNumber(a, ['typeId']);
406
+ if (explicit != null)
407
+ return explicit;
408
+ const typeName = a['typeName'] ?? a['TypeName'];
409
+ if (typeof typeName !== 'string' || typeName.length === 0)
410
+ return null;
411
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
412
+ const url = `${auth.BaseURL}/v2/Programs/${encodeURIComponent(String(programId))}/SessionTypes`;
413
+ const response = await this.MakeHTTPRequest(auth, url, 'GET', this.BuildHeaders(auth));
414
+ if (response.Status < 200 || response.Status >= 300)
415
+ return null;
416
+ const types = this.NormalizeResponse(response.Body, null);
417
+ const match = types.find(t => String(t['name'] ?? t['typeName'] ?? '').toLowerCase() === typeName.toLowerCase());
418
+ if (!match)
419
+ return null;
420
+ const id = match['id'];
421
+ return typeof id === 'number' ? id : (typeof id === 'string' && id.length > 0 ? Number(id) : null);
422
+ }
423
+ /** POST a hand-built create body and route the result through BuildCreatedResult (id from body). */
424
+ async PostCreate(ctx, path, body, idLocation) {
425
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
426
+ const url = `${auth.BaseURL}${path}`;
427
+ const response = await this.MakeHTTPRequest(auth, url, 'POST', this.BuildHeaders(auth), body);
428
+ if (response.Status >= 200 && response.Status < 300) {
429
+ const externalID = this.ExtractIDFromResponse(response, idLocation);
430
+ return this.BuildCreatedResult(externalID, response.Status, ctx.ObjectName);
431
+ }
432
+ return this.FailedResult(this.ExtractErrorMessage(response) ?? `HTTP ${response.Status} on ${ctx.ObjectName} create`, response.Status);
433
+ }
434
+ // ── Literal-write attribute helpers ──────────────────────────────
435
+ RequireNumber(a, key) {
436
+ const v = this.FirstNumber(a, [key]);
437
+ if (v == null)
438
+ throw new Error(`OpenWater write: required numeric attribute "${key}" is missing.`);
439
+ return v;
440
+ }
441
+ /** First parseable number among candidate keys (case-tolerant), or null. */
442
+ FirstNumber(a, keys) {
443
+ for (const key of keys) {
444
+ for (const k of [key, key.charAt(0).toUpperCase() + key.slice(1)]) {
445
+ const v = a[k];
446
+ if (typeof v === 'number' && Number.isFinite(v))
447
+ return v;
448
+ if (typeof v === 'string' && v.length > 0 && Number.isFinite(Number(v)))
449
+ return Number(v);
450
+ }
451
+ }
452
+ return null;
453
+ }
454
+ CopyOptional(src, dest, keys) {
455
+ for (const k of keys)
456
+ if (src[k] !== undefined)
457
+ dest[k] = src[k];
458
+ }
459
+ FailedResult(message, statusCode = 0) {
460
+ return { Success: false, StatusCode: statusCode, ErrorMessage: message };
461
+ }
462
+ /**
463
+ * Flat/door fetch with incremental watermark applied. Reuses the base pagination loop by
464
+ * temporarily folding the watermark param into the IO's DefaultQueryParams-equivalent via a
465
+ * one-shot manual paginated loop (so the watermark rides every page request).
466
+ */
467
+ async FetchDoor(ctx, obj) {
468
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
469
+ const baseURL = this.GetBaseURL(ctx.CompanyIntegration, auth);
470
+ const watermarkParam = this.BuildWatermarkParam(obj, ctx.WatermarkValue);
471
+ const path = this.AppendQuery(obj.APIPath, watermarkParam);
472
+ const fields = this.GetCachedFields(obj.ID);
473
+ const pkFieldNames = this.PrimaryKeyNames(fields);
474
+ const { records, newWatermark, hasMore, nextPage } = await this.PaginateLeaf(auth, baseURL, path, obj, ctx, undefined, watermarkParam);
475
+ return {
476
+ Records: records.map(r => this.BuildExternalRecord(r, obj, fields, pkFieldNames)),
477
+ HasMore: hasMore,
478
+ NextPage: nextPage,
479
+ NewWatermarkValue: newWatermark,
480
+ };
481
+ }
482
+ /**
483
+ * Walks the per-IO AccessPath: query the door, descend the nesting segments to the leaf parent
484
+ * ids, then fetch the entry path once per parent (id in path template or query param), unioning
485
+ * any alternativePaths. An `embedded-array` access path emits records straight from the door.
486
+ */
487
+ async FetchViaAccessPath(ctx, obj, accessPath) {
488
+ const auth = await this.Authenticate(ctx.CompanyIntegration, ctx.ContextUser);
489
+ const baseURL = this.GetBaseURL(ctx.CompanyIntegration, auth);
490
+ const fields = this.GetCachedFields(obj.ID);
491
+ const pkFieldNames = this.PrimaryKeyNames(fields);
492
+ const warnings = [];
493
+ // Pull the door collection (paginated) and descend to the parent leaf values + the door rows.
494
+ const doorRows = await this.FetchDoorRows(auth, baseURL, accessPath.doorPath, obj);
495
+ if (doorRows.length === 0) {
496
+ warnings.push({
497
+ Code: 'ZERO_PARENTS',
498
+ Message: `No "${accessPath.door}" door records available; "${obj.Name}" produced zero records.`,
499
+ Data: { door: accessPath.door, doorPath: accessPath.doorPath },
500
+ });
501
+ return { Records: [], HasMore: false, Warnings: warnings };
502
+ }
503
+ // embedded-array: records are already inside the door payload (e.g. Program.rounds[]).
504
+ if (accessPath.extractionMode === 'embedded-array') {
505
+ const records = this.ExtractEmbedded(doorRows, accessPath.nestingSegments ?? []);
506
+ return {
507
+ Records: records.map(r => this.BuildExternalRecord(r, obj, fields, pkFieldNames)),
508
+ HasMore: false,
509
+ Warnings: warnings,
510
+ };
511
+ }
512
+ const parentIDs = this.DescendToParentIDs(doorRows, accessPath);
513
+ if (parentIDs.length === 0) {
514
+ warnings.push({
515
+ Code: 'ZERO_PARENTS',
516
+ Message: `No "${accessPath.parentParamName}" parent ids reachable via ${accessPath.door} ${(accessPath.nestingSegments ?? []).join('->')}; "${obj.Name}" produced zero records.`,
517
+ Data: { door: accessPath.door, parentParamName: accessPath.parentParamName ?? null },
518
+ });
519
+ return { Records: [], HasMore: false, Warnings: warnings };
520
+ }
521
+ const entryPaths = [accessPath.entryPath, ...(accessPath.alternativePaths ?? [])];
522
+ const parentTagName = accessPath.parentParamName; // e.g. roundId / programId / fundId
523
+ const out = [];
524
+ for (const parentID of parentIDs) {
525
+ for (const entryPath of entryPaths) {
526
+ const leafPath = this.InjectParentID(entryPath, parentID, accessPath);
527
+ if (leafPath == null)
528
+ continue; // template var this entry path doesn't use
529
+ const { records } = await this.PaginateLeaf(auth, baseURL, leafPath, obj, ctx, parentID, '');
530
+ for (const r of records) {
531
+ // Tag the leaf with its parent id (e.g. roundId) when the record doesn't already
532
+ // carry it — makes round/program-scoped objects self-describing for pass-through
533
+ // AND supplies the round context a literal-create write-back (JudgeAssignment) needs.
534
+ if (parentTagName && r[parentTagName] == null)
535
+ r[parentTagName] = parentID;
536
+ out.push(this.BuildExternalRecord(r, obj, fields, pkFieldNames));
537
+ }
538
+ }
539
+ }
540
+ return { Records: out, HasMore: false, Warnings: warnings };
541
+ }
542
+ /** Fetch all pages of a door collection (used to enumerate parent ids / embedded children). */
543
+ async FetchDoorRows(auth, baseURL, doorPath, obj) {
544
+ const { records } = await this.PaginateLeaf(auth, baseURL, doorPath, obj, undefined, undefined, '', true);
545
+ return records;
546
+ }
547
+ /**
548
+ * Generic paginated leaf fetch. Loops pageIndex until a short/empty page (or the batch cap when
549
+ * `ctx` is supplied), tracking the max watermark seen across the IO's IncrementalWatermarkField.
550
+ * `forceFullScan` ignores the batch cap (used when enumerating door parents).
551
+ */
552
+ async PaginateLeaf(auth, baseURL, path, obj, ctx, _parentID, _watermarkParam, forceFullScan = false) {
553
+ const headers = this.BuildHeaders(auth);
554
+ const pageSize = obj.DefaultPageSize && obj.DefaultPageSize > 0 ? obj.DefaultPageSize : DEFAULT_PAGE_SIZE;
555
+ const batchLimit = !forceFullScan && ctx?.BatchSize ? ctx.BatchSize : Number.MAX_SAFE_INTEGER;
556
+ const watermarkField = obj.IncrementalWatermarkField;
557
+ const all = [];
558
+ let page = ctx?.CurrentPage ?? 0;
559
+ let newWatermark = ctx?.WatermarkValue ?? undefined;
560
+ let hasMore = true;
561
+ while (hasMore && all.length < batchLimit) {
562
+ const sep = path.includes('?') ? '&' : '?';
563
+ const usePaging = obj.SupportsPagination && obj.PaginationType !== 'None';
564
+ const url = usePaging
565
+ ? `${baseURL}${path}${sep}pageIndex=${page}&pageSize=${pageSize}`
566
+ : `${baseURL}${path}`;
567
+ const response = await this.MakeHTTPRequest(auth, url, 'GET', headers);
568
+ if (response.Status === 403 || response.Status === 401) {
569
+ console.warn(`[OpenWater] HTTP ${response.Status} for "${obj.Name}" at ${url} — skipping.`);
570
+ break;
571
+ }
572
+ if (response.Status < 200 || response.Status >= 300) {
573
+ throw this.HttpError(`OpenWater fetch failed for "${obj.Name}": HTTP ${response.Status}`, response);
574
+ }
575
+ const records = this.NormalizeResponse(response.Body, obj.ResponseDataKey);
576
+ if (records.length === 0)
577
+ break;
578
+ all.push(...records);
579
+ // Track max watermark seen for the incremental cursor (string/ISO-comparable).
580
+ if (watermarkField) {
581
+ for (const r of records) {
582
+ const v = r[watermarkField];
583
+ if (typeof v === 'string' && (newWatermark == null || v > newWatermark))
584
+ newWatermark = v;
585
+ }
586
+ }
587
+ if (!usePaging)
588
+ break;
589
+ const state = this.ExtractPaginationInfo(response.Body, obj.PaginationType, page, 0, pageSize);
590
+ hasMore = state.HasMore;
591
+ page = state.NextPage ?? page + 1;
592
+ }
593
+ return {
594
+ records: all,
595
+ newWatermark: watermarkField ? newWatermark : undefined,
596
+ hasMore: hasMore && all.length >= batchLimit,
597
+ nextPage: page,
598
+ };
599
+ }
600
+ // ── Access-path helpers ──────────────────────────────────────────
601
+ /** Reads and validates AccessPath from the IO's Configuration JSON; null when absent. */
602
+ ParseAccessPath(obj) {
603
+ if (!obj.Configuration)
604
+ return null;
605
+ try {
606
+ const parsed = JSON.parse(obj.Configuration);
607
+ const ap = parsed.AccessPath;
608
+ if (!ap || !ap.door || !ap.doorPath)
609
+ return null;
610
+ // embedded-array records are sliced from the DOOR payload itself — they have no
611
+ // entryPath by design. Requiring it here made every embedded IO (e.g. Rounds)
612
+ // silently fall back to its non-fetchable "(embedded in ...)" APIPath.
613
+ if (ap.extractionMode !== 'embedded-array' && !ap.entryPath)
614
+ return null;
615
+ return ap;
616
+ }
617
+ catch {
618
+ console.warn(`[OpenWater] Invalid Configuration JSON for object "${obj.Name}"`);
619
+ return null;
620
+ }
621
+ }
622
+ /**
623
+ * Descends the door rows along the nesting segments to the list of parent ids that get injected
624
+ * into the leaf entry path. For `rounds[]` this yields each round's id; for a direct programId
625
+ * parent (no nesting) it yields each door row's `id`.
626
+ */
627
+ DescendToParentIDs(doorRows, accessPath) {
628
+ // Only `[]`-suffixed segments are real array descents in the door payload (e.g. `rounds[]`,
629
+ // whose leaf `id` is the roundId). A bare segment (e.g. `transactions`) names the leaf API
630
+ // resource that lives in entryPath, NOT a nested array — those parents are the door rows
631
+ // themselves (the door's own `id` IS the parent id, e.g. programId / fundId).
632
+ const arraySegments = (accessPath.nestingSegments ?? []).filter(s => s.endsWith('[]'));
633
+ const ids = [];
634
+ const seen = new Set();
635
+ const collect = (id) => {
636
+ if (id == null)
637
+ return;
638
+ const s = String(id);
639
+ if (s.length === 0 || seen.has(s))
640
+ return;
641
+ seen.add(s);
642
+ ids.push(s);
643
+ };
644
+ if (arraySegments.length === 0) {
645
+ // Direct parent: the door row's own id is the parent id (e.g. programId, fundId).
646
+ for (const row of doorRows)
647
+ collect(row['id']);
648
+ return ids;
649
+ }
650
+ // Descend nested array segments (e.g. rounds[]), collecting the leaf nodes' ids.
651
+ const nodes = this.WalkSegments(doorRows, arraySegments);
652
+ for (const leaf of nodes)
653
+ collect(leaf['id']);
654
+ return ids;
655
+ }
656
+ /** Walks the door rows down a chain of (array) field segments, returning the leaf object nodes. */
657
+ WalkSegments(doorRows, segments) {
658
+ let nodes = doorRows;
659
+ for (const seg of segments) {
660
+ const key = seg.endsWith('[]') ? seg.slice(0, -2) : seg;
661
+ const next = [];
662
+ for (const node of nodes) {
663
+ const child = node[key];
664
+ if (Array.isArray(child)) {
665
+ for (const c of child)
666
+ if (c && typeof c === 'object')
667
+ next.push(c);
668
+ }
669
+ else if (child && typeof child === 'object') {
670
+ next.push(child);
671
+ }
672
+ }
673
+ nodes = next;
674
+ }
675
+ return nodes;
676
+ }
677
+ /** For embedded-array access paths: emit the nested records directly from the door payload. */
678
+ ExtractEmbedded(doorRows, segments) {
679
+ return this.WalkSegments(doorRows, segments);
680
+ }
681
+ /**
682
+ * Injects a parent id into an entry path: as a query param (?<parentParamName>=) when
683
+ * parentParamIn='query' (the roundId-gated endpoints, which 400 without it), otherwise into the
684
+ * {parentParamName} path template. Returns null when a path template var is present but unset
685
+ * (so an alternativePath that uses a different var is skipped, not mis-substituted).
686
+ */
687
+ InjectParentID(entryPath, parentID, accessPath) {
688
+ const paramName = accessPath.parentParamName;
689
+ const encoded = encodeURIComponent(parentID);
690
+ if (accessPath.parentParamIn === 'query' && paramName) {
691
+ const sep = entryPath.includes('?') ? '&' : '?';
692
+ return `${entryPath}${sep}${paramName}=${encoded}`;
693
+ }
694
+ // Path-template injection. Substitute the declared parent param if its placeholder is present.
695
+ if (paramName && entryPath.includes(`{${paramName}}`)) {
696
+ return entryPath.replace(`{${paramName}}`, encoded);
697
+ }
698
+ // A single remaining template var (e.g. {roundId}/{programId} in an alternativePath) also
699
+ // takes the parent id; this keeps roundId-based alternative report paths working.
700
+ const m = entryPath.match(/\{(\w+)\}/);
701
+ if (m)
702
+ return entryPath.replace(m[0], encoded);
703
+ // No template var to fill and not a query param → use as-is (already-flat entry path).
704
+ return entryPath;
705
+ }
706
+ // ── Watermark + record helpers ───────────────────────────────────
707
+ /** Builds the incremental watermark query fragment (e.g. lastModifiedSinceUtc=2026-01-01T...). */
708
+ BuildWatermarkParam(obj, watermarkValue) {
709
+ if (!obj.SupportsIncrementalSync || !obj.IncrementalWatermarkField || !watermarkValue)
710
+ return '';
711
+ return `${obj.IncrementalWatermarkField}=${encodeURIComponent(watermarkValue)}`;
712
+ }
713
+ AppendQuery(path, query) {
714
+ if (!query)
715
+ return path;
716
+ const sep = path.includes('?') ? '&' : '?';
717
+ return `${path}${sep}${query}`;
718
+ }
719
+ /**
720
+ * Builds an ExternalRecord. Fields carries the FULL source record (custom-column pass-through);
721
+ * runs the TransformRecord-preserving pipeline; resolves the ExternalID from the declared PK
722
+ * (composite-aware) with a content-hash fallback for partial/missing keys.
723
+ */
724
+ BuildExternalRecord(raw, obj, fields, pkFieldNames) {
725
+ const transformed = this.applyTransformPreservingKeys(raw, obj, fields);
726
+ const allPkPresent = pkFieldNames.length > 0
727
+ && pkFieldNames.every(name => transformed[name] != null && String(transformed[name]).length > 0);
728
+ const externalID = allPkPresent
729
+ ? pkFieldNames.map(name => String(transformed[name])).join('|')
730
+ : this.ContentHash(transformed);
731
+ return { ExternalID: externalID, ObjectType: obj.Name, Fields: transformed };
732
+ }
733
+ PrimaryKeyNames(fields) {
734
+ const pk = fields.filter(f => f.IsPrimaryKey).sort((a, b) => a.Sequence - b.Sequence).map(f => f.Name);
735
+ return pk.length > 0 ? pk : ['id'];
736
+ }
737
+ /** Deterministic fallback identity for partial/missing keys (FNV-1a over the canonical JSON). */
738
+ ContentHash(record) {
739
+ const json = JSON.stringify(record, Object.keys(record).sort());
740
+ let hash = 0x811c9dc5;
741
+ for (let i = 0; i < json.length; i++) {
742
+ hash ^= json.charCodeAt(i);
743
+ hash = Math.imul(hash, 0x01000193);
744
+ }
745
+ return `hash:${(hash >>> 0).toString(16)}`;
746
+ }
747
+ // ── Default config ───────────────────────────────────────────────
748
+ GetDefaultConfiguration() {
749
+ return { DefaultSchemaName: 'OpenWater', DefaultObjects: [] };
750
+ }
751
+ // ─────────────────────────────────────────────────────────────────
752
+ // Private helpers
753
+ // ─────────────────────────────────────────────────────────────────
754
+ async GetAuth(companyIntegration, contextUser, forceRefresh = false) {
755
+ if (!forceRefresh && this.authState)
756
+ return this.authState;
757
+ const config = await this.ParseConfig(companyIntegration, contextUser);
758
+ const baseURL = this.StripTrailingSlash(config.BaseURL ?? '');
759
+ if (!baseURL) {
760
+ // OpenWater is tenant-specific (each customer is white-labeled on its own host, e.g.
761
+ // https://<org>.secure-platform.com). There is NO shared public API host — the legacy
762
+ // default api.getopenwater.com does NOT resolve (NXDOMAIN), so a silent fallback would
763
+ // fail every real connection at DNS. Require the per-tenant BaseURL and fail loudly here.
764
+ throw new Error('OpenWater requires a per-tenant BaseURL — your OpenWater API host, e.g. ' +
765
+ 'https://<your-org>.secure-platform.com. There is no shared public default ' +
766
+ '(api.getopenwater.com does not resolve); set Configuration.BaseURL on the connection.');
767
+ }
768
+ this.authState = { Config: { ...config, BaseURL: baseURL }, BaseURL: baseURL };
769
+ return this.authState;
770
+ }
771
+ async ParseConfig(companyIntegration, contextUser) {
772
+ if (companyIntegration.CredentialID) {
773
+ const fromCred = await this.ParseConfigFromCredential(companyIntegration.CredentialID, contextUser);
774
+ if (fromCred)
775
+ return this.MergeConfigJson(fromCred, companyIntegration.Configuration);
776
+ }
777
+ if (companyIntegration.Configuration) {
778
+ const parsed = JSON.parse(companyIntegration.Configuration);
779
+ return this.ExtractConfig(parsed);
780
+ }
781
+ throw new Error('OpenWater connector requires either CredentialID or Configuration JSON');
782
+ }
783
+ async ParseConfigFromCredential(credentialID, contextUser, provider) {
784
+ const md = provider ?? new Metadata();
785
+ const credential = await md.GetEntityObject('MJ: Credentials', contextUser);
786
+ const loaded = await credential.Load(credentialID);
787
+ if (!loaded || !credential.Values)
788
+ return null;
789
+ const values = JSON.parse(credential.Values);
790
+ return this.ExtractConfig(values, true);
791
+ }
792
+ /** Overlay non-secret config (BaseURL / OrganizationCode) from the CompanyIntegration JSON onto a credential-derived config. */
793
+ MergeConfigJson(base, configJson) {
794
+ if (!configJson)
795
+ return base;
796
+ try {
797
+ const extra = this.ExtractConfig(JSON.parse(configJson), false, true);
798
+ return {
799
+ ...base,
800
+ BaseURL: extra.BaseURL ?? base.BaseURL,
801
+ OrganizationCode: extra.OrganizationCode ?? base.OrganizationCode,
802
+ ClientKey: extra.ClientKey || base.ClientKey,
803
+ };
804
+ }
805
+ catch {
806
+ return base;
807
+ }
808
+ }
809
+ /**
810
+ * Resolves the connection config from a credential / configuration value bag. ClientKey + ApiKey
811
+ * are required unless `lenient` (used when overlaying optional config JSON onto a credential).
812
+ */
813
+ ExtractConfig(values, requireApiKey = true, lenient = false) {
814
+ const get = (...keys) => {
815
+ for (const key of keys) {
816
+ const hit = Object.entries(values).find(([k]) => k.toLowerCase() === key.toLowerCase());
817
+ if (hit && hit[1] != null && String(hit[1]).length > 0)
818
+ return String(hit[1]);
819
+ }
820
+ return undefined;
821
+ };
822
+ const clientKey = get('ClientKey', 'clientKey', 'client_key', 'X-ClientKey');
823
+ const apiKey = get('ApiKey', 'apiKey', 'api_key', 'X-ApiKey');
824
+ const organizationCode = get('OrganizationCode', 'organizationCode', 'organization_code', 'X-OrganizationCode');
825
+ const baseURL = get('BaseURL', 'BaseUrl', 'base_url', 'endpoint');
826
+ if (!lenient) {
827
+ if (!clientKey)
828
+ throw new Error('OpenWater configuration missing required field: ClientKey');
829
+ if (requireApiKey && !apiKey)
830
+ throw new Error('OpenWater configuration missing required field: ApiKey');
831
+ }
832
+ return {
833
+ ClientKey: clientKey ?? '',
834
+ ApiKey: apiKey ?? '',
835
+ OrganizationCode: organizationCode,
836
+ BaseURL: baseURL ? this.StripTrailingSlash(baseURL) : undefined,
837
+ };
838
+ }
839
+ // ── HTTP helpers ─────────────────────────────────────────────────
840
+ async ExecuteFetch(url, method, headers, body, timeoutMs) {
841
+ const controller = new AbortController();
842
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
843
+ try {
844
+ const requestInit = { method, headers, signal: controller.signal };
845
+ if (body !== undefined && method !== 'GET' && method !== 'DELETE') {
846
+ requestInit.body = JSON.stringify(body);
847
+ }
848
+ return await fetch(url, requestInit);
849
+ }
850
+ finally {
851
+ clearTimeout(timer);
852
+ }
853
+ }
854
+ async BuildRESTResponse(response) {
855
+ const headers = {};
856
+ response.headers.forEach((v, k) => { headers[k.toLowerCase()] = v; });
857
+ const contentType = headers['content-type'] ?? '';
858
+ const body = contentType.includes('application/json')
859
+ ? await this.ParseJsonSafely(response)
860
+ : await response.text();
861
+ return { Status: response.status, Body: body, Headers: headers };
862
+ }
863
+ async ParseJsonSafely(response) {
864
+ try {
865
+ return await response.json();
866
+ }
867
+ catch {
868
+ return null;
869
+ }
870
+ }
871
+ ShouldRetry(status) {
872
+ return status === 429 || status === 502 || status === 503 || status === 504;
873
+ }
874
+ ComputeRetryDelay(response, attempt) {
875
+ const retryAfter = response.headers.get('retry-after');
876
+ if (retryAfter) {
877
+ const seconds = Number.parseInt(retryAfter, 10);
878
+ if (!Number.isNaN(seconds) && seconds > 0)
879
+ return seconds * 1000;
880
+ }
881
+ return Math.min(Math.pow(2, attempt) * 1000, 15_000);
882
+ }
883
+ /** Wraps an error message with the response Status + Headers so ExtractRetryAfterMs can read them. */
884
+ HttpError(message, response) {
885
+ const err = new Error(message);
886
+ err.Status = response.Status;
887
+ err.Headers = response.Headers;
888
+ return err;
889
+ }
890
+ Sleep(ms) {
891
+ return new Promise(resolve => setTimeout(resolve, ms));
892
+ }
893
+ StripTrailingSlash(url) {
894
+ return url.endsWith('/') ? url.slice(0, -1) : url;
895
+ }
896
+ };
897
+ OpenWaterConnector = __decorate([
898
+ RegisterClass(BaseIntegrationConnector, '@memberjunction/connector-openwater')
899
+ ], OpenWaterConnector);
900
+ export { OpenWaterConnector };
901
+ /** Tree-shaking prevention — import and call from the module entry point. */
902
+ export function LoadOpenWaterConnector() { }
903
+ //# sourceMappingURL=OpenWaterConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenWaterConnector.js","sourceRoot":"","sources":["../src/OpenWaterConnector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './OpenWaterConnector.js';
2
+ /** Open App bootstrap entry: importing this module ran the connector's @RegisterClass decorator;
3
+ * this no-op satisfies the loader's required startupExport and forces the import at MJAPI boot. */
4
+ export declare function registerConnector(): void;
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './OpenWaterConnector.js';
2
+ /** Open App bootstrap entry: importing this module ran the connector's @RegisterClass decorator;
3
+ * this no-op satisfies the loader's required startupExport and forces the import at MJAPI boot. */
4
+ export function registerConnector() { }
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AAExC;oGACoG;AACpG,MAAM,UAAU,iBAAiB,KAAiD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@memberjunction/connector-openwater",
3
+ "version": "1.0.0",
4
+ "description": "MemberJunction OpenWater connector.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "/dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc && tsc-alias -f",
13
+ "test": "vitest run --passWithNoTests"
14
+ },
15
+ "author": "MemberJunction.com",
16
+ "license": "ISC",
17
+ "peerDependencies": {
18
+ "@memberjunction/core": ">=5.42.0 <6.0.0",
19
+ "@memberjunction/core-entities": ">=5.42.0 <6.0.0",
20
+ "@memberjunction/global": ">=5.42.0 <6.0.0",
21
+ "@memberjunction/integration-engine": ">=5.42.0 <6.0.0"
22
+ },
23
+ "dependencies": {},
24
+ "devDependencies": {
25
+ "@types/node": "24.10.11",
26
+ "tsc-alias": "^1.8.16",
27
+ "typescript": "^5.9.3",
28
+ "vitest": "^4.0.18",
29
+ "@memberjunction/core": "^5.42.0",
30
+ "@memberjunction/core-entities": "^5.42.0",
31
+ "@memberjunction/global": "^5.42.0",
32
+ "@memberjunction/integration-engine": "^5.42.0"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/MemberJunction/Integrations"
37
+ }
38
+ }