@memberjunction/connector-hivebrite 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,150 @@
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 RateLimitPolicy, type ConnectionTestResult, type ExternalObjectSchema, type ExternalFieldSchema, type FetchContext, type FetchBatchResult } from '@memberjunction/integration-engine';
4
+ /**
5
+ * OAuth2 connection configuration for Hivebrite, parsed from the attached MJ Credential
6
+ * (preferred) or the CompanyIntegration.Configuration JSON. Field names are read
7
+ * case-insensitively. None of these values are read at build time — they are resolved
8
+ * from the bound credential at runtime.
9
+ */
10
+ export interface HivebriteConnectionConfig {
11
+ /** OAuth2 client identifier (Hivebrite community OAuth application). */
12
+ ClientId: string;
13
+ /** OAuth2 client secret. */
14
+ ClientSecret: string;
15
+ /** Long-lived refresh token — drives the PRIMARY `refresh_token` grant. */
16
+ RefreshToken?: string;
17
+ /** Admin email — drives the FALLBACK `password` grant (sent as `admin_email`). */
18
+ AdminEmail?: string;
19
+ /** Admin password — drives the FALLBACK `password` grant. */
20
+ Password?: string;
21
+ /** OAuth2 scope. Defaults to `admin` per the Hivebrite Admin API. */
22
+ Scope?: string;
23
+ /** Per-community API base URL (e.g. https://{community}.hivebrite.com). */
24
+ BaseURL: string;
25
+ /** Optional token-endpoint override; defaults to `{base}/api/oauth/token`. */
26
+ TokenURL?: string;
27
+ /** Maximum retries for rate-limited / transient failures. Default 3. */
28
+ MaxRetries?: number;
29
+ /** HTTP request timeout in ms. Default 30000. */
30
+ RequestTimeoutMs?: number;
31
+ }
32
+ export declare class HivebriteConnector extends BaseRESTIntegrationConnector {
33
+ /** Cached auth context for the current sync run. */
34
+ private authCache;
35
+ /** Shared OAuth2 token manager — owns the token round-trip + cache (no inline crypto). */
36
+ private readonly tokenManager;
37
+ /** Current watermark value, emitted as the IO's IncrementalWatermarkField on the request. */
38
+ private currentWatermark;
39
+ get IntegrationName(): string;
40
+ get SupportsCreate(): boolean;
41
+ get SupportsUpdate(): boolean;
42
+ get SupportsDelete(): boolean;
43
+ /** True when any cached IntegrationObject satisfies the predicate. []→false when the engine
44
+ * cache is unavailable (e.g. capability probed before configuration) — fail-safe read-only. */
45
+ private anyObjectDeclares;
46
+ /**
47
+ * Hivebrite documents a 300 req/min limit (5 req/sec). A secondary throttle triggers after
48
+ * 15 HTTP 500+ errors/min. The engine's AIMD token bucket honors this; we set a conservative
49
+ * burst and a slower-than-default recovery so a throttle doesn't immediately re-spike.
50
+ */
51
+ get RateLimitPolicy(): RateLimitPolicy;
52
+ /**
53
+ * Parses a `Retry-After` header (seconds or http-date) into ms. Hivebrite does not document a
54
+ * Retry-After header, but Doorkeeper-fronted 429/503 responses may carry one; honor it when present.
55
+ */
56
+ ExtractRetryAfterMs(error: unknown): number | undefined;
57
+ /**
58
+ * OAuth2 bearer authentication. Mints/refreshes the access token via the shared
59
+ * {@link OAuth2TokenManager}: PRIMARY `refresh_token` grant when a refresh token is
60
+ * present, otherwise the documented FALLBACK `password` grant (admin_email + password).
61
+ */
62
+ protected Authenticate(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<RESTAuthContext>;
63
+ /** Selects the grant and runs the token round-trip through OAuth2TokenManager. */
64
+ private MintToken;
65
+ /** Sends the OAuth2 bearer token on every request. */
66
+ protected BuildHeaders(auth: RESTAuthContext): Record<string, string>;
67
+ protected GetBaseURL(_companyIntegration: MJCompanyIntegrationEntity, auth: RESTAuthContext): string;
68
+ /**
69
+ * Normalizes Hivebrite responses. Handles three real shapes:
70
+ * 1. bare array — list endpoints return a top-level JSON array of records
71
+ * 2. `{ <key>: [...] }` envelope — when an IO declares a ResponseDataKey
72
+ * 3. single object — detail (GET /resource/{id}) endpoints return ONE record
73
+ * Empty strings are coerced to null so date/optional columns persist cleanly.
74
+ * The FULL source record passes through (no field filtering) so the framework's
75
+ * custom-column capture sees everything the source returned.
76
+ */
77
+ protected NormalizeResponse(rawBody: unknown, responseDataKey: string | null): Record<string, unknown>[];
78
+ /**
79
+ * Derives PageNumber pagination state. Hivebrite returns a bare array per page and signals
80
+ * the next page via the RFC-5988 `Link` header — which the base pagination loop does not pass
81
+ * to this method (it receives only the parsed body). The safe, header-free terminator is a
82
+ * SHORT page: fewer rows than the requested `per_page` means the last page was reached. A FULL
83
+ * page means more may remain. The base loop also independently stops on an empty page and on a
84
+ * duplicate-first-record page, so this never loops unboundedly.
85
+ */
86
+ protected ExtractPaginationInfo(rawBody: unknown, _paginationType: PaginationType, currentPage: number, _currentOffset: number, pageSize: number): PaginationState;
87
+ /** Returns the rows of a single-array-property envelope body (else []). */
88
+ private extractSingleArrayLength;
89
+ /**
90
+ * Emits Hivebrite PageNumber params (`page`/`per_page`) plus, for an incremental IO, the vendor
91
+ * watermark param. The watermark behaviour is fully METADATA-DRIVEN: the param NAME comes from
92
+ * the IO's `IncrementalWatermarkField` (e.g. `updated_since` / `created_since` / `deleted_since`)
93
+ * and is emitted only when `SupportsIncrementalSync=true` AND a watermark value is in context.
94
+ * `per_page` is clamped to the server cap (100).
95
+ */
96
+ protected BuildPaginatedURL(basePath: string, obj: MJIntegrationObjectEntity, page: number, _offset: number, _cursor?: string, effectivePageSize?: number): string;
97
+ /** Executes an HTTP request with retry/backoff for 429/503 + transient network errors. */
98
+ protected MakeHTTPRequest(auth: RESTAuthContext, url: string, method: string, headers: Record<string, string>, body?: unknown): Promise<RESTResponse>;
99
+ /**
100
+ * Tests connectivity by minting an OAuth2 token and listing one User record. A 2xx
101
+ * confirms the OAuth2 credentials + per-community base URL are valid against the live API.
102
+ */
103
+ TestConnection(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<ConnectionTestResult>;
104
+ /**
105
+ * Discovers the full object universe from the IntegrationEngineBase cache (the Declared
106
+ * metadata). Hivebrite publishes its catalog credential-free (OpenAPI spec), so the baseline
107
+ * is Declared metadata — never hardcoded here, never sampled at build. A live credential is
108
+ * ADDITIVE (tenant-specific custom fields surfaced at sync via the framework's custom-column
109
+ * capture), never the baseline — so credential-free discovery re-yields the standard universe.
110
+ */
111
+ DiscoverObjects(companyIntegration: MJCompanyIntegrationEntity, contextUser: UserInfo): Promise<ExternalObjectSchema[]>;
112
+ /** Discovers fields for an object from the cached Declared metadata. */
113
+ DiscoverFields(companyIntegration: MJCompanyIntegrationEntity, objectName: string, contextUser: UserInfo): Promise<ExternalFieldSchema[]>;
114
+ /**
115
+ * Sets the watermark context the page URL builder needs, delegates the actual walk to the
116
+ * base (which descends nested Door→Segment template-var paths via FK metadata so nested IOs
117
+ * never silently return 0 rows), then advances the watermark from the returned records on the
118
+ * final batch only (partial-failure-safe).
119
+ */
120
+ FetchChanges(ctx: FetchContext): Promise<FetchBatchResult>;
121
+ /**
122
+ * Parses the OAuth2 connection config, preferring the attached MJ Credential over the raw
123
+ * Configuration JSON. Credential bytes are resolved at runtime — never at build.
124
+ */
125
+ private ParseConfig;
126
+ /** Loads the OAuth2 config from the MJ: Credentials entity Values JSON. */
127
+ private ParseConfigFromCredential;
128
+ /** Validates the parsed config + applies defaults. Field names are case-insensitive. */
129
+ private ValidateConfig;
130
+ /** Resolves the API base URL from the credential's BaseURL (never a hardcoded host). Strips a trailing /api. */
131
+ private ResolveBaseUrl;
132
+ /** Resolves the OAuth2 token endpoint: credential TokenURL override, else `{base}/api/oauth/token`. */
133
+ private ResolveTokenURL;
134
+ /** Normalizes a raw record's top-level values (empty-string → null). */
135
+ private NormalizeRecord;
136
+ /** Extracts the latest updated_at / created_at across a batch for watermark advancement. */
137
+ private ExtractLatestUpdatedAt;
138
+ /** Parses a Retry-After header (seconds or http-date) into ms, if present. */
139
+ private RetryAfterMs;
140
+ /** Exponential backoff delay for retry attempts (capped at 30s). */
141
+ private BackoffDelay;
142
+ /** Checks whether an error is transient (network/timeout). */
143
+ private IsTransientNetworkError;
144
+ /** Builds the normalized RESTResponse from a fetch Response. */
145
+ private BuildRESTResponse;
146
+ /** Promise-wrapped setTimeout. */
147
+ private Sleep;
148
+ }
149
+ /** Tree-shaking prevention — import and call from the package entry point. */
150
+ export declare function LoadHivebriteConnector(): void;
@@ -0,0 +1,533 @@
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
+ * HivebriteConnector — Integration connector for the Hivebrite community-management
9
+ * platform Admin API (v1 / v2 / v3).
10
+ *
11
+ * API docs: https://api-docs.hivebrite.com/ (OpenAPI spec — 174 paths across three
12
+ * concurrent version namespaces: /api/admin/v1, /api/admin/v2, /api/admin/v3).
13
+ *
14
+ * ── Auth: OAuth2 (password + refresh_token grants) ───────────────────────────
15
+ * Mints/refreshes a bearer ACCESS TOKEN via the shared {@link OAuth2TokenManager}
16
+ * (no inlined token/crypto logic). Hivebrite runs a Doorkeeper/WineBouncer OAuth2
17
+ * server (RFC 6749 §4.3 resource-owner password credentials grant):
18
+ * - PRIMARY grant = `refresh_token` (refresh_token + client_id + client_secret
19
+ * POSTed to `{base}/api/oauth/token`) when a refresh token exists.
20
+ * - FALLBACK grant = `password` (admin_email + password + client_id + client_secret
21
+ * + scope=admin) when no refresh token is supplied.
22
+ * Hivebrite names the password-grant username param `admin_email` (not the spec's
23
+ * `username`); the token manager's `UsernameParam` field carries that divergence —
24
+ * the crypto/round-trip itself stays in the shared helper.
25
+ * Every API request sends `Authorization: Bearer {accessToken}`.
26
+ *
27
+ * ── Base URL (per-community) ─────────────────────────────────────────────────
28
+ * The base host is per-community and comes from the credential/config `BaseURL`
29
+ * (e.g. `https://{community}.hivebrite.com` or the operator's custom domain). Never
30
+ * a hardcoded host. Object APIPaths in the metadata already carry the `/admin/vN`
31
+ * prefix; the connector prepends a `/api` segment to reach the live host root.
32
+ *
33
+ * ── Catalog (metadata-driven, NOT hardcoded) ─────────────────────────────────
34
+ * The 98-object / 1185-field universe comes from the Declared metadata seeded in
35
+ * `metadata/integrations/hivebrite/.hivebrite.integration.json` (case 1 — Hivebrite
36
+ * publishes its OpenAPI spec credential-free). The connector NEVER bakes an
37
+ * object/field catalog into code; DiscoverObjects/DiscoverFields read the cache.
38
+ *
39
+ * ── Pagination & incremental ─────────────────────────────────────────────────
40
+ * PageNumber pagination via `page` (1-based) + `per_page` (max 100, recommended 25).
41
+ * Hivebrite returns a bare JSON array per page plus RFC-5988 `Link` headers; the base
42
+ * pagination loop terminates on an empty page, and this connector additionally treats
43
+ * a short page (fewer rows than the requested `per_page`) as end-of-stream. Incremental
44
+ * sync is fully metadata-driven: an IO with `SupportsIncrementalSync=true` emits its
45
+ * `IncrementalWatermarkField` param (`updated_since` / `created_since` / `deleted_since`)
46
+ * carrying the watermark; every other IO is a full pull (engine content-hash dedup).
47
+ *
48
+ * ── Write ─────────────────────────────────────────────────────────────────────
49
+ * Most resources support full CRUD; the generic per-operation CRUD path on the base
50
+ * reads the IO's Create/Update/Delete columns. Write capability is METADATA-DRIVEN
51
+ * (follows the per-operation columns on the cached objects) — read-only when none are
52
+ * authored. Create routes through the base's `BuildCreatedResult` (loud empty-ID fail).
53
+ */
54
+ import { RegisterClass } from '@memberjunction/global';
55
+ import { Metadata } from '@memberjunction/core';
56
+ import { BaseIntegrationConnector, BaseRESTIntegrationConnector, OAuth2TokenManager, } from '@memberjunction/integration-engine';
57
+ import { IntegrationEngineBase } from '@memberjunction/integration-engine-base';
58
+ // ─── Constants ───────────────────────────────────────────────────────
59
+ /** The canonical MJ: Integrations.Name — part of the three-way invariant. */
60
+ const INTEGRATION_NAME = 'Hivebrite';
61
+ /** Token endpoint path appended to the base when no TokenURL override is supplied. */
62
+ const DEFAULT_TOKEN_PATH = '/api/oauth/token';
63
+ /** Default OAuth2 scope for the Hivebrite Admin API. */
64
+ const DEFAULT_SCOPE = 'admin';
65
+ /**
66
+ * Hivebrite PageNumber pagination params. `page` is 1-based; `per_page` max is 100
67
+ * (recommended 25). Documented in the OpenAPI spec info.description.
68
+ */
69
+ const PAGE_PARAM = 'page';
70
+ const PER_PAGE_PARAM = 'per_page';
71
+ /** Server-side hard cap on per_page (spec: "The maximum value for our APIs per_page param is 100"). */
72
+ const HIVEBRITE_MAX_PER_PAGE = 100;
73
+ const DEFAULT_PAGE_SIZE = 100;
74
+ const DEFAULT_MAX_RETRIES = 3;
75
+ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
76
+ /** Documented rate limit: 300 requests / minute = 5 requests / second. */
77
+ const HIVEBRITE_TOKENS_PER_SEC = 5;
78
+ const HIVEBRITE_BURST = 10;
79
+ // ─── Connector Implementation ────────────────────────────────────────
80
+ let HivebriteConnector = class HivebriteConnector extends BaseRESTIntegrationConnector {
81
+ constructor() {
82
+ super(...arguments);
83
+ /** Cached auth context for the current sync run. */
84
+ this.authCache = null;
85
+ /** Shared OAuth2 token manager — owns the token round-trip + cache (no inline crypto). */
86
+ this.tokenManager = new OAuth2TokenManager();
87
+ }
88
+ // Returns the EXACT MJ: Integrations.Name string LITERAL so the T1 ThreeWayName invariant can
89
+ // statically parse the getter's returned value from connector source. Verbatim from the
90
+ // identity-establisher handoff (metadata.fields.Name === 'Hivebrite').
91
+ get IntegrationName() { return 'Hivebrite'; }
92
+ // ── Capability getters: METADATA-DRIVEN (no hardcoded answer) ─────
93
+ //
94
+ // Write capability FOLLOWS the per-operation CRUD columns on the cached IntegrationObjects
95
+ // (Declared metadata). An object is create-capable when it declares both CreateAPIPath +
96
+ // CreateMethod; same for update/delete. The base BaseRESTIntegrationConnector generic CRUD path
97
+ // executes the verb off those columns; this connector wires no idiosyncratic write override —
98
+ // Hivebrite's writes are flat-body PUT/POST/DELETE that the generic per-operation path handles.
99
+ get SupportsCreate() {
100
+ return this.anyObjectDeclares(o => !!o.CreateAPIPath && !!o.CreateMethod);
101
+ }
102
+ get SupportsUpdate() {
103
+ return this.anyObjectDeclares(o => !!o.UpdateAPIPath && !!o.UpdateMethod);
104
+ }
105
+ get SupportsDelete() {
106
+ return this.anyObjectDeclares(o => !!o.DeleteAPIPath && !!o.DeleteMethod);
107
+ }
108
+ /** True when any cached IntegrationObject satisfies the predicate. []→false when the engine
109
+ * cache is unavailable (e.g. capability probed before configuration) — fail-safe read-only. */
110
+ anyObjectDeclares(pred) {
111
+ const integration = IntegrationEngineBase.Instance.GetIntegrationByName(INTEGRATION_NAME);
112
+ if (!integration)
113
+ return false;
114
+ return IntegrationEngineBase.Instance.GetActiveIntegrationObjects(integration.ID).some(pred);
115
+ }
116
+ // ── Sync-efficiency hooks (evidence from the frozen contract) ─────
117
+ /**
118
+ * Hivebrite documents a 300 req/min limit (5 req/sec). A secondary throttle triggers after
119
+ * 15 HTTP 500+ errors/min. The engine's AIMD token bucket honors this; we set a conservative
120
+ * burst and a slower-than-default recovery so a throttle doesn't immediately re-spike.
121
+ */
122
+ get RateLimitPolicy() {
123
+ return {
124
+ TokensPerSec: HIVEBRITE_TOKENS_PER_SEC,
125
+ Burst: HIVEBRITE_BURST,
126
+ ThrottleBackoffFactor: 0.5,
127
+ };
128
+ }
129
+ /**
130
+ * Parses a `Retry-After` header (seconds or http-date) into ms. Hivebrite does not document a
131
+ * Retry-After header, but Doorkeeper-fronted 429/503 responses may carry one; honor it when present.
132
+ */
133
+ ExtractRetryAfterMs(error) {
134
+ if (!error || typeof error !== 'object')
135
+ return undefined;
136
+ const headers = error.Headers;
137
+ const raw = headers?.['retry-after'];
138
+ if (!raw)
139
+ return undefined;
140
+ const asSeconds = Number(raw);
141
+ if (!Number.isNaN(asSeconds))
142
+ return Math.max(0, asSeconds * 1_000);
143
+ const asDate = new Date(raw).getTime();
144
+ if (!Number.isNaN(asDate))
145
+ return Math.max(0, asDate - Date.now());
146
+ return undefined;
147
+ }
148
+ // ─── BaseRESTIntegrationConnector abstract methods ──────────────
149
+ /**
150
+ * OAuth2 bearer authentication. Mints/refreshes the access token via the shared
151
+ * {@link OAuth2TokenManager}: PRIMARY `refresh_token` grant when a refresh token is
152
+ * present, otherwise the documented FALLBACK `password` grant (admin_email + password).
153
+ */
154
+ async Authenticate(companyIntegration, contextUser) {
155
+ if (this.authCache)
156
+ return this.authCache;
157
+ const config = await this.ParseConfig(companyIntegration, contextUser);
158
+ const baseUrl = this.ResolveBaseUrl(config);
159
+ const token = await this.MintToken(config, baseUrl);
160
+ const auth = { Token: token, BaseUrl: baseUrl, Config: config };
161
+ this.authCache = auth;
162
+ return auth;
163
+ }
164
+ /** Selects the grant and runs the token round-trip through OAuth2TokenManager. */
165
+ async MintToken(config, baseUrl) {
166
+ const tokenURL = this.ResolveTokenURL(config, baseUrl);
167
+ const grant = config.RefreshToken ? 'refresh_token' : 'password';
168
+ const req = {
169
+ TokenURL: tokenURL,
170
+ ClientId: config.ClientId,
171
+ ClientSecret: config.ClientSecret,
172
+ RefreshToken: config.RefreshToken,
173
+ Username: config.AdminEmail,
174
+ Password: config.Password,
175
+ // Hivebrite names the password-grant username param `admin_email` (Doorkeeper divergence).
176
+ UsernameParam: 'admin_email',
177
+ Scopes: config.Scope ?? DEFAULT_SCOPE,
178
+ ScopeParam: 'scope',
179
+ TimeoutMs: config.RequestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
180
+ };
181
+ const token = await this.tokenManager.GetAccessToken(req, grant);
182
+ return token.AccessToken;
183
+ }
184
+ /** Sends the OAuth2 bearer token on every request. */
185
+ BuildHeaders(auth) {
186
+ const token = auth.Token ?? auth.Token ?? '';
187
+ return {
188
+ 'Authorization': `Bearer ${token}`,
189
+ 'Accept': 'application/json',
190
+ 'Content-Type': 'application/json',
191
+ };
192
+ }
193
+ GetBaseURL(_companyIntegration, auth) {
194
+ // Object APIPaths carry the `/admin/vN/...` prefix; the live host root is `{base}/api`.
195
+ return `${auth.BaseUrl}/api`;
196
+ }
197
+ /**
198
+ * Normalizes Hivebrite responses. Handles three real shapes:
199
+ * 1. bare array — list endpoints return a top-level JSON array of records
200
+ * 2. `{ <key>: [...] }` envelope — when an IO declares a ResponseDataKey
201
+ * 3. single object — detail (GET /resource/{id}) endpoints return ONE record
202
+ * Empty strings are coerced to null so date/optional columns persist cleanly.
203
+ * The FULL source record passes through (no field filtering) so the framework's
204
+ * custom-column capture sees everything the source returned.
205
+ */
206
+ NormalizeResponse(rawBody, responseDataKey) {
207
+ if (rawBody == null)
208
+ return [];
209
+ if (Array.isArray(rawBody)) {
210
+ return rawBody.map(r => this.NormalizeRecord(r));
211
+ }
212
+ if (typeof rawBody === 'object') {
213
+ const body = rawBody;
214
+ if (responseDataKey && Array.isArray(body[responseDataKey])) {
215
+ return body[responseDataKey].map(r => this.NormalizeRecord(r));
216
+ }
217
+ // Some envelope endpoints expose a single array property (e.g. postal_addresses).
218
+ const arrayValues = Object.values(body).filter(v => Array.isArray(v));
219
+ if (arrayValues.length === 1 && Object.keys(body).length === 1) {
220
+ return arrayValues[0].map(r => this.NormalizeRecord(r));
221
+ }
222
+ // Genuine single-object detail record.
223
+ return [this.NormalizeRecord(body)];
224
+ }
225
+ return [];
226
+ }
227
+ /**
228
+ * Derives PageNumber pagination state. Hivebrite returns a bare array per page and signals
229
+ * the next page via the RFC-5988 `Link` header — which the base pagination loop does not pass
230
+ * to this method (it receives only the parsed body). The safe, header-free terminator is a
231
+ * SHORT page: fewer rows than the requested `per_page` means the last page was reached. A FULL
232
+ * page means more may remain. The base loop also independently stops on an empty page and on a
233
+ * duplicate-first-record page, so this never loops unboundedly.
234
+ */
235
+ ExtractPaginationInfo(rawBody, _paginationType, currentPage, _currentOffset, pageSize) {
236
+ const records = Array.isArray(rawBody)
237
+ ? rawBody
238
+ : this.extractSingleArrayLength(rawBody);
239
+ const effectivePerPage = Math.min(pageSize || DEFAULT_PAGE_SIZE, HIVEBRITE_MAX_PER_PAGE);
240
+ if (records.length === 0)
241
+ return { HasMore: false };
242
+ // A full page (>= the requested per_page) implies another page may exist.
243
+ if (records.length >= effectivePerPage) {
244
+ return { HasMore: true, NextPage: currentPage + 1 };
245
+ }
246
+ return { HasMore: false };
247
+ }
248
+ /** Returns the rows of a single-array-property envelope body (else []). */
249
+ extractSingleArrayLength(rawBody) {
250
+ if (!rawBody || typeof rawBody !== 'object')
251
+ return [];
252
+ const arrays = Object.values(rawBody).filter(Array.isArray);
253
+ return arrays.length === 1 ? arrays[0] : [];
254
+ }
255
+ /**
256
+ * Emits Hivebrite PageNumber params (`page`/`per_page`) plus, for an incremental IO, the vendor
257
+ * watermark param. The watermark behaviour is fully METADATA-DRIVEN: the param NAME comes from
258
+ * the IO's `IncrementalWatermarkField` (e.g. `updated_since` / `created_since` / `deleted_since`)
259
+ * and is emitted only when `SupportsIncrementalSync=true` AND a watermark value is in context.
260
+ * `per_page` is clamped to the server cap (100).
261
+ */
262
+ BuildPaginatedURL(basePath, obj, page, _offset, _cursor, effectivePageSize) {
263
+ const requested = effectivePageSize ?? obj.DefaultPageSize ?? DEFAULT_PAGE_SIZE;
264
+ const perPage = Math.min(requested, HIVEBRITE_MAX_PER_PAGE);
265
+ const separator = basePath.includes('?') ? '&' : '?';
266
+ const params = new URLSearchParams();
267
+ const watermarkField = obj.IncrementalWatermarkField;
268
+ if (obj.SupportsIncrementalSync && watermarkField && this.currentWatermark) {
269
+ params.set(watermarkField, this.currentWatermark);
270
+ }
271
+ params.set(PAGE_PARAM, String(page));
272
+ params.set(PER_PAGE_PARAM, String(perPage));
273
+ return `${basePath}${separator}${params.toString()}`;
274
+ }
275
+ /** Executes an HTTP request with retry/backoff for 429/503 + transient network errors. */
276
+ async MakeHTTPRequest(auth, url, method, headers, body) {
277
+ const hbAuth = auth;
278
+ const maxRetries = hbAuth.Config?.MaxRetries ?? DEFAULT_MAX_RETRIES;
279
+ const timeoutMs = hbAuth.Config?.RequestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
280
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
281
+ const fetchOptions = {
282
+ method,
283
+ headers,
284
+ signal: AbortSignal.timeout(timeoutMs),
285
+ };
286
+ if (body !== undefined && method !== 'GET') {
287
+ fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
288
+ }
289
+ let response;
290
+ try {
291
+ response = await fetch(url, fetchOptions);
292
+ }
293
+ catch (err) {
294
+ if (attempt < maxRetries && this.IsTransientNetworkError(err)) {
295
+ await this.Sleep(this.BackoffDelay(attempt));
296
+ continue;
297
+ }
298
+ throw err;
299
+ }
300
+ if ((response.status === 429 || response.status === 503) && attempt < maxRetries) {
301
+ console.warn(`[Hivebrite] HTTP ${response.status} from ${url} — backing off`);
302
+ await this.Sleep(this.RetryAfterMs(response) ?? this.BackoffDelay(attempt));
303
+ continue;
304
+ }
305
+ return this.BuildRESTResponse(response);
306
+ }
307
+ throw new Error(`Hivebrite request failed after ${maxRetries + 1} attempts: ${url}`);
308
+ }
309
+ // ─── TestConnection ──────────────────────────────────────────────
310
+ /**
311
+ * Tests connectivity by minting an OAuth2 token and listing one User record. A 2xx
312
+ * confirms the OAuth2 credentials + per-community base URL are valid against the live API.
313
+ */
314
+ async TestConnection(companyIntegration, contextUser) {
315
+ try {
316
+ const auth = (await this.Authenticate(companyIntegration, contextUser));
317
+ const headers = this.BuildHeaders(auth);
318
+ const url = `${this.GetBaseURL(companyIntegration, auth)}/admin/v1/users?${PER_PAGE_PARAM}=1`;
319
+ const response = await this.MakeHTTPRequest(auth, url, 'GET', headers);
320
+ if (response.Status < 200 || response.Status >= 300) {
321
+ return {
322
+ Success: false,
323
+ Message: `Hivebrite returned HTTP ${response.Status} from ${url}`,
324
+ };
325
+ }
326
+ return {
327
+ Success: true,
328
+ Message: `Connected to Hivebrite at ${auth.BaseUrl}`,
329
+ ServerVersion: 'Hivebrite Admin API',
330
+ };
331
+ }
332
+ catch (err) {
333
+ const message = err instanceof Error ? err.message : String(err);
334
+ return { Success: false, Message: `Connection failed: ${message}` };
335
+ }
336
+ }
337
+ // ─── Discovery (metadata-driven, no hardcoded catalog) ───────────
338
+ /**
339
+ * Discovers the full object universe from the IntegrationEngineBase cache (the Declared
340
+ * metadata). Hivebrite publishes its catalog credential-free (OpenAPI spec), so the baseline
341
+ * is Declared metadata — never hardcoded here, never sampled at build. A live credential is
342
+ * ADDITIVE (tenant-specific custom fields surfaced at sync via the framework's custom-column
343
+ * capture), never the baseline — so credential-free discovery re-yields the standard universe.
344
+ */
345
+ async DiscoverObjects(companyIntegration, contextUser) {
346
+ return super.DiscoverObjects(companyIntegration, contextUser);
347
+ }
348
+ /** Discovers fields for an object from the cached Declared metadata. */
349
+ async DiscoverFields(companyIntegration, objectName, contextUser) {
350
+ return super.DiscoverFields(companyIntegration, objectName, contextUser);
351
+ }
352
+ // ─── FetchChanges override ──────────────────────────────────────
353
+ /**
354
+ * Sets the watermark context the page URL builder needs, delegates the actual walk to the
355
+ * base (which descends nested Door→Segment template-var paths via FK metadata so nested IOs
356
+ * never silently return 0 rows), then advances the watermark from the returned records on the
357
+ * final batch only (partial-failure-safe).
358
+ */
359
+ async FetchChanges(ctx) {
360
+ this.currentWatermark = ctx.WatermarkValue ?? undefined;
361
+ const result = await super.FetchChanges(ctx);
362
+ const isFinal = !result.HasMore;
363
+ const newWatermark = isFinal
364
+ ? (this.ExtractLatestUpdatedAt(result.Records) ?? ctx.WatermarkValue ?? undefined)
365
+ : undefined;
366
+ return { ...result, NewWatermarkValue: newWatermark };
367
+ }
368
+ // ─── Config parsing ──────────────────────────────────────────────
369
+ /**
370
+ * Parses the OAuth2 connection config, preferring the attached MJ Credential over the raw
371
+ * Configuration JSON. Credential bytes are resolved at runtime — never at build.
372
+ */
373
+ async ParseConfig(companyIntegration, contextUser) {
374
+ if (companyIntegration.CredentialID) {
375
+ return this.ParseConfigFromCredential(companyIntegration.CredentialID, contextUser);
376
+ }
377
+ if (companyIntegration.Configuration) {
378
+ return this.ValidateConfig(JSON.parse(companyIntegration.Configuration));
379
+ }
380
+ throw new Error('Hivebrite connector requires either CredentialID or Configuration JSON');
381
+ }
382
+ /** Loads the OAuth2 config from the MJ: Credentials entity Values JSON. */
383
+ async ParseConfigFromCredential(credentialID, contextUser, provider) {
384
+ const md = provider ?? new Metadata();
385
+ const cred = await md.GetEntityObject('MJ: Credentials', contextUser);
386
+ const loaded = await cred.Load(credentialID);
387
+ if (!loaded || !cred.Values) {
388
+ throw new Error('Hivebrite credential could not be loaded or has no Values JSON');
389
+ }
390
+ return this.ValidateConfig(JSON.parse(cred.Values));
391
+ }
392
+ /** Validates the parsed config + applies defaults. Field names are case-insensitive. */
393
+ ValidateConfig(raw) {
394
+ if (!raw || typeof raw !== 'object') {
395
+ throw new Error('Hivebrite configuration is not a valid object');
396
+ }
397
+ const obj = raw;
398
+ const getStr = (...keys) => {
399
+ for (const key of keys) {
400
+ const lower = key.toLowerCase();
401
+ for (const [k, v] of Object.entries(obj)) {
402
+ if (k.toLowerCase() === lower && typeof v === 'string' && v.length > 0)
403
+ return v;
404
+ }
405
+ }
406
+ return undefined;
407
+ };
408
+ const getNum = (...keys) => {
409
+ for (const key of keys) {
410
+ const lower = key.toLowerCase();
411
+ for (const [k, v] of Object.entries(obj)) {
412
+ if (k.toLowerCase() === lower && typeof v === 'number')
413
+ return v;
414
+ }
415
+ }
416
+ return undefined;
417
+ };
418
+ const baseURL = getStr('baseurl', 'base_url', 'communityurl', 'community_url');
419
+ if (!baseURL) {
420
+ throw new Error('Hivebrite configuration missing required field: BaseURL');
421
+ }
422
+ const clientId = getStr('clientid', 'client_id');
423
+ const clientSecret = getStr('clientsecret', 'client_secret');
424
+ if (!clientId || !clientSecret) {
425
+ throw new Error('Hivebrite OAuth2 configuration missing required field: ClientId / ClientSecret');
426
+ }
427
+ const refreshToken = getStr('refreshtoken', 'refresh_token');
428
+ const adminEmail = getStr('adminemail', 'admin_email', 'username', 'email');
429
+ const password = getStr('password', 'pass');
430
+ if (!refreshToken && !(adminEmail && password)) {
431
+ throw new Error('Hivebrite OAuth2 configuration requires a RefreshToken (primary grant) ' +
432
+ 'or AdminEmail + Password (fallback grant)');
433
+ }
434
+ return {
435
+ ClientId: clientId,
436
+ ClientSecret: clientSecret,
437
+ RefreshToken: refreshToken,
438
+ AdminEmail: adminEmail,
439
+ Password: password,
440
+ Scope: getStr('scope', 'scopes'),
441
+ BaseURL: baseURL,
442
+ TokenURL: getStr('tokenurl', 'token_url'),
443
+ MaxRetries: getNum('maxretries') ?? DEFAULT_MAX_RETRIES,
444
+ RequestTimeoutMs: getNum('requesttimeoutms') ?? DEFAULT_REQUEST_TIMEOUT_MS,
445
+ };
446
+ }
447
+ /** Resolves the API base URL from the credential's BaseURL (never a hardcoded host). Strips a trailing /api. */
448
+ ResolveBaseUrl(config) {
449
+ return config.BaseURL.replace(/\/+$/, '').replace(/\/api$/i, '');
450
+ }
451
+ /** Resolves the OAuth2 token endpoint: credential TokenURL override, else `{base}/api/oauth/token`. */
452
+ ResolveTokenURL(config, baseUrl) {
453
+ if (config.TokenURL && config.TokenURL.length > 0)
454
+ return config.TokenURL;
455
+ return `${baseUrl}${DEFAULT_TOKEN_PATH}`;
456
+ }
457
+ // ─── Normalization helpers ───────────────────────────────────────
458
+ /** Normalizes a raw record's top-level values (empty-string → null). */
459
+ NormalizeRecord(record) {
460
+ const out = {};
461
+ for (const [key, value] of Object.entries(record)) {
462
+ out[key] = value === '' ? null : value;
463
+ }
464
+ return out;
465
+ }
466
+ /** Extracts the latest updated_at / created_at across a batch for watermark advancement. */
467
+ ExtractLatestUpdatedAt(records) {
468
+ let latest = null;
469
+ for (const rec of records) {
470
+ const raw = rec.Fields?.updated_at ?? rec.Fields?.created_at ?? rec.Fields?.deleted_at;
471
+ if (typeof raw !== 'string' || raw.length === 0)
472
+ continue;
473
+ const d = new Date(raw);
474
+ if (!Number.isNaN(d.getTime()) && (latest === null || d > latest))
475
+ latest = d;
476
+ }
477
+ return latest ? latest.toISOString() : null;
478
+ }
479
+ // ─── HTTP helpers ────────────────────────────────────────────────
480
+ /** Parses a Retry-After header (seconds or http-date) into ms, if present. */
481
+ RetryAfterMs(response) {
482
+ const header = response.headers.get('retry-after');
483
+ if (!header)
484
+ return undefined;
485
+ const asSeconds = Number(header);
486
+ if (!Number.isNaN(asSeconds))
487
+ return Math.max(0, asSeconds * 1_000);
488
+ const asDate = new Date(header).getTime();
489
+ if (!Number.isNaN(asDate))
490
+ return Math.max(0, asDate - Date.now());
491
+ return undefined;
492
+ }
493
+ /** Exponential backoff delay for retry attempts (capped at 30s). */
494
+ BackoffDelay(attempt) {
495
+ return Math.min(2_000 * Math.pow(2, attempt), 30_000);
496
+ }
497
+ /** Checks whether an error is transient (network/timeout). */
498
+ IsTransientNetworkError(err) {
499
+ if (!(err instanceof Error))
500
+ return false;
501
+ const msg = err.message.toLowerCase();
502
+ return msg.includes('timeout') || msg.includes('abort') ||
503
+ msg.includes('econnreset') || msg.includes('econnrefused') ||
504
+ msg.includes('fetch failed');
505
+ }
506
+ /** Builds the normalized RESTResponse from a fetch Response. */
507
+ async BuildRESTResponse(response) {
508
+ const headers = {};
509
+ response.headers.forEach((v, k) => { headers[k.toLowerCase()] = v; });
510
+ const text = await response.text();
511
+ let body = null;
512
+ if (text.length > 0) {
513
+ try {
514
+ body = JSON.parse(text);
515
+ }
516
+ catch {
517
+ body = text;
518
+ }
519
+ }
520
+ return { Status: response.status, Body: body, Headers: headers };
521
+ }
522
+ /** Promise-wrapped setTimeout. */
523
+ Sleep(ms) {
524
+ return new Promise(resolve => setTimeout(resolve, ms));
525
+ }
526
+ };
527
+ HivebriteConnector = __decorate([
528
+ RegisterClass(BaseIntegrationConnector, '@memberjunction/connector-hivebrite')
529
+ ], HivebriteConnector);
530
+ export { HivebriteConnector };
531
+ /** Tree-shaking prevention — import and call from the package entry point. */
532
+ export function LoadHivebriteConnector() { }
533
+ //# sourceMappingURL=HivebriteConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HivebriteConnector.js","sourceRoot":"","sources":["../src/HivebriteConnector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './HivebriteConnector.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 './HivebriteConnector.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,40 @@
1
+ {
2
+ "name": "@memberjunction/connector-hivebrite",
3
+ "version": "1.0.0",
4
+ "description": "MemberJunction Hivebrite 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
+ "devDependencies": {
26
+ "@types/node": "24.10.11",
27
+ "tsc-alias": "^1.8.16",
28
+ "typescript": "^5.9.3",
29
+ "vitest": "^4.0.18",
30
+ "@memberjunction/core": "^5.42.0",
31
+ "@memberjunction/core-entities": "^5.42.0",
32
+ "@memberjunction/global": "^5.42.0",
33
+ "@memberjunction/integration-engine": "^5.42.0",
34
+ "@memberjunction/integration-engine-base": "^5.42.0"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/MemberJunction/Integrations"
39
+ }
40
+ }