@memberjunction/connector-fonteva 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,152 @@
1
+ import type { UserInfo } from '@memberjunction/core';
2
+ import type { MJCompanyIntegrationEntity } from '@memberjunction/core-entities';
3
+ import { type ExternalObjectSchema, type ExternalFieldSchema, type FetchContext, type FetchBatchResult, type ExternalRecord, type CRUDResult, type CreateRecordContext, type UpdateRecordContext, type DeleteRecordContext, type GetRecordContext, type SearchContext, type SearchResult, type SourceSchemaInfo, type IntrospectSchemaOptions } from '@memberjunction/integration-engine';
4
+ import { SalesforceConnector } from '@memberjunction/connector-salesforce';
5
+ /**
6
+ * Fonteva AMS connector.
7
+ *
8
+ * Fonteva is a Salesforce **managed package** (the OrderApi__ and EventApi__
9
+ * namespaces), so it rides the core Salesforce REST infrastructure verbatim.
10
+ * This connector therefore COMPOSES on {@link SalesforceConnector}, reusing —
11
+ * unchanged — its:
12
+ * - Salesforce OAuth2 bearer authentication (JWT-bearer / client-credentials),
13
+ * - global describe object discovery (`/services/data/vXX/sobjects/`),
14
+ * - per-object `/describe` field discovery,
15
+ * - SOQL incremental fetch with `nextRecordsUrl` cursor pagination,
16
+ * - `SystemModstamp` watermark incremental sync,
17
+ * - generic sObject CRUD (POST/PATCH/DELETE) and the `BuildCreatedResult`
18
+ * loud-fail-on-empty-ID write contract.
19
+ *
20
+ * The Fonteva-specific layer added here is intentionally thin:
21
+ * 1. **Namespace scoping** — `DiscoverObjects` filters the inherited Salesforce
22
+ * global describe down to the managed-package namespaces (OrderApi__ /
23
+ * EventApi__), so the connector surfaces ONLY Fonteva AMS objects (the
24
+ * standard SF CRM objects are the SalesforceConnector's job).
25
+ * 2. **IO-name ↔ backing-sObject translation** — the friendly IO `Name`
26
+ * ("Assignment") is mapped to its real sObject API name
27
+ * ("OrderApi__Assignment__c", read from the IO's Configuration) before
28
+ * every inherited Salesforce operation, and the returned records'
29
+ * `ObjectType` is rewritten back to the IO name for engine identity.
30
+ * 3. **FDService domain services** — the `/services/apexrest/FDService/*` Apex
31
+ * REST services are wired as an opt-in read path with the documented
32
+ * SearchRequest filter/fields/sort/limit query params.
33
+ *
34
+ * Discovery is the live global-describe MECHANISM (no baked catalog); the object
35
+ * universe is Declared (docs) + Discovered (runtime describe). Writes use the
36
+ * inherited generic sObject CRUD; FDService write shapes are not idiosyncratic
37
+ * enough to warrant overriding the sObject write path (the metadata routes all
38
+ * writes through the platform sObject endpoints).
39
+ */
40
+ export declare class FontevaConnector extends SalesforceConnector {
41
+ private _fontevaConfig;
42
+ get IntegrationName(): string;
43
+ /**
44
+ * AUTHORITATIVE discovery (inherited rationale): the scoped global describe
45
+ * enumerates the COMPLETE set of Fonteva managed-package objects the
46
+ * credentials expose, so absence in a refresh genuinely means the object was
47
+ * removed and the engine may safely deactivate it. Kept explicit so the
48
+ * Fonteva-scoped filter doesn't quietly inherit a non-authoritative default.
49
+ */
50
+ get DiscoveryIsAuthoritative(): boolean;
51
+ /**
52
+ * Parses the integration-level Configuration JSON for the Fonteva-specific
53
+ * knobs (managed-package namespaces, FDService base path, opt-in FDService
54
+ * read). Tolerant of missing/invalid Configuration — falls back to documented
55
+ * defaults so a freshly-seeded integration works without extra config.
56
+ */
57
+ private GetFontevaConfig;
58
+ /**
59
+ * Discovers Fonteva objects by reusing the inherited Salesforce global
60
+ * describe and filtering it to the managed-package namespaces. NO baked
61
+ * catalog — the list comes entirely from the live `/sobjects/` describe; this
62
+ * method only scopes it and presents the friendly (namespace-stripped) IO name.
63
+ */
64
+ DiscoverObjects(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<ExternalObjectSchema[]>;
65
+ /**
66
+ * Builds a reverse map (lower-cased backing sObject API name → declared IO Name) from the
67
+ * loaded metadata — the inverse of {@link ResolveBackingSObject}. Used at discovery time so a
68
+ * discovered sObject resolves to the IO the metadata actually declares for it, instead of a
69
+ * mechanically-derived name that may not round-trip (singular/plural, wrapper-vs-sObject renames).
70
+ * Returns an empty map when the engine cache isn't populated (e.g. unit tests) — callers then
71
+ * fall back to {@link SObjectToFriendlyName}.
72
+ */
73
+ private BuildBackingSObjectReverseMap;
74
+ /**
75
+ * Discovers fields for a Fonteva object. Translates the friendly IO name back
76
+ * to its backing sObject API name, then reuses the inherited Salesforce
77
+ * `/describe` field discovery verbatim.
78
+ */
79
+ DiscoverFields(companyIntegration: MJCompanyIntegrationEntity, objectName: string, contextUser: UserInfo): Promise<ExternalFieldSchema[]>;
80
+ /**
81
+ * Full schema introspection scoped to the managed-package namespaces. Defers
82
+ * entirely to the inherited Salesforce introspection (which calls
83
+ * DiscoverObjects — overridden here to scope — then `/describe`s each), but
84
+ * re-resolves any caller-supplied ObjectNames (friendly IO names) to their
85
+ * backing sObjects so the inherited describe loop targets real sObjects.
86
+ */
87
+ IntrospectSchema(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo, options?: IntrospectSchemaOptions): Promise<SourceSchemaInfo>;
88
+ /**
89
+ * Fetches changed records. Default path reuses the inherited Salesforce SOQL
90
+ * incremental fetch (SystemModstamp watermark + nextRecordsUrl cursor)
91
+ * verbatim, with the IO name translated to its backing sObject. When the
92
+ * connection opts into FDService reads (`UseFDServiceForRead`), routes through
93
+ * the FDService Apex REST domain service instead.
94
+ */
95
+ FetchChanges(ctx: FetchContext): Promise<FetchBatchResult>;
96
+ CreateRecord(ctx: CreateRecordContext): Promise<CRUDResult>;
97
+ UpdateRecord(ctx: UpdateRecordContext): Promise<CRUDResult>;
98
+ DeleteRecord(ctx: DeleteRecordContext): Promise<CRUDResult>;
99
+ GetRecord(ctx: GetRecordContext): Promise<ExternalRecord | null>;
100
+ SearchRecords(ctx: SearchContext): Promise<SearchResult>;
101
+ /**
102
+ * Reads records through a Fonteva FDService Apex REST domain service using
103
+ * the documented SearchRequest parameters (filter / fields / sort / limit).
104
+ * The connector follows the SystemModstamp watermark by encoding a SOQL WHERE
105
+ * fragment into the `filter` (a.k.a. whereClause) param.
106
+ *
107
+ * Idiosyncratic to Fonteva: FDService returns the wrapper records under a
108
+ * `records` key (camelCase wrapper properties), with the universal `id`
109
+ * property carrying the Salesforce 18-char Id. There is no documented cursor
110
+ * token, so pagination is bounded by `limit` and advanced by the watermark on
111
+ * subsequent syncs (the connector reports the max SystemModstamp it saw).
112
+ */
113
+ private FetchViaFDService;
114
+ /** Builds SearchRequest params from the fetch context (watermark → filter). */
115
+ private BuildFDServiceSearchParams;
116
+ private EncodeFDServiceParams;
117
+ private FormatFDServiceDateTime;
118
+ /**
119
+ * Parses an FDService response into ExternalRecords. FDService wraps records
120
+ * under a `records` array (each a flat camelCase wrapper object whose `id`
121
+ * carries the Salesforce Id). Preserves the FULL record into Fields for
122
+ * custom-column capture — no narrow projection.
123
+ */
124
+ private ParseFDServiceRecords;
125
+ private MaxSystemModstamp;
126
+ private BuildFDServicePath;
127
+ /**
128
+ * Resolves the friendly IO `Name` to its backing Salesforce sObject API name.
129
+ * Reads the IO's Configuration.BackingSObject from the engine cache; falls
130
+ * back to a namespace-prefixed PascalSnake derivation when metadata isn't
131
+ * loaded (e.g. unit tests) or the IO already IS a fully-qualified sObject.
132
+ */
133
+ private ResolveBackingSObject;
134
+ /** Reads + parses the per-IO Configuration from the engine cache. Returns null if unavailable. */
135
+ private GetObjectConfig;
136
+ private IsInManagedPackage;
137
+ /**
138
+ * Presents a managed-package sObject API name as a friendly IO name by
139
+ * stripping the namespace prefix and the `__c` suffix and PascalCasing the
140
+ * snake segments (e.g. OrderApi__Sales_Order_Line__c → SalesOrderLine).
141
+ */
142
+ private SObjectToFriendlyName;
143
+ /** Rewrites a fetch batch's record ObjectType from the backing sObject back to the IO name. */
144
+ private RewriteObjectType;
145
+ private AuthenticateForFonteva;
146
+ private FontevaHeaders;
147
+ private MakeFontevaRequest;
148
+ private FontevaApiBase;
149
+ private PreviewFonteva;
150
+ }
151
+ /** Tree-shaking prevention: referenced from index.ts so the @RegisterClass survives bundling. */
152
+ export declare function LoadFontevaConnector(): void;
@@ -0,0 +1,421 @@
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
+ import { RegisterClass } from '@memberjunction/global';
8
+ import { IntegrationEngineBase } from '@memberjunction/integration-engine-base';
9
+ import { BaseIntegrationConnector, } from '@memberjunction/integration-engine';
10
+ import { SalesforceConnector } from '@memberjunction/connector-salesforce';
11
+ // ─── Constants ────────────────────────────────────────────────────────
12
+ const DEFAULT_MANAGED_PACKAGE_NAMESPACES = ['orderapi', 'eventapi'];
13
+ const DEFAULT_FDSERVICE_BASE_PATH = '/services/apexrest/FDService';
14
+ // ─── FontevaConnector ──────────────────────────────────────────────────
15
+ /**
16
+ * Fonteva AMS connector.
17
+ *
18
+ * Fonteva is a Salesforce **managed package** (the OrderApi__ and EventApi__
19
+ * namespaces), so it rides the core Salesforce REST infrastructure verbatim.
20
+ * This connector therefore COMPOSES on {@link SalesforceConnector}, reusing —
21
+ * unchanged — its:
22
+ * - Salesforce OAuth2 bearer authentication (JWT-bearer / client-credentials),
23
+ * - global describe object discovery (`/services/data/vXX/sobjects/`),
24
+ * - per-object `/describe` field discovery,
25
+ * - SOQL incremental fetch with `nextRecordsUrl` cursor pagination,
26
+ * - `SystemModstamp` watermark incremental sync,
27
+ * - generic sObject CRUD (POST/PATCH/DELETE) and the `BuildCreatedResult`
28
+ * loud-fail-on-empty-ID write contract.
29
+ *
30
+ * The Fonteva-specific layer added here is intentionally thin:
31
+ * 1. **Namespace scoping** — `DiscoverObjects` filters the inherited Salesforce
32
+ * global describe down to the managed-package namespaces (OrderApi__ /
33
+ * EventApi__), so the connector surfaces ONLY Fonteva AMS objects (the
34
+ * standard SF CRM objects are the SalesforceConnector's job).
35
+ * 2. **IO-name ↔ backing-sObject translation** — the friendly IO `Name`
36
+ * ("Assignment") is mapped to its real sObject API name
37
+ * ("OrderApi__Assignment__c", read from the IO's Configuration) before
38
+ * every inherited Salesforce operation, and the returned records'
39
+ * `ObjectType` is rewritten back to the IO name for engine identity.
40
+ * 3. **FDService domain services** — the `/services/apexrest/FDService/*` Apex
41
+ * REST services are wired as an opt-in read path with the documented
42
+ * SearchRequest filter/fields/sort/limit query params.
43
+ *
44
+ * Discovery is the live global-describe MECHANISM (no baked catalog); the object
45
+ * universe is Declared (docs) + Discovered (runtime describe). Writes use the
46
+ * inherited generic sObject CRUD; FDService write shapes are not idiosyncratic
47
+ * enough to warrant overriding the sObject write path (the metadata routes all
48
+ * writes through the platform sObject endpoints).
49
+ */
50
+ let FontevaConnector = class FontevaConnector extends SalesforceConnector {
51
+ constructor() {
52
+ super(...arguments);
53
+ this._fontevaConfig = null;
54
+ }
55
+ // ─── Identity (three-way invariant) ──────────────────────────────
56
+ get IntegrationName() { return 'Fonteva'; }
57
+ /**
58
+ * AUTHORITATIVE discovery (inherited rationale): the scoped global describe
59
+ * enumerates the COMPLETE set of Fonteva managed-package objects the
60
+ * credentials expose, so absence in a refresh genuinely means the object was
61
+ * removed and the engine may safely deactivate it. Kept explicit so the
62
+ * Fonteva-scoped filter doesn't quietly inherit a non-authoritative default.
63
+ */
64
+ get DiscoveryIsAuthoritative() { return true; }
65
+ // ─── Config ──────────────────────────────────────────────────────
66
+ /**
67
+ * Parses the integration-level Configuration JSON for the Fonteva-specific
68
+ * knobs (managed-package namespaces, FDService base path, opt-in FDService
69
+ * read). Tolerant of missing/invalid Configuration — falls back to documented
70
+ * defaults so a freshly-seeded integration works without extra config.
71
+ */
72
+ GetFontevaConfig(companyIntegration) {
73
+ if (this._fontevaConfig)
74
+ return this._fontevaConfig;
75
+ const defaults = {
76
+ ManagedPackageNamespaces: [...DEFAULT_MANAGED_PACKAGE_NAMESPACES],
77
+ FDServiceBasePath: DEFAULT_FDSERVICE_BASE_PATH,
78
+ UseFDServiceForRead: false,
79
+ };
80
+ const raw = companyIntegration.Configuration;
81
+ if (!raw) {
82
+ this._fontevaConfig = defaults;
83
+ return defaults;
84
+ }
85
+ try {
86
+ const parsed = JSON.parse(raw);
87
+ const namespaces = Array.isArray(parsed['ManagedPackageNamespaces'])
88
+ ? parsed['ManagedPackageNamespaces']
89
+ .filter((n) => typeof n === 'string')
90
+ .map(n => n.toLowerCase())
91
+ : defaults.ManagedPackageNamespaces;
92
+ const fdBasePath = typeof parsed['FDServiceBasePath'] === 'string'
93
+ ? parsed['FDServiceBasePath']
94
+ : defaults.FDServiceBasePath;
95
+ const useFDService = parsed['UseFDServiceForRead'] === true;
96
+ this._fontevaConfig = {
97
+ ManagedPackageNamespaces: namespaces.length > 0 ? namespaces : defaults.ManagedPackageNamespaces,
98
+ FDServiceBasePath: fdBasePath,
99
+ UseFDServiceForRead: useFDService,
100
+ };
101
+ }
102
+ catch {
103
+ this._fontevaConfig = defaults;
104
+ }
105
+ return this._fontevaConfig;
106
+ }
107
+ // ─── Discovery (scoped to the managed-package namespaces) ────────
108
+ /**
109
+ * Discovers Fonteva objects by reusing the inherited Salesforce global
110
+ * describe and filtering it to the managed-package namespaces. NO baked
111
+ * catalog — the list comes entirely from the live `/sobjects/` describe; this
112
+ * method only scopes it and presents the friendly (namespace-stripped) IO name.
113
+ */
114
+ async DiscoverObjects(companyIntegration, contextUser) {
115
+ const cfg = this.GetFontevaConfig(companyIntegration);
116
+ const all = await super.DiscoverObjects(companyIntegration, contextUser);
117
+ const sObjectToIOName = this.BuildBackingSObjectReverseMap(companyIntegration);
118
+ return all
119
+ .filter(o => this.IsInManagedPackage(o.Name, cfg.ManagedPackageNamespaces))
120
+ .map(o => ({
121
+ ...o,
122
+ // Prefer the DECLARED IO name whose Configuration.BackingSObject matches this sObject —
123
+ // this lets IOs whose name diverges from the mechanical derivation map correctly
124
+ // (Term → OrderApi__Renewal__c, EventChatterGroup → EventApi__Event_Chatter_Groups__c).
125
+ // Fall back to the mechanical namespace-strip + PascalCase when no declared mapping exists
126
+ // (a genuinely Discovered object the metadata doesn't yet name).
127
+ Name: sObjectToIOName.get(o.Name.toLowerCase()) ?? this.SObjectToFriendlyName(o.Name),
128
+ }));
129
+ }
130
+ /**
131
+ * Builds a reverse map (lower-cased backing sObject API name → declared IO Name) from the
132
+ * loaded metadata — the inverse of {@link ResolveBackingSObject}. Used at discovery time so a
133
+ * discovered sObject resolves to the IO the metadata actually declares for it, instead of a
134
+ * mechanically-derived name that may not round-trip (singular/plural, wrapper-vs-sObject renames).
135
+ * Returns an empty map when the engine cache isn't populated (e.g. unit tests) — callers then
136
+ * fall back to {@link SObjectToFriendlyName}.
137
+ */
138
+ BuildBackingSObjectReverseMap(companyIntegration) {
139
+ const map = new Map();
140
+ try {
141
+ const ios = IntegrationEngineBase.Instance.IntegrationObjects.filter(io => io.IntegrationID === companyIntegration.IntegrationID);
142
+ for (const io of ios) {
143
+ if (!io.Configuration)
144
+ continue;
145
+ try {
146
+ const objCfg = JSON.parse(io.Configuration);
147
+ if (objCfg.BackingSObject)
148
+ map.set(objCfg.BackingSObject.toLowerCase(), io.Name);
149
+ }
150
+ catch { /* unparseable Configuration — skip this IO */ }
151
+ }
152
+ }
153
+ catch { /* engine cache unavailable — caller falls back to mechanical derivation */ }
154
+ return map;
155
+ }
156
+ /**
157
+ * Discovers fields for a Fonteva object. Translates the friendly IO name back
158
+ * to its backing sObject API name, then reuses the inherited Salesforce
159
+ * `/describe` field discovery verbatim.
160
+ */
161
+ async DiscoverFields(companyIntegration, objectName, contextUser) {
162
+ const sObject = this.ResolveBackingSObject(companyIntegration, objectName);
163
+ return super.DiscoverFields(companyIntegration, sObject, contextUser);
164
+ }
165
+ /**
166
+ * Full schema introspection scoped to the managed-package namespaces. Defers
167
+ * entirely to the inherited Salesforce introspection (which calls
168
+ * DiscoverObjects — overridden here to scope — then `/describe`s each), but
169
+ * re-resolves any caller-supplied ObjectNames (friendly IO names) to their
170
+ * backing sObjects so the inherited describe loop targets real sObjects.
171
+ */
172
+ async IntrospectSchema(companyIntegration, contextUser, options) {
173
+ if (options?.ObjectNames && options.ObjectNames.length > 0) {
174
+ const resolved = options.ObjectNames.map(n => this.ResolveBackingSObject(companyIntegration, n));
175
+ return super.IntrospectSchema(companyIntegration, contextUser, { ...options, ObjectNames: resolved });
176
+ }
177
+ return super.IntrospectSchema(companyIntegration, contextUser, options);
178
+ }
179
+ // ─── Fetch (SOQL platform layer reused; FDService opt-in) ────────
180
+ /**
181
+ * Fetches changed records. Default path reuses the inherited Salesforce SOQL
182
+ * incremental fetch (SystemModstamp watermark + nextRecordsUrl cursor)
183
+ * verbatim, with the IO name translated to its backing sObject. When the
184
+ * connection opts into FDService reads (`UseFDServiceForRead`), routes through
185
+ * the FDService Apex REST domain service instead.
186
+ */
187
+ async FetchChanges(ctx) {
188
+ const cfg = this.GetFontevaConfig(ctx.CompanyIntegration);
189
+ const ioName = ctx.ObjectName;
190
+ const objCfg = this.GetObjectConfig(ctx.CompanyIntegration, ioName);
191
+ if (cfg.UseFDServiceForRead && objCfg?.AccessPath?.fdServicePath) {
192
+ const batch = await this.FetchViaFDService(ctx, objCfg, cfg);
193
+ return this.RewriteObjectType(batch, ioName);
194
+ }
195
+ const sObject = objCfg?.BackingSObject ?? this.ResolveBackingSObject(ctx.CompanyIntegration, ioName);
196
+ const batch = await super.FetchChanges({ ...ctx, ObjectName: sObject });
197
+ return this.RewriteObjectType(batch, ioName);
198
+ }
199
+ // ─── CRUD (generic sObject path reused; IO name → sObject) ───────
200
+ async CreateRecord(ctx) {
201
+ const sObject = this.ResolveBackingSObject(ctx.CompanyIntegration, ctx.ObjectName);
202
+ return super.CreateRecord({ ...ctx, ObjectName: sObject });
203
+ }
204
+ async UpdateRecord(ctx) {
205
+ const sObject = this.ResolveBackingSObject(ctx.CompanyIntegration, ctx.ObjectName);
206
+ return super.UpdateRecord({ ...ctx, ObjectName: sObject });
207
+ }
208
+ async DeleteRecord(ctx) {
209
+ const sObject = this.ResolveBackingSObject(ctx.CompanyIntegration, ctx.ObjectName);
210
+ return super.DeleteRecord({ ...ctx, ObjectName: sObject });
211
+ }
212
+ async GetRecord(ctx) {
213
+ const sObject = this.ResolveBackingSObject(ctx.CompanyIntegration, ctx.ObjectName);
214
+ const record = await super.GetRecord({ ...ctx, ObjectName: sObject });
215
+ if (record)
216
+ record.ObjectType = ctx.ObjectName;
217
+ return record;
218
+ }
219
+ async SearchRecords(ctx) {
220
+ const sObject = this.ResolveBackingSObject(ctx.CompanyIntegration, ctx.ObjectName);
221
+ const result = await super.SearchRecords({ ...ctx, ObjectName: sObject });
222
+ for (const r of result.Records)
223
+ r.ObjectType = ctx.ObjectName;
224
+ return result;
225
+ }
226
+ // ─── FDService Apex REST domain services ─────────────────────────
227
+ /**
228
+ * Reads records through a Fonteva FDService Apex REST domain service using
229
+ * the documented SearchRequest parameters (filter / fields / sort / limit).
230
+ * The connector follows the SystemModstamp watermark by encoding a SOQL WHERE
231
+ * fragment into the `filter` (a.k.a. whereClause) param.
232
+ *
233
+ * Idiosyncratic to Fonteva: FDService returns the wrapper records under a
234
+ * `records` key (camelCase wrapper properties), with the universal `id`
235
+ * property carrying the Salesforce 18-char Id. There is no documented cursor
236
+ * token, so pagination is bounded by `limit` and advanced by the watermark on
237
+ * subsequent syncs (the connector reports the max SystemModstamp it saw).
238
+ */
239
+ async FetchViaFDService(ctx, objCfg, cfg) {
240
+ const auth = await this.AuthenticateForFonteva(ctx.CompanyIntegration, ctx.ContextUser);
241
+ const servicePath = objCfg.AccessPath?.fdServicePath ?? this.BuildFDServicePath(cfg, objCfg);
242
+ const params = this.BuildFDServiceSearchParams(ctx);
243
+ const query = this.EncodeFDServiceParams(params);
244
+ const url = `${this.FontevaApiBase(auth)}${servicePath}${query ? `?${query}` : ''}`;
245
+ const headers = this.FontevaHeaders(auth);
246
+ const response = await this.MakeFontevaRequest(auth, url, 'GET', headers);
247
+ if (response.Status < 200 || response.Status >= 300) {
248
+ throw new Error(`Fonteva FDService GET ${url} returned HTTP ${response.Status}: ${this.PreviewFonteva(response.Body)}`);
249
+ }
250
+ const records = this.ParseFDServiceRecords(response.Body, ctx.ObjectName);
251
+ const newWatermark = this.MaxSystemModstamp(records);
252
+ return {
253
+ Records: records,
254
+ HasMore: false,
255
+ NewWatermarkValue: newWatermark ?? undefined,
256
+ };
257
+ }
258
+ /** Builds SearchRequest params from the fetch context (watermark → filter). */
259
+ BuildFDServiceSearchParams(ctx) {
260
+ const params = {
261
+ limit: ctx.BatchSize > 0 ? ctx.BatchSize : undefined,
262
+ sort: 'SystemModstamp',
263
+ sorDir: 'ASC',
264
+ };
265
+ if (ctx.WatermarkValue) {
266
+ params.filter = `SystemModstamp >= ${this.FormatFDServiceDateTime(ctx.WatermarkValue)}`;
267
+ }
268
+ if (ctx.RequestedSourceFields && ctx.RequestedSourceFields.length > 0) {
269
+ params.fields = ctx.RequestedSourceFields.join(',');
270
+ }
271
+ return params;
272
+ }
273
+ EncodeFDServiceParams(params) {
274
+ const usp = new URLSearchParams();
275
+ if (params.id)
276
+ usp.set('id', params.id);
277
+ if (params.filter)
278
+ usp.set('filter', params.filter);
279
+ if (params.fields)
280
+ usp.set('fields', params.fields);
281
+ if (params.sort)
282
+ usp.set('sort', params.sort);
283
+ if (params.sorDir)
284
+ usp.set('sorDir', params.sorDir);
285
+ if (params.limit != null)
286
+ usp.set('limit', String(params.limit));
287
+ return usp.toString();
288
+ }
289
+ FormatFDServiceDateTime(value) {
290
+ return value.includes('T') ? value : `${value}T00:00:00.000Z`;
291
+ }
292
+ /**
293
+ * Parses an FDService response into ExternalRecords. FDService wraps records
294
+ * under a `records` array (each a flat camelCase wrapper object whose `id`
295
+ * carries the Salesforce Id). Preserves the FULL record into Fields for
296
+ * custom-column capture — no narrow projection.
297
+ */
298
+ ParseFDServiceRecords(body, objectType) {
299
+ const envelope = body;
300
+ const list = Array.isArray(envelope)
301
+ ? envelope
302
+ : Array.isArray(envelope?.records) ? envelope.records : [];
303
+ return list.map(item => {
304
+ const raw = item;
305
+ const id = String(raw['id'] ?? raw['Id'] ?? '');
306
+ const modstamp = (raw['SystemModstamp'] ?? raw['systemModstamp']);
307
+ return {
308
+ ExternalID: id,
309
+ ObjectType: objectType,
310
+ Fields: { ...raw }, // full record pass-through (custom-column capture contract)
311
+ ModifiedAt: modstamp ? new Date(modstamp) : undefined,
312
+ };
313
+ });
314
+ }
315
+ MaxSystemModstamp(records) {
316
+ let max = null;
317
+ for (const r of records) {
318
+ const stamp = (r.Fields['SystemModstamp'] ?? r.Fields['systemModstamp']);
319
+ if (stamp && (!max || stamp > max))
320
+ max = stamp;
321
+ }
322
+ if (!max)
323
+ return null;
324
+ const parsed = new Date(max);
325
+ if (Number.isNaN(parsed.getTime()))
326
+ return max;
327
+ // Advance 1ms so the next `>=` filter excludes the boundary cluster (mirrors the SOQL path).
328
+ return new Date(parsed.getTime() + 1).toISOString();
329
+ }
330
+ BuildFDServicePath(cfg, objCfg) {
331
+ const wrapper = objCfg.FDServiceWrapper ?? 'Order';
332
+ return `${cfg.FDServiceBasePath}/${wrapper}Service`;
333
+ }
334
+ // ─── Backing-sObject resolution ──────────────────────────────────
335
+ /**
336
+ * Resolves the friendly IO `Name` to its backing Salesforce sObject API name.
337
+ * Reads the IO's Configuration.BackingSObject from the engine cache; falls
338
+ * back to a namespace-prefixed PascalSnake derivation when metadata isn't
339
+ * loaded (e.g. unit tests) or the IO already IS a fully-qualified sObject.
340
+ */
341
+ ResolveBackingSObject(companyIntegration, ioName) {
342
+ const objCfg = this.GetObjectConfig(companyIntegration, ioName);
343
+ if (objCfg?.BackingSObject)
344
+ return objCfg.BackingSObject;
345
+ // Already a fully-qualified managed-package sObject — pass through unchanged.
346
+ if (/__c$/i.test(ioName))
347
+ return ioName;
348
+ return ioName; // best-effort: unmapped name used verbatim (describe will surface a clear error)
349
+ }
350
+ /** Reads + parses the per-IO Configuration from the engine cache. Returns null if unavailable. */
351
+ GetObjectConfig(companyIntegration, ioName) {
352
+ try {
353
+ const obj = IntegrationEngineBase.Instance.GetIntegrationObject(companyIntegration.IntegrationID, ioName);
354
+ if (!obj?.Configuration)
355
+ return null;
356
+ return JSON.parse(obj.Configuration);
357
+ }
358
+ catch {
359
+ return null;
360
+ }
361
+ }
362
+ // ─── Namespace + name helpers ────────────────────────────────────
363
+ IsInManagedPackage(sObjectName, namespaces) {
364
+ const lower = sObjectName.toLowerCase();
365
+ return namespaces.some(ns => lower.startsWith(`${ns}__`));
366
+ }
367
+ /**
368
+ * Presents a managed-package sObject API name as a friendly IO name by
369
+ * stripping the namespace prefix and the `__c` suffix and PascalCasing the
370
+ * snake segments (e.g. OrderApi__Sales_Order_Line__c → SalesOrderLine).
371
+ */
372
+ SObjectToFriendlyName(sObjectName) {
373
+ const withoutNamespace = sObjectName.replace(/^[A-Za-z]+__/i, '');
374
+ const withoutSuffix = withoutNamespace.replace(/__c$/i, '');
375
+ return withoutSuffix
376
+ .split('_')
377
+ .filter(seg => seg.length > 0)
378
+ .map(seg => seg.charAt(0).toUpperCase() + seg.slice(1))
379
+ .join('');
380
+ }
381
+ /** Rewrites a fetch batch's record ObjectType from the backing sObject back to the IO name. */
382
+ RewriteObjectType(batch, ioName) {
383
+ for (const r of batch.Records)
384
+ r.ObjectType = ioName;
385
+ return batch;
386
+ }
387
+ // ─── Reuse-friendly thin wrappers over inherited protected helpers ──
388
+ // SalesforceConnector exposes Authenticate / BuildHeaders / MakeHTTPRequest /
389
+ // GetBaseURL as protected; these named wrappers keep the FDService code paths
390
+ // readable and route ALL FDService HTTP through the same auth + mock-redirect
391
+ // surface the inherited SOQL path uses (so FDService is mock-testable too).
392
+ async AuthenticateForFonteva(companyIntegration, contextUser) {
393
+ return this.Authenticate(companyIntegration, contextUser);
394
+ }
395
+ FontevaHeaders(auth) {
396
+ return this.BuildHeaders(auth);
397
+ }
398
+ async MakeFontevaRequest(auth, url, method, headers, body) {
399
+ return this.MakeHTTPRequest(auth, url, method, headers, body);
400
+ }
401
+ FontevaApiBase(auth) {
402
+ return this.GetBaseURL(auth.CompanyIntegration, auth);
403
+ }
404
+ PreviewFonteva(body) {
405
+ if (typeof body === 'string')
406
+ return body.slice(0, 500);
407
+ try {
408
+ return JSON.stringify(body).slice(0, 500);
409
+ }
410
+ catch {
411
+ return String(body);
412
+ }
413
+ }
414
+ };
415
+ FontevaConnector = __decorate([
416
+ RegisterClass(BaseIntegrationConnector, '@memberjunction/connector-fonteva')
417
+ ], FontevaConnector);
418
+ export { FontevaConnector };
419
+ /** Tree-shaking prevention: referenced from index.ts so the @RegisterClass survives bundling. */
420
+ export function LoadFontevaConnector() { }
421
+ //# sourceMappingURL=FontevaConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FontevaConnector.js","sourceRoot":"","sources":["../src/FontevaConnector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './FontevaConnector.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 './FontevaConnector.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,uBAAuB,CAAC;AAEtC;oGACoG;AACpG,MAAM,UAAU,iBAAiB,KAAiD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@memberjunction/connector-fonteva",
3
+ "version": "1.0.0",
4
+ "description": "MemberJunction Fonteva 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
+ "@memberjunction/integration-engine-base": ">=5.42.0 <6.0.0"
23
+ },
24
+ "dependencies": {
25
+ "@memberjunction/connector-salesforce": "*"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "24.10.11",
29
+ "tsc-alias": "^1.8.16",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^4.0.18",
32
+ "@memberjunction/core": "^5.42.0",
33
+ "@memberjunction/core-entities": "^5.42.0",
34
+ "@memberjunction/global": "^5.42.0",
35
+ "@memberjunction/integration-engine": "^5.42.0",
36
+ "@memberjunction/integration-engine-base": "^5.42.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/MemberJunction/Integrations"
41
+ }
42
+ }