@sailpoint/connector-sdk 1.1.41 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/cache.d.ts +90 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +152 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/data-store.d.ts +102 -0
- package/dist/lib/data-store.d.ts.map +1 -0
- package/dist/lib/data-store.js +178 -0
- package/dist/lib/data-store.js.map +1 -0
- package/dist/lib/http-client.d.ts +195 -0
- package/dist/lib/http-client.d.ts.map +1 -0
- package/dist/lib/http-client.js +312 -0
- package/dist/lib/http-client.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key prefix reserved for internal SDK use. User keys must not start with this prefix.
|
|
3
|
+
*/
|
|
4
|
+
export declare const SDK_CACHE_PREFIX = "__sdk:";
|
|
5
|
+
/**
|
|
6
|
+
* A general-purpose in-memory cache with TTL support.
|
|
7
|
+
*
|
|
8
|
+
* Because connectors run in a Lambda-like environment where module-level state persists
|
|
9
|
+
* across warm invocations, values stored in the cache remain available between requests
|
|
10
|
+
* as long as the container stays warm.
|
|
11
|
+
*
|
|
12
|
+
* The SDK uses this cache internally for auth token storage (with reserved keys prefixed
|
|
13
|
+
* by `__sdk:`). Connector developers can use it to cache any data that is expensive to
|
|
14
|
+
* fetch on every invocation.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { connectorCache } from '@sailpoint/connector-sdk'
|
|
19
|
+
*
|
|
20
|
+
* // Cache an API response for 5 minutes using fetch()
|
|
21
|
+
* const users = await connectorCache.fetch('all-users', () => myClient.getUsers(), 300)
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class ConnectorCache {
|
|
25
|
+
private readonly store;
|
|
26
|
+
private readonly inflight;
|
|
27
|
+
/**
|
|
28
|
+
* Get a value from the cache. Returns `undefined` if the key does not exist or has expired.
|
|
29
|
+
* @param key Cache key
|
|
30
|
+
*/
|
|
31
|
+
get<T = any>(key: string): T | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Store a value in the cache.
|
|
34
|
+
* @param key Cache key (must not start with `__sdk:` — that prefix is reserved for internal use)
|
|
35
|
+
* @param value Value to cache
|
|
36
|
+
* @param ttlSeconds Time-to-live in seconds. If omitted, the entry never expires.
|
|
37
|
+
*/
|
|
38
|
+
set<T = any>(key: string, value: T, ttlSeconds?: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Check whether a key exists and has not expired.
|
|
41
|
+
* @param key Cache key
|
|
42
|
+
*/
|
|
43
|
+
has(key: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Return the cached value for `key`, or compute and store it if absent.
|
|
46
|
+
*
|
|
47
|
+
* If the key is not in the cache (or has expired), `factory` is called once to produce
|
|
48
|
+
* the value, which is then stored with the given TTL. Concurrent calls with the same key
|
|
49
|
+
* are deduplicated — only one `factory` invocation runs, and all callers receive the
|
|
50
|
+
* same result.
|
|
51
|
+
*
|
|
52
|
+
* @param key Cache key
|
|
53
|
+
* @param factory Async function that produces the value when the cache is empty
|
|
54
|
+
* @param ttlSeconds Time-to-live in seconds. If omitted, the entry never expires.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const entitlementMap = await connectorCache.fetch(
|
|
59
|
+
* 'entitlement-map',
|
|
60
|
+
* async () => {
|
|
61
|
+
* const entitlements = await client.listEntitlements()
|
|
62
|
+
* return new Map(entitlements.map(e => [e.id, e.name]))
|
|
63
|
+
* },
|
|
64
|
+
* 600,
|
|
65
|
+
* )
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
fetch<T = any>(key: string, factory: () => Promise<T>, ttlSeconds?: number): Promise<T>;
|
|
69
|
+
/**
|
|
70
|
+
* Remove a key from the cache.
|
|
71
|
+
* @param key Cache key
|
|
72
|
+
*/
|
|
73
|
+
delete(key: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Remove all entries from the cache. By default, only clears user entries and
|
|
76
|
+
* preserves internal SDK entries. Pass `true` to clear everything.
|
|
77
|
+
* @param includeInternal If true, also clears internal SDK cache entries
|
|
78
|
+
*/
|
|
79
|
+
clear(includeInternal?: boolean): void;
|
|
80
|
+
/**
|
|
81
|
+
* Get the number of entries currently in the cache (including expired but not yet evicted).
|
|
82
|
+
*/
|
|
83
|
+
get size(): number;
|
|
84
|
+
private validateUserKey;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Module-level singleton cache instance. Persists across warm invocations in Lambda-like environments.
|
|
88
|
+
*/
|
|
89
|
+
export declare const connectorCache: ConnectorCache;
|
|
90
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../lib/cache.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAOxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAE3D;;;OAGG;IACH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAYxC;;;;;OAKG;IACH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ9D;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAwB7F;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;;;OAIG;IACH,KAAK,CAAC,eAAe,GAAE,OAAe,GAAG,IAAI;IAY7C;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,eAAe;CAKvB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAA"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (c) 2021. SailPoint Technologies, Inc. All rights reserved. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.connectorCache = exports.ConnectorCache = exports.SDK_CACHE_PREFIX = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Key prefix reserved for internal SDK use. User keys must not start with this prefix.
|
|
7
|
+
*/
|
|
8
|
+
exports.SDK_CACHE_PREFIX = '__sdk:';
|
|
9
|
+
/**
|
|
10
|
+
* A general-purpose in-memory cache with TTL support.
|
|
11
|
+
*
|
|
12
|
+
* Because connectors run in a Lambda-like environment where module-level state persists
|
|
13
|
+
* across warm invocations, values stored in the cache remain available between requests
|
|
14
|
+
* as long as the container stays warm.
|
|
15
|
+
*
|
|
16
|
+
* The SDK uses this cache internally for auth token storage (with reserved keys prefixed
|
|
17
|
+
* by `__sdk:`). Connector developers can use it to cache any data that is expensive to
|
|
18
|
+
* fetch on every invocation.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { connectorCache } from '@sailpoint/connector-sdk'
|
|
23
|
+
*
|
|
24
|
+
* // Cache an API response for 5 minutes using fetch()
|
|
25
|
+
* const users = await connectorCache.fetch('all-users', () => myClient.getUsers(), 300)
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
class ConnectorCache {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.store = new Map();
|
|
31
|
+
this.inflight = new Map();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get a value from the cache. Returns `undefined` if the key does not exist or has expired.
|
|
35
|
+
* @param key Cache key
|
|
36
|
+
*/
|
|
37
|
+
get(key) {
|
|
38
|
+
const entry = this.store.get(key);
|
|
39
|
+
if (!entry) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (entry.expiresAt !== null && Date.now() >= entry.expiresAt) {
|
|
43
|
+
this.store.delete(key);
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
return entry.value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Store a value in the cache.
|
|
50
|
+
* @param key Cache key (must not start with `__sdk:` — that prefix is reserved for internal use)
|
|
51
|
+
* @param value Value to cache
|
|
52
|
+
* @param ttlSeconds Time-to-live in seconds. If omitted, the entry never expires.
|
|
53
|
+
*/
|
|
54
|
+
set(key, value, ttlSeconds) {
|
|
55
|
+
if (!key.startsWith(exports.SDK_CACHE_PREFIX)) {
|
|
56
|
+
this.validateUserKey(key);
|
|
57
|
+
}
|
|
58
|
+
const expiresAt = ttlSeconds != null ? Date.now() + ttlSeconds * 1000 : null;
|
|
59
|
+
this.store.set(key, { value, expiresAt });
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check whether a key exists and has not expired.
|
|
63
|
+
* @param key Cache key
|
|
64
|
+
*/
|
|
65
|
+
has(key) {
|
|
66
|
+
return this.get(key) !== undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Return the cached value for `key`, or compute and store it if absent.
|
|
70
|
+
*
|
|
71
|
+
* If the key is not in the cache (or has expired), `factory` is called once to produce
|
|
72
|
+
* the value, which is then stored with the given TTL. Concurrent calls with the same key
|
|
73
|
+
* are deduplicated — only one `factory` invocation runs, and all callers receive the
|
|
74
|
+
* same result.
|
|
75
|
+
*
|
|
76
|
+
* @param key Cache key
|
|
77
|
+
* @param factory Async function that produces the value when the cache is empty
|
|
78
|
+
* @param ttlSeconds Time-to-live in seconds. If omitted, the entry never expires.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const entitlementMap = await connectorCache.fetch(
|
|
83
|
+
* 'entitlement-map',
|
|
84
|
+
* async () => {
|
|
85
|
+
* const entitlements = await client.listEntitlements()
|
|
86
|
+
* return new Map(entitlements.map(e => [e.id, e.name]))
|
|
87
|
+
* },
|
|
88
|
+
* 600,
|
|
89
|
+
* )
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
async fetch(key, factory, ttlSeconds) {
|
|
93
|
+
const cached = this.get(key);
|
|
94
|
+
if (cached !== undefined) {
|
|
95
|
+
return cached;
|
|
96
|
+
}
|
|
97
|
+
const existing = this.inflight.get(key);
|
|
98
|
+
if (existing) {
|
|
99
|
+
return existing;
|
|
100
|
+
}
|
|
101
|
+
const promise = factory().then((value) => {
|
|
102
|
+
this.set(key, value, ttlSeconds);
|
|
103
|
+
this.inflight.delete(key);
|
|
104
|
+
return value;
|
|
105
|
+
}).catch((err) => {
|
|
106
|
+
this.inflight.delete(key);
|
|
107
|
+
throw err;
|
|
108
|
+
});
|
|
109
|
+
this.inflight.set(key, promise);
|
|
110
|
+
return promise;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Remove a key from the cache.
|
|
114
|
+
* @param key Cache key
|
|
115
|
+
*/
|
|
116
|
+
delete(key) {
|
|
117
|
+
return this.store.delete(key);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Remove all entries from the cache. By default, only clears user entries and
|
|
121
|
+
* preserves internal SDK entries. Pass `true` to clear everything.
|
|
122
|
+
* @param includeInternal If true, also clears internal SDK cache entries
|
|
123
|
+
*/
|
|
124
|
+
clear(includeInternal = false) {
|
|
125
|
+
if (includeInternal) {
|
|
126
|
+
this.store.clear();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for (const key of Array.from(this.store.keys())) {
|
|
130
|
+
if (!key.startsWith(exports.SDK_CACHE_PREFIX)) {
|
|
131
|
+
this.store.delete(key);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get the number of entries currently in the cache (including expired but not yet evicted).
|
|
137
|
+
*/
|
|
138
|
+
get size() {
|
|
139
|
+
return this.store.size;
|
|
140
|
+
}
|
|
141
|
+
validateUserKey(key) {
|
|
142
|
+
if (key.startsWith(exports.SDK_CACHE_PREFIX)) {
|
|
143
|
+
throw new Error(`Cache keys starting with "${exports.SDK_CACHE_PREFIX}" are reserved for internal SDK use`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.ConnectorCache = ConnectorCache;
|
|
148
|
+
/**
|
|
149
|
+
* Module-level singleton cache instance. Persists across warm invocations in Lambda-like environments.
|
|
150
|
+
*/
|
|
151
|
+
exports.connectorCache = new ConnectorCache();
|
|
152
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../lib/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Response } from './response';
|
|
2
|
+
import { Context } from './connector-handler';
|
|
3
|
+
/**
|
|
4
|
+
* A persistent key-value data store backed by source config attributes.
|
|
5
|
+
*
|
|
6
|
+
* Provides a simple API to read and write values that persist across connector invocations.
|
|
7
|
+
* Under the hood, changes are sent via `patchConfig` as JSON Patch operations targeting
|
|
8
|
+
* `/<key>` directly. Only changed values are patched — if a value is set to the same thing
|
|
9
|
+
* it was before, no patch is emitted.
|
|
10
|
+
*
|
|
11
|
+
* During long aggregations, call `reload(context)` to pick up config changes that occurred
|
|
12
|
+
* mid-run (including values written by a previous `flush()` call in the same invocation).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createConnectorDataStore, readConfig } from '@sailpoint/connector-sdk'
|
|
17
|
+
*
|
|
18
|
+
* // Inside a command handler:
|
|
19
|
+
* async (context, input, res) => {
|
|
20
|
+
* const config = await readConfig()
|
|
21
|
+
* const dataStore = createConnectorDataStore(config, res)
|
|
22
|
+
*
|
|
23
|
+
* // Read a previously stored value
|
|
24
|
+
* const lastSync = dataStore.get<string>('lastSyncTimestamp')
|
|
25
|
+
*
|
|
26
|
+
* // Fetch data since last sync...
|
|
27
|
+
* const data = await fetchDataSince(lastSync)
|
|
28
|
+
*
|
|
29
|
+
* // Store the new timestamp (only patched if different)
|
|
30
|
+
* dataStore.set('lastSyncTimestamp', new Date().toISOString())
|
|
31
|
+
*
|
|
32
|
+
* // Send all accumulated changes
|
|
33
|
+
* dataStore.flush()
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class ConnectorDataStore {
|
|
38
|
+
private config;
|
|
39
|
+
private readonly res;
|
|
40
|
+
private readonly pending;
|
|
41
|
+
constructor(config: Record<string, any>, res: Response<any>);
|
|
42
|
+
/**
|
|
43
|
+
* Get a value from the config.
|
|
44
|
+
* Returns the pending value if one has been set, otherwise the original config value.
|
|
45
|
+
* @param key Attribute key
|
|
46
|
+
*/
|
|
47
|
+
get<T = any>(key: string): T | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Set a value in the config. The change is buffered until `flush()` is called.
|
|
50
|
+
* If the value is identical to the current stored value, no patch will be emitted.
|
|
51
|
+
* @param key Attribute key
|
|
52
|
+
* @param value Value to store (must be JSON-serializable)
|
|
53
|
+
*/
|
|
54
|
+
set(key: string, value: any): void;
|
|
55
|
+
/**
|
|
56
|
+
* Remove a key from the config. The change is buffered until `flush()` is called.
|
|
57
|
+
* If the key doesn't exist, no patch will be emitted.
|
|
58
|
+
* @param key Attribute key to remove
|
|
59
|
+
*/
|
|
60
|
+
delete(key: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Returns true if there are pending changes that haven't been flushed yet.
|
|
63
|
+
*/
|
|
64
|
+
get hasPendingChanges(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Send all accumulated changes as a single `patchConfig` call.
|
|
67
|
+
* Only emits patches for values that differ from the current config.
|
|
68
|
+
* After flushing, the local config is updated to reflect the sent patches so that
|
|
69
|
+
* subsequent `set()` calls in the same invocation use the correct baseline for
|
|
70
|
+
* change detection.
|
|
71
|
+
*/
|
|
72
|
+
flush(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Reload the connector config from ISC via the command context and update the data
|
|
75
|
+
* store's baseline. Call this during long aggregations to pick up config changes that
|
|
76
|
+
* occurred mid-run — for example, values written by a previous `flush()` call or
|
|
77
|
+
* updates made externally.
|
|
78
|
+
*
|
|
79
|
+
* Pending changes are preserved across a reload.
|
|
80
|
+
*
|
|
81
|
+
* @param context The command context passed to the handler
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* // Flush a batch of changes, then reload so the next batch uses the updated baseline
|
|
86
|
+
* dataStore.set('cursor', nextCursor)
|
|
87
|
+
* dataStore.flush()
|
|
88
|
+
* await dataStore.reload(context)
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
reload(context: Context): Promise<void>;
|
|
92
|
+
private deepEqual;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates a persistent data store backed by source config attributes.
|
|
96
|
+
*
|
|
97
|
+
* @param config The connector config object (from `readConfig()`)
|
|
98
|
+
* @param res The response object from the current command handler
|
|
99
|
+
* @returns A ConnectorDataStore instance
|
|
100
|
+
*/
|
|
101
|
+
export declare function createConnectorDataStore(config: Record<string, any>, res: Response<any>): ConnectorDataStore;
|
|
102
|
+
//# sourceMappingURL=data-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../../lib/data-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2D;gBAEvE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC;IAK3D;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAQxC;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IASlC;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQzB;;OAEG;IACH,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED;;;;;;OAMG;IACH,KAAK,IAAI,IAAI;IAyCb;;;;;;;;;;;;;;;;;OAiBG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,OAAO,CAAC,SAAS;CAOjB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAE5G"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (c) 2021. SailPoint Technologies, Inc. All rights reserved. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createConnectorDataStore = exports.ConnectorDataStore = void 0;
|
|
5
|
+
const response_1 = require("./response");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
/**
|
|
8
|
+
* A persistent key-value data store backed by source config attributes.
|
|
9
|
+
*
|
|
10
|
+
* Provides a simple API to read and write values that persist across connector invocations.
|
|
11
|
+
* Under the hood, changes are sent via `patchConfig` as JSON Patch operations targeting
|
|
12
|
+
* `/<key>` directly. Only changed values are patched — if a value is set to the same thing
|
|
13
|
+
* it was before, no patch is emitted.
|
|
14
|
+
*
|
|
15
|
+
* During long aggregations, call `reload(context)` to pick up config changes that occurred
|
|
16
|
+
* mid-run (including values written by a previous `flush()` call in the same invocation).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { createConnectorDataStore, readConfig } from '@sailpoint/connector-sdk'
|
|
21
|
+
*
|
|
22
|
+
* // Inside a command handler:
|
|
23
|
+
* async (context, input, res) => {
|
|
24
|
+
* const config = await readConfig()
|
|
25
|
+
* const dataStore = createConnectorDataStore(config, res)
|
|
26
|
+
*
|
|
27
|
+
* // Read a previously stored value
|
|
28
|
+
* const lastSync = dataStore.get<string>('lastSyncTimestamp')
|
|
29
|
+
*
|
|
30
|
+
* // Fetch data since last sync...
|
|
31
|
+
* const data = await fetchDataSince(lastSync)
|
|
32
|
+
*
|
|
33
|
+
* // Store the new timestamp (only patched if different)
|
|
34
|
+
* dataStore.set('lastSyncTimestamp', new Date().toISOString())
|
|
35
|
+
*
|
|
36
|
+
* // Send all accumulated changes
|
|
37
|
+
* dataStore.flush()
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
class ConnectorDataStore {
|
|
42
|
+
constructor(config, res) {
|
|
43
|
+
this.pending = new Map();
|
|
44
|
+
this.config = config;
|
|
45
|
+
this.res = res;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get a value from the config.
|
|
49
|
+
* Returns the pending value if one has been set, otherwise the original config value.
|
|
50
|
+
* @param key Attribute key
|
|
51
|
+
*/
|
|
52
|
+
get(key) {
|
|
53
|
+
const pendingEntry = this.pending.get(key);
|
|
54
|
+
if (pendingEntry) {
|
|
55
|
+
return pendingEntry.op === 'delete' ? undefined : pendingEntry.value;
|
|
56
|
+
}
|
|
57
|
+
return this.config?.[key];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Set a value in the config. The change is buffered until `flush()` is called.
|
|
61
|
+
* If the value is identical to the current stored value, no patch will be emitted.
|
|
62
|
+
* @param key Attribute key
|
|
63
|
+
* @param value Value to store (must be JSON-serializable)
|
|
64
|
+
*/
|
|
65
|
+
set(key, value) {
|
|
66
|
+
const current = this.config?.[key];
|
|
67
|
+
if (this.deepEqual(current, value)) {
|
|
68
|
+
this.pending.delete(key);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.pending.set(key, { op: 'set', value });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Remove a key from the config. The change is buffered until `flush()` is called.
|
|
75
|
+
* If the key doesn't exist, no patch will be emitted.
|
|
76
|
+
* @param key Attribute key to remove
|
|
77
|
+
*/
|
|
78
|
+
delete(key) {
|
|
79
|
+
const exists = this.config?.hasOwnProperty(key);
|
|
80
|
+
if (!exists && !this.pending.has(key)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.pending.set(key, { op: 'delete' });
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Returns true if there are pending changes that haven't been flushed yet.
|
|
87
|
+
*/
|
|
88
|
+
get hasPendingChanges() {
|
|
89
|
+
return this.pending.size > 0;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Send all accumulated changes as a single `patchConfig` call.
|
|
93
|
+
* Only emits patches for values that differ from the current config.
|
|
94
|
+
* After flushing, the local config is updated to reflect the sent patches so that
|
|
95
|
+
* subsequent `set()` calls in the same invocation use the correct baseline for
|
|
96
|
+
* change detection.
|
|
97
|
+
*/
|
|
98
|
+
flush() {
|
|
99
|
+
if (this.pending.size === 0) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const log = logger_1.logger.child({ component: 'data-store' });
|
|
103
|
+
log.debug({ config: this.config ?? null }, 'data-store flush: config baseline');
|
|
104
|
+
const patches = [];
|
|
105
|
+
for (const [key, entry] of this.pending) {
|
|
106
|
+
if (entry.op === 'delete') {
|
|
107
|
+
patches.push({ op: response_1.PatchOp.Remove, path: `/${key}` });
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const existed = this.config?.hasOwnProperty(key);
|
|
111
|
+
patches.push({
|
|
112
|
+
op: existed ? response_1.PatchOp.Replace : response_1.PatchOp.Add,
|
|
113
|
+
path: `/${key}`,
|
|
114
|
+
value: entry.value,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
log.debug({ patches }, 'data-store flush: sending patches');
|
|
119
|
+
if (patches.length > 0) {
|
|
120
|
+
this.res.patchConfig(patches);
|
|
121
|
+
}
|
|
122
|
+
// Update the local config baseline so subsequent set() calls detect no change
|
|
123
|
+
for (const [key, entry] of this.pending) {
|
|
124
|
+
if (entry.op === 'delete') {
|
|
125
|
+
delete this.config[key];
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.config[key] = entry.value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
this.pending.clear();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Reload the connector config from ISC via the command context and update the data
|
|
135
|
+
* store's baseline. Call this during long aggregations to pick up config changes that
|
|
136
|
+
* occurred mid-run — for example, values written by a previous `flush()` call or
|
|
137
|
+
* updates made externally.
|
|
138
|
+
*
|
|
139
|
+
* Pending changes are preserved across a reload.
|
|
140
|
+
*
|
|
141
|
+
* @param context The command context passed to the handler
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* // Flush a batch of changes, then reload so the next batch uses the updated baseline
|
|
146
|
+
* dataStore.set('cursor', nextCursor)
|
|
147
|
+
* dataStore.flush()
|
|
148
|
+
* await dataStore.reload(context)
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
async reload(context) {
|
|
152
|
+
this.config = await context.reloadConfig();
|
|
153
|
+
}
|
|
154
|
+
deepEqual(a, b) {
|
|
155
|
+
if (a === b)
|
|
156
|
+
return true;
|
|
157
|
+
if (a == null || b == null)
|
|
158
|
+
return false;
|
|
159
|
+
if (typeof a !== typeof b)
|
|
160
|
+
return false;
|
|
161
|
+
if (typeof a !== 'object')
|
|
162
|
+
return false;
|
|
163
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.ConnectorDataStore = ConnectorDataStore;
|
|
167
|
+
/**
|
|
168
|
+
* Creates a persistent data store backed by source config attributes.
|
|
169
|
+
*
|
|
170
|
+
* @param config The connector config object (from `readConfig()`)
|
|
171
|
+
* @param res The response object from the current command handler
|
|
172
|
+
* @returns A ConnectorDataStore instance
|
|
173
|
+
*/
|
|
174
|
+
function createConnectorDataStore(config, res) {
|
|
175
|
+
return new ConnectorDataStore(config, res);
|
|
176
|
+
}
|
|
177
|
+
exports.createConnectorDataStore = createConnectorDataStore;
|
|
178
|
+
//# sourceMappingURL=data-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-store.js","sourceRoot":"","sources":["../../lib/data-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { AxiosInstance, CreateAxiosDefaults } from 'axios';
|
|
2
|
+
export type { AxiosInstance } from 'axios';
|
|
3
|
+
/**
|
|
4
|
+
* Basic authentication using username and password
|
|
5
|
+
*/
|
|
6
|
+
export interface BasicAuth {
|
|
7
|
+
type: 'basic';
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Bearer token authentication using a static token
|
|
13
|
+
*/
|
|
14
|
+
export interface BearerTokenAuth {
|
|
15
|
+
type: 'bearer';
|
|
16
|
+
token: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* API key authentication sent as a header or query parameter
|
|
20
|
+
*/
|
|
21
|
+
export interface ApiKeyAuth {
|
|
22
|
+
type: 'apiKey';
|
|
23
|
+
/**
|
|
24
|
+
* Where to send the API key: 'header' or 'query'
|
|
25
|
+
*/
|
|
26
|
+
in: 'header' | 'query';
|
|
27
|
+
/**
|
|
28
|
+
* Name of the header or query parameter (e.g. 'X-API-Key', 'api_key')
|
|
29
|
+
*/
|
|
30
|
+
name: string;
|
|
31
|
+
value: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* OAuth2 Client Credentials grant. Automatically fetches and refreshes access tokens.
|
|
35
|
+
*/
|
|
36
|
+
export interface OAuth2ClientCredentialsAuth {
|
|
37
|
+
type: 'oauth2ClientCredentials';
|
|
38
|
+
/**
|
|
39
|
+
* Token endpoint URL (e.g. 'https://auth.example.com/oauth/token')
|
|
40
|
+
*/
|
|
41
|
+
tokenUrl: string;
|
|
42
|
+
clientId: string;
|
|
43
|
+
clientSecret: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional scopes to request
|
|
46
|
+
*/
|
|
47
|
+
scope?: string;
|
|
48
|
+
/**
|
|
49
|
+
* How to send credentials: 'body' (form post) or 'header' (Basic auth header).
|
|
50
|
+
* Defaults to 'body'.
|
|
51
|
+
*/
|
|
52
|
+
credentialPlacement?: 'body' | 'header';
|
|
53
|
+
}
|
|
54
|
+
export type AuthConfig = BasicAuth | BearerTokenAuth | ApiKeyAuth | OAuth2ClientCredentialsAuth;
|
|
55
|
+
/**
|
|
56
|
+
* Configuration for automatic request retry with exponential backoff.
|
|
57
|
+
*/
|
|
58
|
+
export interface RetryConfig {
|
|
59
|
+
/**
|
|
60
|
+
* Maximum number of retry attempts. Set to 0 to disable retries.
|
|
61
|
+
* Default: 3
|
|
62
|
+
*/
|
|
63
|
+
maxRetries?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Base delay in milliseconds for exponential backoff. The actual delay is
|
|
66
|
+
* `baseDelay * 2^(attempt - 1)` plus jitter.
|
|
67
|
+
* Default: 1000
|
|
68
|
+
*/
|
|
69
|
+
baseDelay?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Maximum delay in milliseconds between retries.
|
|
72
|
+
* Default: 30000
|
|
73
|
+
*/
|
|
74
|
+
maxDelay?: number;
|
|
75
|
+
/**
|
|
76
|
+
* HTTP status codes that should trigger a retry.
|
|
77
|
+
* Default: [429, 500, 502, 503, 504]
|
|
78
|
+
*/
|
|
79
|
+
retryableStatusCodes?: number[];
|
|
80
|
+
/**
|
|
81
|
+
* Whether to retry on network errors (no response received).
|
|
82
|
+
* Default: true
|
|
83
|
+
*/
|
|
84
|
+
retryOnNetworkError?: boolean;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Options for creating a connector HTTP client
|
|
88
|
+
*/
|
|
89
|
+
export interface HttpClientOptions {
|
|
90
|
+
/**
|
|
91
|
+
* Base URL for all requests (e.g. 'https://api.example.com/v1')
|
|
92
|
+
*/
|
|
93
|
+
baseURL?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Default headers to include on every request
|
|
96
|
+
*/
|
|
97
|
+
headers?: Record<string, string>;
|
|
98
|
+
/**
|
|
99
|
+
* Request timeout in milliseconds (default: 30000)
|
|
100
|
+
*/
|
|
101
|
+
timeout?: number;
|
|
102
|
+
/**
|
|
103
|
+
* Authentication configuration. Supports basic, bearer, apiKey, and oauth2ClientCredentials.
|
|
104
|
+
*/
|
|
105
|
+
auth?: AuthConfig;
|
|
106
|
+
/**
|
|
107
|
+
* Retry configuration. Enabled by default with 3 retries and exponential backoff.
|
|
108
|
+
* Set to `false` to disable retries entirely.
|
|
109
|
+
*/
|
|
110
|
+
retry?: RetryConfig | false;
|
|
111
|
+
/**
|
|
112
|
+
* Additional Axios configuration options
|
|
113
|
+
*/
|
|
114
|
+
axiosOptions?: CreateAxiosDefaults;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parses the Retry-After header value into milliseconds to wait.
|
|
118
|
+
* Supports both seconds (integer) and HTTP-date formats.
|
|
119
|
+
* Returns undefined if the header is missing or unparseable.
|
|
120
|
+
*/
|
|
121
|
+
export declare function parseRetryAfter(headerValue: string | undefined | null): number | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Calculates the delay for a retry attempt using exponential backoff with jitter.
|
|
124
|
+
*/
|
|
125
|
+
export declare function calculateRetryDelay(attempt: number, baseDelay: number, maxDelay: number): number;
|
|
126
|
+
/**
|
|
127
|
+
* Creates a pre-configured Axios HTTP client instance for use within connectors.
|
|
128
|
+
*
|
|
129
|
+
* The client includes:
|
|
130
|
+
* - Configurable base URL, headers, and timeout
|
|
131
|
+
* - Built-in authentication (basic, bearer, apiKey, oauth2ClientCredentials)
|
|
132
|
+
* - Automatic retry with exponential backoff (429, 5xx, network errors)
|
|
133
|
+
* - Token caching via the shared `connectorCache` (persists across warm invocations)
|
|
134
|
+
* - Request/response logging via the SDK's pino logger
|
|
135
|
+
* - Error logging for failed requests
|
|
136
|
+
*
|
|
137
|
+
* @example Basic auth
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const httpClient = createConnectorHttpClient({
|
|
140
|
+
* baseURL: config.apiUrl,
|
|
141
|
+
* auth: { type: 'basic', username: config.username, password: config.password },
|
|
142
|
+
* })
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example Bearer token
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const httpClient = createConnectorHttpClient({
|
|
148
|
+
* baseURL: config.apiUrl,
|
|
149
|
+
* auth: { type: 'bearer', token: config.token },
|
|
150
|
+
* })
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @example API key
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const httpClient = createConnectorHttpClient({
|
|
156
|
+
* baseURL: config.apiUrl,
|
|
157
|
+
* auth: { type: 'apiKey', in: 'header', name: 'X-API-Key', value: config.apiKey },
|
|
158
|
+
* })
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @example OAuth2 Client Credentials (automatic token management)
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const httpClient = createConnectorHttpClient({
|
|
164
|
+
* baseURL: config.apiUrl,
|
|
165
|
+
* auth: {
|
|
166
|
+
* type: 'oauth2ClientCredentials',
|
|
167
|
+
* tokenUrl: config.tokenUrl,
|
|
168
|
+
* clientId: config.clientId,
|
|
169
|
+
* clientSecret: config.clientSecret,
|
|
170
|
+
* scope: 'read write',
|
|
171
|
+
* },
|
|
172
|
+
* })
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @example Custom retry configuration
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const httpClient = createConnectorHttpClient({
|
|
178
|
+
* baseURL: config.apiUrl,
|
|
179
|
+
* retry: { maxRetries: 5, baseDelay: 2000 },
|
|
180
|
+
* })
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @example Disable retries
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const httpClient = createConnectorHttpClient({
|
|
186
|
+
* baseURL: config.apiUrl,
|
|
187
|
+
* retry: false,
|
|
188
|
+
* })
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @param options Configuration options for the HTTP client
|
|
192
|
+
* @returns A configured Axios instance
|
|
193
|
+
*/
|
|
194
|
+
export declare function createConnectorHttpClient(options?: HttpClientOptions): AxiosInstance;
|
|
195
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../lib/http-client.ts"],"names":[],"mappings":"AAEA,OAAc,EAAc,aAAa,EAAE,mBAAmB,EAA8B,MAAM,OAAO,CAAA;AAIzG,YAAY,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAW1C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,QAAQ,CAAA;IACd;;OAEG;IACH,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,IAAI,EAAE,yBAAyB,CAAA;IAC/B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CACvC;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,eAAe,GAAG,UAAU,GAAG,2BAA2B,CAAA;AAE/F;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE/B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,UAAU,CAAA;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,KAAK,CAAA;IAE3B;;OAEG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAA;CAClC;AAoFD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAmB1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIhG;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,iBAAsB,GAAG,aAAa,CA6JxF"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (c) 2021. SailPoint Technologies, Inc. All rights reserved. */
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.createConnectorHttpClient = exports.calculateRetryDelay = exports.parseRetryAfter = void 0;
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const cache_1 = require("./cache");
|
|
11
|
+
/** Cache key prefix for auth tokens */
|
|
12
|
+
const AUTH_CACHE_PREFIX = `${cache_1.SDK_CACHE_PREFIX}auth:`;
|
|
13
|
+
/** Custom config property to track retry count */
|
|
14
|
+
const RETRY_COUNT_KEY = '__retryCount';
|
|
15
|
+
/** Default status codes that trigger a retry */
|
|
16
|
+
const DEFAULT_RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504];
|
|
17
|
+
/**
|
|
18
|
+
* Builds a deterministic cache key from the auth config so that the same credentials
|
|
19
|
+
* always resolve to the same cached token, even across multiple `createConnectorHttpClient` calls.
|
|
20
|
+
*/
|
|
21
|
+
function authCacheKey(auth) {
|
|
22
|
+
switch (auth.type) {
|
|
23
|
+
case 'oauth2ClientCredentials':
|
|
24
|
+
return `${AUTH_CACHE_PREFIX}oauth2:${auth.tokenUrl}:${auth.clientId}`;
|
|
25
|
+
default:
|
|
26
|
+
return `${AUTH_CACHE_PREFIX}${auth.type}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Tracks in-flight token fetches to deduplicate concurrent requests
|
|
30
|
+
const inflightTokenRequests = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* Fetches an OAuth2 Client Credentials token, using the shared cache and deduplicating
|
|
33
|
+
* concurrent requests.
|
|
34
|
+
*/
|
|
35
|
+
async function getOAuth2Token(config, cacheKey, log) {
|
|
36
|
+
// Check the shared cache first
|
|
37
|
+
const cached = cache_1.connectorCache.get(cacheKey);
|
|
38
|
+
if (cached) {
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
// Deduplicate concurrent token requests
|
|
42
|
+
const inflight = inflightTokenRequests.get(cacheKey);
|
|
43
|
+
if (inflight) {
|
|
44
|
+
return inflight;
|
|
45
|
+
}
|
|
46
|
+
const promise = fetchOAuth2Token(config, cacheKey, log);
|
|
47
|
+
inflightTokenRequests.set(cacheKey, promise);
|
|
48
|
+
try {
|
|
49
|
+
return await promise;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
inflightTokenRequests.delete(cacheKey);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function fetchOAuth2Token(config, cacheKey, log) {
|
|
56
|
+
log.debug({ tokenUrl: config.tokenUrl }, 'Fetching OAuth2 access token');
|
|
57
|
+
const params = new URLSearchParams();
|
|
58
|
+
params.append('grant_type', 'client_credentials');
|
|
59
|
+
if (config.scope) {
|
|
60
|
+
params.append('scope', config.scope);
|
|
61
|
+
}
|
|
62
|
+
const headers = {
|
|
63
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
64
|
+
};
|
|
65
|
+
if (config.credentialPlacement === 'header') {
|
|
66
|
+
const encoded = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64');
|
|
67
|
+
headers['Authorization'] = `Basic ${encoded}`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
params.append('client_id', config.clientId);
|
|
71
|
+
params.append('client_secret', config.clientSecret);
|
|
72
|
+
}
|
|
73
|
+
const response = await axios_1.default.post(config.tokenUrl, params.toString(), { headers });
|
|
74
|
+
const { access_token, expires_in } = response.data;
|
|
75
|
+
// Cache with TTL. Use a 30s buffer so the token is refreshed before it actually expires.
|
|
76
|
+
const ttlSeconds = Math.max((expires_in || 3600) - 30, 0);
|
|
77
|
+
cache_1.connectorCache.set(cacheKey, access_token, ttlSeconds);
|
|
78
|
+
log.debug({ expiresIn: expires_in }, 'OAuth2 access token acquired');
|
|
79
|
+
return access_token;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Parses the Retry-After header value into milliseconds to wait.
|
|
83
|
+
* Supports both seconds (integer) and HTTP-date formats.
|
|
84
|
+
* Returns undefined if the header is missing or unparseable.
|
|
85
|
+
*/
|
|
86
|
+
function parseRetryAfter(headerValue) {
|
|
87
|
+
if (!headerValue) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
// Try parsing as integer seconds
|
|
91
|
+
const seconds = Number(headerValue);
|
|
92
|
+
if (!isNaN(seconds) && seconds >= 0) {
|
|
93
|
+
return seconds * 1000;
|
|
94
|
+
}
|
|
95
|
+
// Try parsing as HTTP-date
|
|
96
|
+
const date = new Date(headerValue);
|
|
97
|
+
if (!isNaN(date.getTime())) {
|
|
98
|
+
const delay = date.getTime() - Date.now();
|
|
99
|
+
return Math.max(delay, 0);
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
104
|
+
/**
|
|
105
|
+
* Calculates the delay for a retry attempt using exponential backoff with jitter.
|
|
106
|
+
*/
|
|
107
|
+
function calculateRetryDelay(attempt, baseDelay, maxDelay) {
|
|
108
|
+
const exponentialDelay = baseDelay * Math.pow(2, attempt - 1);
|
|
109
|
+
const jitter = Math.random() * baseDelay * 0.5;
|
|
110
|
+
return Math.min(exponentialDelay + jitter, maxDelay);
|
|
111
|
+
}
|
|
112
|
+
exports.calculateRetryDelay = calculateRetryDelay;
|
|
113
|
+
function sleep(ms) {
|
|
114
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Creates a pre-configured Axios HTTP client instance for use within connectors.
|
|
118
|
+
*
|
|
119
|
+
* The client includes:
|
|
120
|
+
* - Configurable base URL, headers, and timeout
|
|
121
|
+
* - Built-in authentication (basic, bearer, apiKey, oauth2ClientCredentials)
|
|
122
|
+
* - Automatic retry with exponential backoff (429, 5xx, network errors)
|
|
123
|
+
* - Token caching via the shared `connectorCache` (persists across warm invocations)
|
|
124
|
+
* - Request/response logging via the SDK's pino logger
|
|
125
|
+
* - Error logging for failed requests
|
|
126
|
+
*
|
|
127
|
+
* @example Basic auth
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const httpClient = createConnectorHttpClient({
|
|
130
|
+
* baseURL: config.apiUrl,
|
|
131
|
+
* auth: { type: 'basic', username: config.username, password: config.password },
|
|
132
|
+
* })
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @example Bearer token
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const httpClient = createConnectorHttpClient({
|
|
138
|
+
* baseURL: config.apiUrl,
|
|
139
|
+
* auth: { type: 'bearer', token: config.token },
|
|
140
|
+
* })
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* @example API key
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const httpClient = createConnectorHttpClient({
|
|
146
|
+
* baseURL: config.apiUrl,
|
|
147
|
+
* auth: { type: 'apiKey', in: 'header', name: 'X-API-Key', value: config.apiKey },
|
|
148
|
+
* })
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @example OAuth2 Client Credentials (automatic token management)
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const httpClient = createConnectorHttpClient({
|
|
154
|
+
* baseURL: config.apiUrl,
|
|
155
|
+
* auth: {
|
|
156
|
+
* type: 'oauth2ClientCredentials',
|
|
157
|
+
* tokenUrl: config.tokenUrl,
|
|
158
|
+
* clientId: config.clientId,
|
|
159
|
+
* clientSecret: config.clientSecret,
|
|
160
|
+
* scope: 'read write',
|
|
161
|
+
* },
|
|
162
|
+
* })
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @example Custom retry configuration
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const httpClient = createConnectorHttpClient({
|
|
168
|
+
* baseURL: config.apiUrl,
|
|
169
|
+
* retry: { maxRetries: 5, baseDelay: 2000 },
|
|
170
|
+
* })
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* @example Disable retries
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const httpClient = createConnectorHttpClient({
|
|
176
|
+
* baseURL: config.apiUrl,
|
|
177
|
+
* retry: false,
|
|
178
|
+
* })
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @param options Configuration options for the HTTP client
|
|
182
|
+
* @returns A configured Axios instance
|
|
183
|
+
*/
|
|
184
|
+
function createConnectorHttpClient(options = {}) {
|
|
185
|
+
const { baseURL, headers, timeout = 30000, auth, retry, axiosOptions = {} } = options;
|
|
186
|
+
const client = axios_1.default.create({
|
|
187
|
+
...axiosOptions,
|
|
188
|
+
baseURL,
|
|
189
|
+
timeout,
|
|
190
|
+
headers: {
|
|
191
|
+
...axiosOptions.headers,
|
|
192
|
+
...headers,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
const log = logger_1.logger.child({ component: 'http-client' });
|
|
196
|
+
// Set up authentication interceptor
|
|
197
|
+
if (auth) {
|
|
198
|
+
switch (auth.type) {
|
|
199
|
+
case 'basic': {
|
|
200
|
+
const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString('base64');
|
|
201
|
+
client.interceptors.request.use((config) => {
|
|
202
|
+
config.headers.set('Authorization', `Basic ${encoded}`);
|
|
203
|
+
return config;
|
|
204
|
+
});
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case 'bearer': {
|
|
208
|
+
client.interceptors.request.use((config) => {
|
|
209
|
+
config.headers.set('Authorization', `Bearer ${auth.token}`);
|
|
210
|
+
return config;
|
|
211
|
+
});
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case 'apiKey': {
|
|
215
|
+
client.interceptors.request.use((config) => {
|
|
216
|
+
if (auth.in === 'header') {
|
|
217
|
+
config.headers.set(auth.name, auth.value);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
config.params = { ...config.params, [auth.name]: auth.value };
|
|
221
|
+
}
|
|
222
|
+
return config;
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case 'oauth2ClientCredentials': {
|
|
227
|
+
const cacheKey = authCacheKey(auth);
|
|
228
|
+
client.interceptors.request.use(async (config) => {
|
|
229
|
+
const token = await getOAuth2Token(auth, cacheKey, log);
|
|
230
|
+
config.headers.set('Authorization', `Bearer ${token}`);
|
|
231
|
+
return config;
|
|
232
|
+
});
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Logging interceptors
|
|
238
|
+
client.interceptors.request.use((config) => {
|
|
239
|
+
log.debug({ method: config.method?.toUpperCase(), url: config.url, baseURL: config.baseURL }, 'HTTP request');
|
|
240
|
+
return config;
|
|
241
|
+
}, (error) => {
|
|
242
|
+
log.error({ error: error.message }, 'HTTP request error');
|
|
243
|
+
return Promise.reject(error);
|
|
244
|
+
});
|
|
245
|
+
client.interceptors.response.use((response) => {
|
|
246
|
+
log.debug({ method: response.config.method?.toUpperCase(), url: response.config.url, status: response.status }, 'HTTP response');
|
|
247
|
+
return response;
|
|
248
|
+
}, (error) => {
|
|
249
|
+
if (error.response) {
|
|
250
|
+
log.error({
|
|
251
|
+
method: error.config?.method?.toUpperCase(),
|
|
252
|
+
url: error.config?.url,
|
|
253
|
+
status: error.response.status,
|
|
254
|
+
}, 'HTTP response error');
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
log.error({ message: error.message }, 'HTTP request failed');
|
|
258
|
+
}
|
|
259
|
+
return Promise.reject(error);
|
|
260
|
+
});
|
|
261
|
+
// Retry interceptor (added after logging so retries are logged)
|
|
262
|
+
if (retry !== false) {
|
|
263
|
+
const retryConfig = {
|
|
264
|
+
maxRetries: retry?.maxRetries ?? 3,
|
|
265
|
+
baseDelay: retry?.baseDelay ?? 1000,
|
|
266
|
+
maxDelay: retry?.maxDelay ?? 30000,
|
|
267
|
+
retryableStatusCodes: retry?.retryableStatusCodes ?? DEFAULT_RETRYABLE_STATUS_CODES,
|
|
268
|
+
retryOnNetworkError: retry?.retryOnNetworkError ?? true,
|
|
269
|
+
};
|
|
270
|
+
client.interceptors.response.use(undefined, async (error) => {
|
|
271
|
+
const config = error.config;
|
|
272
|
+
if (!config) {
|
|
273
|
+
return Promise.reject(error);
|
|
274
|
+
}
|
|
275
|
+
const retryCount = config[RETRY_COUNT_KEY] || 0;
|
|
276
|
+
if (retryCount >= retryConfig.maxRetries) {
|
|
277
|
+
return Promise.reject(error);
|
|
278
|
+
}
|
|
279
|
+
const status = error.response?.status;
|
|
280
|
+
const isRetryable = status
|
|
281
|
+
? retryConfig.retryableStatusCodes.includes(status)
|
|
282
|
+
: retryConfig.retryOnNetworkError && !error.response;
|
|
283
|
+
if (!isRetryable) {
|
|
284
|
+
return Promise.reject(error);
|
|
285
|
+
}
|
|
286
|
+
const attempt = retryCount + 1;
|
|
287
|
+
// For 429, prefer Retry-After header
|
|
288
|
+
let delay;
|
|
289
|
+
if (status === 429) {
|
|
290
|
+
const retryAfterHeader = error.response?.headers?.['retry-after'];
|
|
291
|
+
const retryAfterMs = parseRetryAfter(retryAfterHeader);
|
|
292
|
+
delay = retryAfterMs ?? calculateRetryDelay(attempt, retryConfig.baseDelay, retryConfig.maxDelay);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
delay = calculateRetryDelay(attempt, retryConfig.baseDelay, retryConfig.maxDelay);
|
|
296
|
+
}
|
|
297
|
+
log.info({
|
|
298
|
+
attempt,
|
|
299
|
+
maxRetries: retryConfig.maxRetries,
|
|
300
|
+
status,
|
|
301
|
+
delay: Math.round(delay),
|
|
302
|
+
url: config.url,
|
|
303
|
+
}, 'Retrying request');
|
|
304
|
+
config[RETRY_COUNT_KEY] = attempt;
|
|
305
|
+
await sleep(delay);
|
|
306
|
+
return client.request(config);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return client;
|
|
310
|
+
}
|
|
311
|
+
exports.createConnectorHttpClient = createConnectorHttpClient;
|
|
312
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../lib/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,SAAS,CAAA;AACvB,cAAc,qBAAqB,CAAA;AACnC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,oBAAoB,CAAA;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,SAAS,CAAA;AACvB,cAAc,qBAAqB,CAAA;AACnC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,oBAAoB,CAAA;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
|
package/dist/lib/index.js
CHANGED
|
@@ -27,4 +27,7 @@ __exportStar(require("./logger"), exports);
|
|
|
27
27
|
__exportStar(require("./partitionAdapter"), exports);
|
|
28
28
|
__exportStar(require("./filter"), exports);
|
|
29
29
|
__exportStar(require("./unescape"), exports);
|
|
30
|
+
__exportStar(require("./cache"), exports);
|
|
31
|
+
__exportStar(require("./data-store"), exports);
|
|
32
|
+
__exportStar(require("./http-client"), exports);
|
|
30
33
|
//# sourceMappingURL=index.js.map
|
package/dist/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";AAAA,2EAA2E;;;;;;;;;;;;;;;;AAE3E,6CAA0B;AAC1B,2CAAwB;AACxB,8CAA2B;AAC3B,yDAAsC;AACtC,0CAAuB;AACvB,sDAAmC;AACnC,iEAA8C;AAC9C,6CAA0B;AAC1B,2CAAwB;AACxB,qDAAkC;AAClC,2CAAyB;AACzB,6CAA2B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";AAAA,2EAA2E;;;;;;;;;;;;;;;;AAE3E,6CAA0B;AAC1B,2CAAwB;AACxB,8CAA2B;AAC3B,yDAAsC;AACtC,0CAAuB;AACvB,sDAAmC;AACnC,iEAA8C;AAC9C,6CAA0B;AAC1B,2CAAwB;AACxB,qDAAkC;AAClC,2CAAyB;AACzB,6CAA2B;AAC3B,0CAAwB;AACxB,+CAA6B;AAC7B,gDAA8B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sailpoint/connector-sdk",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "JavaScript framework to build SailPoint Connectors",
|
|
5
5
|
"author": "SailPoint Technologies, Inc.",
|
|
6
6
|
"license": "Copyright (c) 2023. SailPoint Technologies, Inc. All rights reserved.",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"archiver": "^7.0.1",
|
|
32
|
+
"axios": "^1.14.0",
|
|
32
33
|
"debug": "^4.4.1",
|
|
33
34
|
"express": "^5.2.1",
|
|
34
35
|
"jsep": "^1.4.0",
|