@quiltt/core 5.0.3 → 5.1.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/CHANGELOG.md +20 -0
- package/dist/api/browser.d.ts +6 -0
- package/dist/api/graphql/{SubscriptionLink-12s-wjkChfxO.cjs → SubscriptionLink-12s-DUvHs5WL.cjs} +11 -4
- package/dist/api/graphql/{SubscriptionLink-12s-ufJBKwu1.js → SubscriptionLink-12s-UDBUsy8w.js} +11 -4
- package/dist/api/graphql/index.cjs +62 -6
- package/dist/api/graphql/index.d.ts +22 -2
- package/dist/api/graphql/index.js +62 -7
- package/dist/api/rest/index.cjs +49 -33
- package/dist/api/rest/index.d.ts +17 -3
- package/dist/api/rest/index.js +50 -34
- package/dist/config/index.cjs +1 -1
- package/dist/config/index.js +1 -1
- package/dist/utils/index.cjs +4 -4
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/index.js +4 -4
- package/package.json +1 -1
- package/src/api/browser.ts +6 -0
- package/src/api/graphql/links/ActionCableLink.ts +14 -3
- package/src/api/graphql/links/AuthLink.ts +1 -1
- package/src/api/graphql/links/HeadersLink.ts +84 -0
- package/src/api/graphql/links/VersionLink.ts +3 -4
- package/src/api/graphql/links/index.ts +1 -0
- package/src/api/rest/auth.ts +25 -4
- package/src/api/rest/connectors.ts +24 -7
- package/src/config/configuration.ts +2 -2
- package/src/utils/telemetry.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @quiltt/core
|
|
2
2
|
|
|
3
|
+
## 5.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#419](https://github.com/quiltt/quiltt-js/pull/419) [`5f5846a`](https://github.com/quiltt/quiltt-js/commit/5f5846a1d807f517c156bbebe60d639256a7db1e) Thanks [@rubendinho](https://github.com/rubendinho)! - Update telemetry headers
|
|
8
|
+
|
|
9
|
+
- [#421](https://github.com/quiltt/quiltt-js/pull/421) [`0756cb5`](https://github.com/quiltt/quiltt-js/commit/0756cb59d3fb55208cc2d1bdc10a2a8d5b66b595) Thanks [@sirwolfgang](https://github.com/sirwolfgang)! - Ensure custom Headers are passed to all API calls
|
|
10
|
+
|
|
11
|
+
## 5.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#406](https://github.com/quiltt/quiltt-js/pull/406) [`177a4fc`](https://github.com/quiltt/quiltt-js/commit/177a4fc3d70fa3f313f6586396719dae9763cf4b) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Add OAuth redirect URL support to React SDK
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#418](https://github.com/quiltt/quiltt-js/pull/418) [`2d918a0`](https://github.com/quiltt/quiltt-js/commit/2d918a089f8546bb7d20db1eefd958beca296ee0) Thanks [@sirwolfgang](https://github.com/sirwolfgang)! - Internal: Add `headers` prop to QuilttProvider
|
|
20
|
+
|
|
21
|
+
For Quiltt internal usage. Not intended for public use.
|
|
22
|
+
|
|
3
23
|
## 5.0.3
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/api/browser.d.ts
CHANGED
|
@@ -101,6 +101,8 @@ type ConnectorSDKCallbackMetadata = {
|
|
|
101
101
|
type ConnectorSDKConnectOptions = ConnectorSDKCallbacks & {
|
|
102
102
|
/** The Institution ID or search term to connect */
|
|
103
103
|
institution?: string;
|
|
104
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
105
|
+
oauthRedirectUrl?: string;
|
|
104
106
|
};
|
|
105
107
|
/**
|
|
106
108
|
* Options for the Reconnect flow
|
|
@@ -109,6 +111,8 @@ type ConnectorSDKConnectOptions = ConnectorSDKCallbacks & {
|
|
|
109
111
|
type ConnectorSDKReconnectOptions = ConnectorSDKCallbacks & {
|
|
110
112
|
/** The ID of the Connection to reconnect */
|
|
111
113
|
connectionId: string;
|
|
114
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
115
|
+
oauthRedirectUrl?: string;
|
|
112
116
|
};
|
|
113
117
|
/** Options to initialize Connector
|
|
114
118
|
*
|
|
@@ -122,6 +126,8 @@ type ConnectorSDKConnectorOptions = ConnectorSDKCallbacks & {
|
|
|
122
126
|
connectionId?: string;
|
|
123
127
|
/** The nonce to use for the script tag */
|
|
124
128
|
nonce?: string;
|
|
129
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
130
|
+
oauthRedirectUrl?: string;
|
|
125
131
|
};
|
|
126
132
|
|
|
127
133
|
export { ConnectorSDKEventType };
|
package/dist/api/graphql/{SubscriptionLink-12s-wjkChfxO.cjs → SubscriptionLink-12s-DUvHs5WL.cjs}
RENAMED
|
@@ -99,6 +99,7 @@ class ActionCableLink extends core.ApolloLink {
|
|
|
99
99
|
this.cables[token] = actioncable.createConsumer(index_cjs$1.endpointWebsockets + (token ? `?token=${token}` : ''));
|
|
100
100
|
}
|
|
101
101
|
return new rxjs.Observable((observer)=>{
|
|
102
|
+
let cancelled = false;
|
|
102
103
|
const channelId = Math.round(Date.now() + Math.random() * 100000).toString(16);
|
|
103
104
|
const actionName = this.actionName;
|
|
104
105
|
const connectionParams = typeof this.connectionParams === 'function' ? this.connectionParams(operation) : this.connectionParams;
|
|
@@ -108,6 +109,7 @@ class ActionCableLink extends core.ApolloLink {
|
|
|
108
109
|
channelId: channelId
|
|
109
110
|
}, connectionParams), {
|
|
110
111
|
connected: (args)=>{
|
|
112
|
+
if (cancelled) return;
|
|
111
113
|
channel.perform(actionName, {
|
|
112
114
|
query: operation.query ? graphql.print(operation.query) : null,
|
|
113
115
|
variables: operation.variables,
|
|
@@ -118,6 +120,7 @@ class ActionCableLink extends core.ApolloLink {
|
|
|
118
120
|
callbacks.connected?.(args);
|
|
119
121
|
},
|
|
120
122
|
received: (payload)=>{
|
|
123
|
+
if (cancelled) return;
|
|
121
124
|
if (payload?.result?.data || payload?.result?.errors) {
|
|
122
125
|
observer.next(payload.result);
|
|
123
126
|
}
|
|
@@ -126,14 +129,18 @@ class ActionCableLink extends core.ApolloLink {
|
|
|
126
129
|
}
|
|
127
130
|
callbacks.received?.(payload);
|
|
128
131
|
},
|
|
132
|
+
// Intentionally not guarded by `cancelled` - disconnected represents
|
|
133
|
+
// the WebSocket connection state which users may want to know about
|
|
134
|
+
// for cleanup/status purposes, even after the observable completes.
|
|
129
135
|
disconnected: ()=>{
|
|
130
136
|
callbacks.disconnected?.();
|
|
131
137
|
}
|
|
132
138
|
});
|
|
133
|
-
//
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
// Return teardown logic
|
|
140
|
+
return ()=>{
|
|
141
|
+
cancelled = true;
|
|
142
|
+
channel.unsubscribe();
|
|
143
|
+
};
|
|
137
144
|
});
|
|
138
145
|
}
|
|
139
146
|
}
|
package/dist/api/graphql/{SubscriptionLink-12s-ufJBKwu1.js → SubscriptionLink-12s-UDBUsy8w.js}
RENAMED
|
@@ -99,6 +99,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
99
99
|
this.cables[token] = createConsumer(endpointWebsockets + (token ? `?token=${token}` : ''));
|
|
100
100
|
}
|
|
101
101
|
return new Observable((observer)=>{
|
|
102
|
+
let cancelled = false;
|
|
102
103
|
const channelId = Math.round(Date.now() + Math.random() * 100000).toString(16);
|
|
103
104
|
const actionName = this.actionName;
|
|
104
105
|
const connectionParams = typeof this.connectionParams === 'function' ? this.connectionParams(operation) : this.connectionParams;
|
|
@@ -108,6 +109,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
108
109
|
channelId: channelId
|
|
109
110
|
}, connectionParams), {
|
|
110
111
|
connected: (args)=>{
|
|
112
|
+
if (cancelled) return;
|
|
111
113
|
channel.perform(actionName, {
|
|
112
114
|
query: operation.query ? print(operation.query) : null,
|
|
113
115
|
variables: operation.variables,
|
|
@@ -118,6 +120,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
118
120
|
callbacks.connected?.(args);
|
|
119
121
|
},
|
|
120
122
|
received: (payload)=>{
|
|
123
|
+
if (cancelled) return;
|
|
121
124
|
if (payload?.result?.data || payload?.result?.errors) {
|
|
122
125
|
observer.next(payload.result);
|
|
123
126
|
}
|
|
@@ -126,14 +129,18 @@ class ActionCableLink extends ApolloLink {
|
|
|
126
129
|
}
|
|
127
130
|
callbacks.received?.(payload);
|
|
128
131
|
},
|
|
132
|
+
// Intentionally not guarded by `cancelled` - disconnected represents
|
|
133
|
+
// the WebSocket connection state which users may want to know about
|
|
134
|
+
// for cleanup/status purposes, even after the observable completes.
|
|
129
135
|
disconnected: ()=>{
|
|
130
136
|
callbacks.disconnected?.();
|
|
131
137
|
}
|
|
132
138
|
});
|
|
133
|
-
//
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
// Return teardown logic
|
|
140
|
+
return ()=>{
|
|
141
|
+
cancelled = true;
|
|
142
|
+
channel.unsubscribe();
|
|
143
|
+
};
|
|
137
144
|
});
|
|
138
145
|
}
|
|
139
146
|
}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
3
3
|
var core = require('@apollo/client/core');
|
|
4
4
|
var index_cjs = require('../../config/index.cjs');
|
|
5
5
|
var rxjs = require('rxjs');
|
|
6
|
-
var SubscriptionLink12s = require('./SubscriptionLink-12s-
|
|
6
|
+
var SubscriptionLink12s = require('./SubscriptionLink-12s-DUvHs5WL.cjs');
|
|
7
7
|
var batchHttp = require('@apollo/client/link/batch-http');
|
|
8
8
|
var crossfetch = require('cross-fetch');
|
|
9
9
|
var error = require('@apollo/client/link/error');
|
|
@@ -88,6 +88,62 @@ const ErrorLink = new error.ErrorLink(({ error, result })=>{
|
|
|
88
88
|
|
|
89
89
|
const ForwardableLink = new core.ApolloLink((operation, forward)=>forward(operation));
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Apollo Link that adds custom headers to GraphQL requests.
|
|
93
|
+
*
|
|
94
|
+
* Headers can be provided statically or dynamically via a function.
|
|
95
|
+
* These headers are added before the AuthLink, so they will be preserved
|
|
96
|
+
* alongside the authorization header.
|
|
97
|
+
*/ class HeadersLink extends core.ApolloLink {
|
|
98
|
+
constructor(options = {}){
|
|
99
|
+
super();
|
|
100
|
+
this.headers = options.headers ?? {};
|
|
101
|
+
this.getHeaders = options.getHeaders;
|
|
102
|
+
}
|
|
103
|
+
request(operation, forward) {
|
|
104
|
+
// If we have a dynamic headers function, handle it
|
|
105
|
+
if (this.getHeaders) {
|
|
106
|
+
return new rxjs.Observable((observer)=>{
|
|
107
|
+
let innerSubscription;
|
|
108
|
+
let cancelled = false;
|
|
109
|
+
Promise.resolve(this.getHeaders()).then((dynamicHeaders)=>{
|
|
110
|
+
// Guard against late resolution after unsubscribe
|
|
111
|
+
if (cancelled) return;
|
|
112
|
+
operation.setContext(({ headers = {} })=>({
|
|
113
|
+
headers: {
|
|
114
|
+
...headers,
|
|
115
|
+
...this.headers,
|
|
116
|
+
...dynamicHeaders
|
|
117
|
+
}
|
|
118
|
+
}));
|
|
119
|
+
innerSubscription = forward(operation).subscribe({
|
|
120
|
+
next: (value)=>!cancelled && observer.next(value),
|
|
121
|
+
error: (err)=>!cancelled && observer.error(err),
|
|
122
|
+
complete: ()=>!cancelled && observer.complete()
|
|
123
|
+
});
|
|
124
|
+
}).catch((error)=>{
|
|
125
|
+
if (!cancelled) {
|
|
126
|
+
observer.error(error);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// Return teardown logic
|
|
130
|
+
return ()=>{
|
|
131
|
+
cancelled = true;
|
|
132
|
+
innerSubscription?.unsubscribe();
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// Static headers only
|
|
137
|
+
operation.setContext(({ headers = {} })=>({
|
|
138
|
+
headers: {
|
|
139
|
+
...headers,
|
|
140
|
+
...this.headers
|
|
141
|
+
}
|
|
142
|
+
}));
|
|
143
|
+
return forward(operation);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
91
147
|
// Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
|
|
92
148
|
const effectiveFetch = typeof fetch === 'undefined' ? crossfetch__default.default : fetch;
|
|
93
149
|
const HttpLink = new http.HttpLink({
|
|
@@ -131,22 +187,21 @@ const TerminatingLink = new core.ApolloLink(()=>{
|
|
|
131
187
|
return `${major}.${minor}.${patch}`;
|
|
132
188
|
};
|
|
133
189
|
/**
|
|
134
|
-
* Generates a
|
|
190
|
+
* Generates a custom SDK Agent string following standard format
|
|
135
191
|
* Format: Quiltt/<version> (<platform-info>)
|
|
136
|
-
*/ const
|
|
192
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
137
193
|
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
138
194
|
};
|
|
139
195
|
|
|
140
196
|
const createVersionLink = (platformInfo)=>{
|
|
141
197
|
const versionNumber = extractVersionNumber(index_cjs.version);
|
|
142
|
-
const
|
|
198
|
+
const sdkAgent = getSDKAgent(versionNumber, platformInfo);
|
|
143
199
|
return new core.ApolloLink((operation, forward)=>{
|
|
144
200
|
operation.setContext(({ headers = {} })=>({
|
|
145
201
|
headers: {
|
|
146
202
|
...headers,
|
|
147
203
|
'Quiltt-Client-Version': index_cjs.version,
|
|
148
|
-
'Quiltt-SDK-Agent':
|
|
149
|
-
'User-Agent': userAgent
|
|
204
|
+
'Quiltt-SDK-Agent': sdkAgent
|
|
150
205
|
}
|
|
151
206
|
}));
|
|
152
207
|
return forward(operation);
|
|
@@ -212,6 +267,7 @@ exports.AuthLink = AuthLink;
|
|
|
212
267
|
exports.BatchHttpLink = BatchHttpLink;
|
|
213
268
|
exports.ErrorLink = ErrorLink;
|
|
214
269
|
exports.ForwardableLink = ForwardableLink;
|
|
270
|
+
exports.HeadersLink = HeadersLink;
|
|
215
271
|
exports.HttpLink = HttpLink;
|
|
216
272
|
exports.QuilttClient = QuilttClient;
|
|
217
273
|
exports.RetryLink = RetryLink;
|
|
@@ -38,6 +38,26 @@ declare const ErrorLink: ErrorLink$1;
|
|
|
38
38
|
|
|
39
39
|
declare const ForwardableLink: ApolloLink;
|
|
40
40
|
|
|
41
|
+
type HeadersLinkOptions = {
|
|
42
|
+
/** Static headers to add to every request */
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
/** Dynamic headers function called on each request */
|
|
45
|
+
getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Apollo Link that adds custom headers to GraphQL requests.
|
|
49
|
+
*
|
|
50
|
+
* Headers can be provided statically or dynamically via a function.
|
|
51
|
+
* These headers are added before the AuthLink, so they will be preserved
|
|
52
|
+
* alongside the authorization header.
|
|
53
|
+
*/
|
|
54
|
+
declare class HeadersLink extends ApolloLink {
|
|
55
|
+
private headers;
|
|
56
|
+
private getHeaders?;
|
|
57
|
+
constructor(options?: HeadersLinkOptions);
|
|
58
|
+
request(operation: ApolloLink.Operation, forward: ApolloLink.ForwardFunction): Observable<ApolloLink.Result>;
|
|
59
|
+
}
|
|
60
|
+
|
|
41
61
|
declare const HttpLink: HttpLink$1;
|
|
42
62
|
|
|
43
63
|
declare const RetryLink: RetryLink$1;
|
|
@@ -78,5 +98,5 @@ declare const TerminatingLink: ApolloLink;
|
|
|
78
98
|
|
|
79
99
|
declare const createVersionLink: (platformInfo: string) => ApolloLink;
|
|
80
100
|
|
|
81
|
-
export { AuthLink, BatchHttpLink, ErrorLink, ForwardableLink, HttpLink, QuilttClient, RetryLink, SubscriptionLink, TerminatingLink, createVersionLink };
|
|
82
|
-
export type { QuilttClientOptions };
|
|
101
|
+
export { AuthLink, BatchHttpLink, ErrorLink, ForwardableLink, HeadersLink, HttpLink, QuilttClient, RetryLink, SubscriptionLink, TerminatingLink, createVersionLink };
|
|
102
|
+
export type { HeadersLinkOptions, QuilttClientOptions };
|
|
@@ -2,7 +2,7 @@ import { ApolloLink, ApolloClient } from '@apollo/client/core';
|
|
|
2
2
|
export { gql } from '@apollo/client/core';
|
|
3
3
|
import { endpointGraphQL, version, debugging } from '../../config/index.js';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
|
-
import { v as validateSessionToken, S as SubscriptionLink } from './SubscriptionLink-12s-
|
|
5
|
+
import { v as validateSessionToken, S as SubscriptionLink } from './SubscriptionLink-12s-UDBUsy8w.js';
|
|
6
6
|
import { BatchHttpLink as BatchHttpLink$1 } from '@apollo/client/link/batch-http';
|
|
7
7
|
import crossfetch from 'cross-fetch';
|
|
8
8
|
import { ErrorLink as ErrorLink$1 } from '@apollo/client/link/error';
|
|
@@ -83,6 +83,62 @@ const ErrorLink = new ErrorLink$1(({ error, result })=>{
|
|
|
83
83
|
|
|
84
84
|
const ForwardableLink = new ApolloLink((operation, forward)=>forward(operation));
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Apollo Link that adds custom headers to GraphQL requests.
|
|
88
|
+
*
|
|
89
|
+
* Headers can be provided statically or dynamically via a function.
|
|
90
|
+
* These headers are added before the AuthLink, so they will be preserved
|
|
91
|
+
* alongside the authorization header.
|
|
92
|
+
*/ class HeadersLink extends ApolloLink {
|
|
93
|
+
constructor(options = {}){
|
|
94
|
+
super();
|
|
95
|
+
this.headers = options.headers ?? {};
|
|
96
|
+
this.getHeaders = options.getHeaders;
|
|
97
|
+
}
|
|
98
|
+
request(operation, forward) {
|
|
99
|
+
// If we have a dynamic headers function, handle it
|
|
100
|
+
if (this.getHeaders) {
|
|
101
|
+
return new Observable((observer)=>{
|
|
102
|
+
let innerSubscription;
|
|
103
|
+
let cancelled = false;
|
|
104
|
+
Promise.resolve(this.getHeaders()).then((dynamicHeaders)=>{
|
|
105
|
+
// Guard against late resolution after unsubscribe
|
|
106
|
+
if (cancelled) return;
|
|
107
|
+
operation.setContext(({ headers = {} })=>({
|
|
108
|
+
headers: {
|
|
109
|
+
...headers,
|
|
110
|
+
...this.headers,
|
|
111
|
+
...dynamicHeaders
|
|
112
|
+
}
|
|
113
|
+
}));
|
|
114
|
+
innerSubscription = forward(operation).subscribe({
|
|
115
|
+
next: (value)=>!cancelled && observer.next(value),
|
|
116
|
+
error: (err)=>!cancelled && observer.error(err),
|
|
117
|
+
complete: ()=>!cancelled && observer.complete()
|
|
118
|
+
});
|
|
119
|
+
}).catch((error)=>{
|
|
120
|
+
if (!cancelled) {
|
|
121
|
+
observer.error(error);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// Return teardown logic
|
|
125
|
+
return ()=>{
|
|
126
|
+
cancelled = true;
|
|
127
|
+
innerSubscription?.unsubscribe();
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// Static headers only
|
|
132
|
+
operation.setContext(({ headers = {} })=>({
|
|
133
|
+
headers: {
|
|
134
|
+
...headers,
|
|
135
|
+
...this.headers
|
|
136
|
+
}
|
|
137
|
+
}));
|
|
138
|
+
return forward(operation);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
86
142
|
// Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
|
|
87
143
|
const effectiveFetch = typeof fetch === 'undefined' ? crossfetch : fetch;
|
|
88
144
|
const HttpLink = new HttpLink$1({
|
|
@@ -126,22 +182,21 @@ const TerminatingLink = new ApolloLink(()=>{
|
|
|
126
182
|
return `${major}.${minor}.${patch}`;
|
|
127
183
|
};
|
|
128
184
|
/**
|
|
129
|
-
* Generates a
|
|
185
|
+
* Generates a custom SDK Agent string following standard format
|
|
130
186
|
* Format: Quiltt/<version> (<platform-info>)
|
|
131
|
-
*/ const
|
|
187
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
132
188
|
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
133
189
|
};
|
|
134
190
|
|
|
135
191
|
const createVersionLink = (platformInfo)=>{
|
|
136
192
|
const versionNumber = extractVersionNumber(version);
|
|
137
|
-
const
|
|
193
|
+
const sdkAgent = getSDKAgent(versionNumber, platformInfo);
|
|
138
194
|
return new ApolloLink((operation, forward)=>{
|
|
139
195
|
operation.setContext(({ headers = {} })=>({
|
|
140
196
|
headers: {
|
|
141
197
|
...headers,
|
|
142
198
|
'Quiltt-Client-Version': version,
|
|
143
|
-
'Quiltt-SDK-Agent':
|
|
144
|
-
'User-Agent': userAgent
|
|
199
|
+
'Quiltt-SDK-Agent': sdkAgent
|
|
145
200
|
}
|
|
146
201
|
}));
|
|
147
202
|
return forward(operation);
|
|
@@ -182,4 +237,4 @@ class QuilttClient extends ApolloClient {
|
|
|
182
237
|
}
|
|
183
238
|
}
|
|
184
239
|
|
|
185
|
-
export { AuthLink, BatchHttpLink, ErrorLink, ForwardableLink, HttpLink, QuilttClient, RetryLink, SubscriptionLink, TerminatingLink, createVersionLink };
|
|
240
|
+
export { AuthLink, BatchHttpLink, ErrorLink, ForwardableLink, HeadersLink, HttpLink, QuilttClient, RetryLink, SubscriptionLink, TerminatingLink, createVersionLink };
|
package/dist/api/rest/index.cjs
CHANGED
|
@@ -7,6 +7,32 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
7
7
|
|
|
8
8
|
var crossfetch__default = /*#__PURE__*/_interopDefault(crossfetch);
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Extracts version number from formatted version string
|
|
12
|
+
* @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
|
|
13
|
+
* @returns Version number like "4.5.1" or "unknown" if not found
|
|
14
|
+
*/ const extractVersionNumber = (formattedVersion)=>{
|
|
15
|
+
// Find the 'v' prefix and extract version after it
|
|
16
|
+
const vIndex = formattedVersion.indexOf('v');
|
|
17
|
+
if (vIndex === -1) return 'unknown';
|
|
18
|
+
const versionPart = formattedVersion.substring(vIndex + 1);
|
|
19
|
+
const parts = versionPart.split('.');
|
|
20
|
+
// Validate we have at least major.minor.patch
|
|
21
|
+
if (parts.length < 3) return 'unknown';
|
|
22
|
+
// Extract numeric parts (handles cases like "4.5.1-beta")
|
|
23
|
+
const major = parts[0].match(/^\d+/)?.[0];
|
|
24
|
+
const minor = parts[1].match(/^\d+/)?.[0];
|
|
25
|
+
const patch = parts[2].match(/^\d+/)?.[0];
|
|
26
|
+
if (!major || !minor || !patch) return 'unknown';
|
|
27
|
+
return `${major}.${minor}.${patch}`;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Generates a custom SDK Agent string following standard format
|
|
31
|
+
* Format: Quiltt/<version> (<platform-info>)
|
|
32
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
33
|
+
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
34
|
+
};
|
|
35
|
+
|
|
10
36
|
// Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
|
|
11
37
|
const effectiveFetch = typeof fetch === 'undefined' ? crossfetch__default.default : fetch;
|
|
12
38
|
const RETRY_DELAY = 150 // ms
|
|
@@ -60,8 +86,7 @@ var AuthStrategies = /*#__PURE__*/ function(AuthStrategies) {
|
|
|
60
86
|
}({});
|
|
61
87
|
// https://www.quiltt.dev/api-reference/auth
|
|
62
88
|
class AuthAPI {
|
|
63
|
-
|
|
64
|
-
constructor(clientId){
|
|
89
|
+
constructor(clientId, customHeaders, sdkAgent = getSDKAgent(extractVersionNumber(index_cjs.version), 'Unknown')){
|
|
65
90
|
/**
|
|
66
91
|
* Response Statuses:
|
|
67
92
|
* - 200: OK -> Session is Valid
|
|
@@ -114,6 +139,13 @@ class AuthAPI {
|
|
|
114
139
|
const headers = new Headers();
|
|
115
140
|
headers.set('Content-Type', 'application/json');
|
|
116
141
|
headers.set('Accept', 'application/json');
|
|
142
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent);
|
|
143
|
+
// Apply custom headers
|
|
144
|
+
if (this.customHeaders) {
|
|
145
|
+
Object.entries(this.customHeaders).forEach(([key, value])=>{
|
|
146
|
+
headers.set(key, value);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
117
149
|
if (token) {
|
|
118
150
|
headers.set('Authorization', `Bearer ${token}`);
|
|
119
151
|
}
|
|
@@ -136,37 +168,13 @@ class AuthAPI {
|
|
|
136
168
|
};
|
|
137
169
|
};
|
|
138
170
|
this.clientId = clientId;
|
|
171
|
+
this.customHeaders = customHeaders;
|
|
172
|
+
this.sdkAgent = sdkAgent;
|
|
139
173
|
}
|
|
140
174
|
}
|
|
141
175
|
|
|
142
|
-
/**
|
|
143
|
-
* Extracts version number from formatted version string
|
|
144
|
-
* @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
|
|
145
|
-
* @returns Version number like "4.5.1" or "unknown" if not found
|
|
146
|
-
*/ const extractVersionNumber = (formattedVersion)=>{
|
|
147
|
-
// Find the 'v' prefix and extract version after it
|
|
148
|
-
const vIndex = formattedVersion.indexOf('v');
|
|
149
|
-
if (vIndex === -1) return 'unknown';
|
|
150
|
-
const versionPart = formattedVersion.substring(vIndex + 1);
|
|
151
|
-
const parts = versionPart.split('.');
|
|
152
|
-
// Validate we have at least major.minor.patch
|
|
153
|
-
if (parts.length < 3) return 'unknown';
|
|
154
|
-
// Extract numeric parts (handles cases like "4.5.1-beta")
|
|
155
|
-
const major = parts[0].match(/^\d+/)?.[0];
|
|
156
|
-
const minor = parts[1].match(/^\d+/)?.[0];
|
|
157
|
-
const patch = parts[2].match(/^\d+/)?.[0];
|
|
158
|
-
if (!major || !minor || !patch) return 'unknown';
|
|
159
|
-
return `${major}.${minor}.${patch}`;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Generates a User-Agent string following standard format
|
|
163
|
-
* Format: Quiltt/<version> (<platform-info>)
|
|
164
|
-
*/ const getUserAgent = (sdkVersion, platformInfo)=>{
|
|
165
|
-
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
166
|
-
};
|
|
167
|
-
|
|
168
176
|
class ConnectorsAPI {
|
|
169
|
-
constructor(clientId,
|
|
177
|
+
constructor(clientId, sdkAgent = getSDKAgent(extractVersionNumber(index_cjs.version), 'Unknown'), customHeaders){
|
|
170
178
|
/**
|
|
171
179
|
* Response Statuses:
|
|
172
180
|
* - 200: OK -> Institutions Found
|
|
@@ -207,9 +215,16 @@ class ConnectorsAPI {
|
|
|
207
215
|
const headers = new Headers();
|
|
208
216
|
headers.set('Content-Type', 'application/json');
|
|
209
217
|
headers.set('Accept', 'application/json');
|
|
210
|
-
headers.set('
|
|
211
|
-
headers
|
|
212
|
-
|
|
218
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent);
|
|
219
|
+
// Apply custom headers
|
|
220
|
+
if (this.customHeaders) {
|
|
221
|
+
Object.entries(this.customHeaders).forEach(([key, value])=>{
|
|
222
|
+
headers.set(key, value);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (token) {
|
|
226
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
227
|
+
}
|
|
213
228
|
return {
|
|
214
229
|
headers,
|
|
215
230
|
validateStatus: this.validateStatus,
|
|
@@ -218,7 +233,8 @@ class ConnectorsAPI {
|
|
|
218
233
|
};
|
|
219
234
|
this.validateStatus = (status)=>status < 500 && status !== 429;
|
|
220
235
|
this.clientId = clientId;
|
|
221
|
-
this.
|
|
236
|
+
this.sdkAgent = sdkAgent;
|
|
237
|
+
this.customHeaders = customHeaders;
|
|
222
238
|
}
|
|
223
239
|
}
|
|
224
240
|
|
package/dist/api/rest/index.d.ts
CHANGED
|
@@ -50,7 +50,15 @@ type SessionResponse = FetchResponse<SessionData>;
|
|
|
50
50
|
declare class AuthAPI {
|
|
51
51
|
/** The Connector ID, required for identify & authenticate calls */
|
|
52
52
|
clientId: string | undefined;
|
|
53
|
-
|
|
53
|
+
/** The SDK Agent string for telemetry */
|
|
54
|
+
sdkAgent: string;
|
|
55
|
+
/**
|
|
56
|
+
* Custom headers to include with every request.
|
|
57
|
+
* For Quiltt internal usage. Not intended for public use.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
customHeaders: Record<string, string> | undefined;
|
|
61
|
+
constructor(clientId?: string | undefined, customHeaders?: Record<string, string>, sdkAgent?: string);
|
|
54
62
|
/**
|
|
55
63
|
* Response Statuses:
|
|
56
64
|
* - 200: OK -> Session is Valid
|
|
@@ -96,8 +104,14 @@ type SearchResponse = FetchResponse<InstitutionsData>;
|
|
|
96
104
|
type ResolvableResponse = FetchResponse<ResolvableData>;
|
|
97
105
|
declare class ConnectorsAPI {
|
|
98
106
|
clientId: string;
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
sdkAgent: string;
|
|
108
|
+
/**
|
|
109
|
+
* Custom headers to include with every request.
|
|
110
|
+
* For Quiltt internal usage. Not intended for public use.
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
customHeaders: Record<string, string> | undefined;
|
|
114
|
+
constructor(clientId: string, sdkAgent?: string, customHeaders?: Record<string, string>);
|
|
101
115
|
/**
|
|
102
116
|
* Response Statuses:
|
|
103
117
|
* - 200: OK -> Institutions Found
|
package/dist/api/rest/index.js
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
import { endpointAuth,
|
|
1
|
+
import { endpointAuth, version, endpointRest } from '../../config/index.js';
|
|
2
2
|
import crossfetch from 'cross-fetch';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Extracts version number from formatted version string
|
|
6
|
+
* @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
|
|
7
|
+
* @returns Version number like "4.5.1" or "unknown" if not found
|
|
8
|
+
*/ const extractVersionNumber = (formattedVersion)=>{
|
|
9
|
+
// Find the 'v' prefix and extract version after it
|
|
10
|
+
const vIndex = formattedVersion.indexOf('v');
|
|
11
|
+
if (vIndex === -1) return 'unknown';
|
|
12
|
+
const versionPart = formattedVersion.substring(vIndex + 1);
|
|
13
|
+
const parts = versionPart.split('.');
|
|
14
|
+
// Validate we have at least major.minor.patch
|
|
15
|
+
if (parts.length < 3) return 'unknown';
|
|
16
|
+
// Extract numeric parts (handles cases like "4.5.1-beta")
|
|
17
|
+
const major = parts[0].match(/^\d+/)?.[0];
|
|
18
|
+
const minor = parts[1].match(/^\d+/)?.[0];
|
|
19
|
+
const patch = parts[2].match(/^\d+/)?.[0];
|
|
20
|
+
if (!major || !minor || !patch) return 'unknown';
|
|
21
|
+
return `${major}.${minor}.${patch}`;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Generates a custom SDK Agent string following standard format
|
|
25
|
+
* Format: Quiltt/<version> (<platform-info>)
|
|
26
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
27
|
+
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
28
|
+
};
|
|
29
|
+
|
|
4
30
|
// Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
|
|
5
31
|
const effectiveFetch = typeof fetch === 'undefined' ? crossfetch : fetch;
|
|
6
32
|
const RETRY_DELAY = 150 // ms
|
|
@@ -54,8 +80,7 @@ var AuthStrategies = /*#__PURE__*/ function(AuthStrategies) {
|
|
|
54
80
|
}({});
|
|
55
81
|
// https://www.quiltt.dev/api-reference/auth
|
|
56
82
|
class AuthAPI {
|
|
57
|
-
|
|
58
|
-
constructor(clientId){
|
|
83
|
+
constructor(clientId, customHeaders, sdkAgent = getSDKAgent(extractVersionNumber(version), 'Unknown')){
|
|
59
84
|
/**
|
|
60
85
|
* Response Statuses:
|
|
61
86
|
* - 200: OK -> Session is Valid
|
|
@@ -108,6 +133,13 @@ class AuthAPI {
|
|
|
108
133
|
const headers = new Headers();
|
|
109
134
|
headers.set('Content-Type', 'application/json');
|
|
110
135
|
headers.set('Accept', 'application/json');
|
|
136
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent);
|
|
137
|
+
// Apply custom headers
|
|
138
|
+
if (this.customHeaders) {
|
|
139
|
+
Object.entries(this.customHeaders).forEach(([key, value])=>{
|
|
140
|
+
headers.set(key, value);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
111
143
|
if (token) {
|
|
112
144
|
headers.set('Authorization', `Bearer ${token}`);
|
|
113
145
|
}
|
|
@@ -130,37 +162,13 @@ class AuthAPI {
|
|
|
130
162
|
};
|
|
131
163
|
};
|
|
132
164
|
this.clientId = clientId;
|
|
165
|
+
this.customHeaders = customHeaders;
|
|
166
|
+
this.sdkAgent = sdkAgent;
|
|
133
167
|
}
|
|
134
168
|
}
|
|
135
169
|
|
|
136
|
-
/**
|
|
137
|
-
* Extracts version number from formatted version string
|
|
138
|
-
* @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
|
|
139
|
-
* @returns Version number like "4.5.1" or "unknown" if not found
|
|
140
|
-
*/ const extractVersionNumber = (formattedVersion)=>{
|
|
141
|
-
// Find the 'v' prefix and extract version after it
|
|
142
|
-
const vIndex = formattedVersion.indexOf('v');
|
|
143
|
-
if (vIndex === -1) return 'unknown';
|
|
144
|
-
const versionPart = formattedVersion.substring(vIndex + 1);
|
|
145
|
-
const parts = versionPart.split('.');
|
|
146
|
-
// Validate we have at least major.minor.patch
|
|
147
|
-
if (parts.length < 3) return 'unknown';
|
|
148
|
-
// Extract numeric parts (handles cases like "4.5.1-beta")
|
|
149
|
-
const major = parts[0].match(/^\d+/)?.[0];
|
|
150
|
-
const minor = parts[1].match(/^\d+/)?.[0];
|
|
151
|
-
const patch = parts[2].match(/^\d+/)?.[0];
|
|
152
|
-
if (!major || !minor || !patch) return 'unknown';
|
|
153
|
-
return `${major}.${minor}.${patch}`;
|
|
154
|
-
};
|
|
155
|
-
/**
|
|
156
|
-
* Generates a User-Agent string following standard format
|
|
157
|
-
* Format: Quiltt/<version> (<platform-info>)
|
|
158
|
-
*/ const getUserAgent = (sdkVersion, platformInfo)=>{
|
|
159
|
-
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
160
|
-
};
|
|
161
|
-
|
|
162
170
|
class ConnectorsAPI {
|
|
163
|
-
constructor(clientId,
|
|
171
|
+
constructor(clientId, sdkAgent = getSDKAgent(extractVersionNumber(version), 'Unknown'), customHeaders){
|
|
164
172
|
/**
|
|
165
173
|
* Response Statuses:
|
|
166
174
|
* - 200: OK -> Institutions Found
|
|
@@ -201,9 +209,16 @@ class ConnectorsAPI {
|
|
|
201
209
|
const headers = new Headers();
|
|
202
210
|
headers.set('Content-Type', 'application/json');
|
|
203
211
|
headers.set('Accept', 'application/json');
|
|
204
|
-
headers.set('
|
|
205
|
-
headers
|
|
206
|
-
|
|
212
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent);
|
|
213
|
+
// Apply custom headers
|
|
214
|
+
if (this.customHeaders) {
|
|
215
|
+
Object.entries(this.customHeaders).forEach(([key, value])=>{
|
|
216
|
+
headers.set(key, value);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (token) {
|
|
220
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
221
|
+
}
|
|
207
222
|
return {
|
|
208
223
|
headers,
|
|
209
224
|
validateStatus: this.validateStatus,
|
|
@@ -212,7 +227,8 @@ class ConnectorsAPI {
|
|
|
212
227
|
};
|
|
213
228
|
this.validateStatus = (status)=>status < 500 && status !== 429;
|
|
214
229
|
this.clientId = clientId;
|
|
215
|
-
this.
|
|
230
|
+
this.sdkAgent = sdkAgent;
|
|
231
|
+
this.customHeaders = customHeaders;
|
|
216
232
|
}
|
|
217
233
|
}
|
|
218
234
|
|
package/dist/config/index.cjs
CHANGED
package/dist/config/index.js
CHANGED
package/dist/utils/index.cjs
CHANGED
|
@@ -20,13 +20,13 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
20
20
|
return `${major}.${minor}.${patch}`;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
|
-
* Generates a
|
|
23
|
+
* Generates a custom SDK Agent string following standard format
|
|
24
24
|
* Format: Quiltt/<version> (<platform-info>)
|
|
25
|
-
*/ const
|
|
25
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
26
26
|
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
* Detects browser information from user agent string
|
|
29
|
+
* Detects browser information from Browser's user agent string
|
|
30
30
|
* Returns browser name and version, or 'Unknown' if not detected
|
|
31
31
|
*/ const getBrowserInfo = ()=>{
|
|
32
32
|
if (typeof navigator === 'undefined' || !navigator.userAgent) {
|
|
@@ -58,4 +58,4 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
58
58
|
|
|
59
59
|
exports.extractVersionNumber = extractVersionNumber;
|
|
60
60
|
exports.getBrowserInfo = getBrowserInfo;
|
|
61
|
-
exports.
|
|
61
|
+
exports.getSDKAgent = getSDKAgent;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
declare const extractVersionNumber: (formattedVersion: string) => string;
|
|
7
7
|
/**
|
|
8
|
-
* Generates a
|
|
8
|
+
* Generates a custom SDK Agent string following standard format
|
|
9
9
|
* Format: Quiltt/<version> (<platform-info>)
|
|
10
10
|
*/
|
|
11
|
-
declare const
|
|
11
|
+
declare const getSDKAgent: (sdkVersion: string, platformInfo: string) => string;
|
|
12
12
|
/**
|
|
13
|
-
* Detects browser information from user agent string
|
|
13
|
+
* Detects browser information from Browser's user agent string
|
|
14
14
|
* Returns browser name and version, or 'Unknown' if not detected
|
|
15
15
|
*/
|
|
16
16
|
declare const getBrowserInfo: () => string;
|
|
17
17
|
|
|
18
|
-
export { extractVersionNumber, getBrowserInfo,
|
|
18
|
+
export { extractVersionNumber, getBrowserInfo, getSDKAgent };
|
package/dist/utils/index.js
CHANGED
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
return `${major}.${minor}.${patch}`;
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
|
-
* Generates a
|
|
21
|
+
* Generates a custom SDK Agent string following standard format
|
|
22
22
|
* Format: Quiltt/<version> (<platform-info>)
|
|
23
|
-
*/ const
|
|
23
|
+
*/ const getSDKAgent = (sdkVersion, platformInfo)=>{
|
|
24
24
|
return `Quiltt/${sdkVersion} (${platformInfo})`;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
|
-
* Detects browser information from user agent string
|
|
27
|
+
* Detects browser information from Browser's user agent string
|
|
28
28
|
* Returns browser name and version, or 'Unknown' if not detected
|
|
29
29
|
*/ const getBrowserInfo = ()=>{
|
|
30
30
|
if (typeof navigator === 'undefined' || !navigator.userAgent) {
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
return 'Unknown';
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export { extractVersionNumber, getBrowserInfo,
|
|
57
|
+
export { extractVersionNumber, getBrowserInfo, getSDKAgent };
|
package/package.json
CHANGED
package/src/api/browser.ts
CHANGED
|
@@ -125,6 +125,8 @@ export type ConnectorSDKCallbackMetadata = {
|
|
|
125
125
|
export type ConnectorSDKConnectOptions = ConnectorSDKCallbacks & {
|
|
126
126
|
/** The Institution ID or search term to connect */
|
|
127
127
|
institution?: string
|
|
128
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
129
|
+
oauthRedirectUrl?: string
|
|
128
130
|
}
|
|
129
131
|
|
|
130
132
|
/**
|
|
@@ -134,6 +136,8 @@ export type ConnectorSDKConnectOptions = ConnectorSDKCallbacks & {
|
|
|
134
136
|
export type ConnectorSDKReconnectOptions = ConnectorSDKCallbacks & {
|
|
135
137
|
/** The ID of the Connection to reconnect */
|
|
136
138
|
connectionId: string
|
|
139
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
140
|
+
oauthRedirectUrl?: string
|
|
137
141
|
}
|
|
138
142
|
|
|
139
143
|
/** Options to initialize Connector
|
|
@@ -148,4 +152,6 @@ export type ConnectorSDKConnectorOptions = ConnectorSDKCallbacks & {
|
|
|
148
152
|
connectionId?: string
|
|
149
153
|
/** The nonce to use for the script tag */
|
|
150
154
|
nonce?: string
|
|
155
|
+
/** The OAuth redirect URL for mobile or embedded webview flows */
|
|
156
|
+
oauthRedirectUrl?: string
|
|
151
157
|
}
|
|
@@ -39,7 +39,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
39
39
|
|
|
40
40
|
// Interestingly, this link does _not_ call through to `next` because
|
|
41
41
|
// instead, it sends the request to ActionCable.
|
|
42
|
-
request(
|
|
42
|
+
override request(
|
|
43
43
|
operation: ApolloLink.Operation,
|
|
44
44
|
_next: ApolloLink.ForwardFunction
|
|
45
45
|
): Observable<RequestResult> {
|
|
@@ -58,6 +58,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
return new Observable((observer) => {
|
|
61
|
+
let cancelled = false
|
|
61
62
|
const channelId = Math.round(Date.now() + Math.random() * 100000).toString(16)
|
|
62
63
|
const actionName = this.actionName
|
|
63
64
|
const connectionParams =
|
|
@@ -77,6 +78,7 @@ class ActionCableLink extends ApolloLink {
|
|
|
77
78
|
),
|
|
78
79
|
{
|
|
79
80
|
connected: (args?: { reconnected: boolean }) => {
|
|
81
|
+
if (cancelled) return
|
|
80
82
|
channel.perform(actionName, {
|
|
81
83
|
query: operation.query ? print(operation.query) : null,
|
|
82
84
|
variables: operation.variables,
|
|
@@ -88,6 +90,8 @@ class ActionCableLink extends ApolloLink {
|
|
|
88
90
|
},
|
|
89
91
|
|
|
90
92
|
received: (payload: { result: RequestResult; more: any }) => {
|
|
93
|
+
if (cancelled) return
|
|
94
|
+
|
|
91
95
|
if (payload?.result?.data || payload?.result?.errors) {
|
|
92
96
|
observer.next(payload.result)
|
|
93
97
|
}
|
|
@@ -98,13 +102,20 @@ class ActionCableLink extends ApolloLink {
|
|
|
98
102
|
|
|
99
103
|
callbacks.received?.(payload)
|
|
100
104
|
},
|
|
105
|
+
// Intentionally not guarded by `cancelled` - disconnected represents
|
|
106
|
+
// the WebSocket connection state which users may want to know about
|
|
107
|
+
// for cleanup/status purposes, even after the observable completes.
|
|
101
108
|
disconnected: () => {
|
|
102
109
|
callbacks.disconnected?.()
|
|
103
110
|
},
|
|
104
111
|
}
|
|
105
112
|
)
|
|
106
|
-
|
|
107
|
-
|
|
113
|
+
|
|
114
|
+
// Return teardown logic
|
|
115
|
+
return () => {
|
|
116
|
+
cancelled = true
|
|
117
|
+
channel.unsubscribe()
|
|
118
|
+
}
|
|
108
119
|
})
|
|
109
120
|
}
|
|
110
121
|
}
|
|
@@ -13,7 +13,7 @@ import { validateSessionToken } from '@/utils/token-validation'
|
|
|
13
13
|
* - Emits GraphQL errors for consistent Apollo error handling
|
|
14
14
|
*/
|
|
15
15
|
export class AuthLink extends ApolloLink {
|
|
16
|
-
request(
|
|
16
|
+
override request(
|
|
17
17
|
operation: ApolloLink.Operation,
|
|
18
18
|
forward: ApolloLink.ForwardFunction
|
|
19
19
|
): Observable<ApolloLink.Result> {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ApolloLink } from '@apollo/client/core'
|
|
2
|
+
import type { Subscription } from 'rxjs'
|
|
3
|
+
import { Observable } from 'rxjs'
|
|
4
|
+
|
|
5
|
+
export type HeadersLinkOptions = {
|
|
6
|
+
/** Static headers to add to every request */
|
|
7
|
+
headers?: Record<string, string>
|
|
8
|
+
/** Dynamic headers function called on each request */
|
|
9
|
+
getHeaders?: () => Record<string, string> | Promise<Record<string, string>>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Apollo Link that adds custom headers to GraphQL requests.
|
|
14
|
+
*
|
|
15
|
+
* Headers can be provided statically or dynamically via a function.
|
|
16
|
+
* These headers are added before the AuthLink, so they will be preserved
|
|
17
|
+
* alongside the authorization header.
|
|
18
|
+
*/
|
|
19
|
+
export class HeadersLink extends ApolloLink {
|
|
20
|
+
private headers: Record<string, string>
|
|
21
|
+
private getHeaders?: () => Record<string, string> | Promise<Record<string, string>>
|
|
22
|
+
|
|
23
|
+
constructor(options: HeadersLinkOptions = {}) {
|
|
24
|
+
super()
|
|
25
|
+
this.headers = options.headers ?? {}
|
|
26
|
+
this.getHeaders = options.getHeaders
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override request(
|
|
30
|
+
operation: ApolloLink.Operation,
|
|
31
|
+
forward: ApolloLink.ForwardFunction
|
|
32
|
+
): Observable<ApolloLink.Result> {
|
|
33
|
+
// If we have a dynamic headers function, handle it
|
|
34
|
+
if (this.getHeaders) {
|
|
35
|
+
return new Observable((observer) => {
|
|
36
|
+
let innerSubscription: Subscription | undefined
|
|
37
|
+
let cancelled = false
|
|
38
|
+
|
|
39
|
+
Promise.resolve(this.getHeaders!())
|
|
40
|
+
.then((dynamicHeaders) => {
|
|
41
|
+
// Guard against late resolution after unsubscribe
|
|
42
|
+
if (cancelled) return
|
|
43
|
+
|
|
44
|
+
operation.setContext(({ headers = {} }) => ({
|
|
45
|
+
headers: {
|
|
46
|
+
...headers,
|
|
47
|
+
...this.headers,
|
|
48
|
+
...dynamicHeaders,
|
|
49
|
+
},
|
|
50
|
+
}))
|
|
51
|
+
|
|
52
|
+
innerSubscription = forward(operation).subscribe({
|
|
53
|
+
next: (value) => !cancelled && observer.next(value),
|
|
54
|
+
error: (err) => !cancelled && observer.error(err),
|
|
55
|
+
complete: () => !cancelled && observer.complete(),
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
.catch((error) => {
|
|
59
|
+
if (!cancelled) {
|
|
60
|
+
observer.error(error)
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Return teardown logic
|
|
65
|
+
return () => {
|
|
66
|
+
cancelled = true
|
|
67
|
+
innerSubscription?.unsubscribe()
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Static headers only
|
|
73
|
+
operation.setContext(({ headers = {} }) => ({
|
|
74
|
+
headers: {
|
|
75
|
+
...headers,
|
|
76
|
+
...this.headers,
|
|
77
|
+
},
|
|
78
|
+
}))
|
|
79
|
+
|
|
80
|
+
return forward(operation)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default HeadersLink
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { ApolloLink } from '@apollo/client/core'
|
|
2
2
|
|
|
3
3
|
import { version } from '@/config'
|
|
4
|
-
import { extractVersionNumber,
|
|
4
|
+
import { extractVersionNumber, getSDKAgent } from '@/utils/telemetry'
|
|
5
5
|
|
|
6
6
|
export const createVersionLink = (platformInfo: string) => {
|
|
7
7
|
const versionNumber = extractVersionNumber(version)
|
|
8
|
-
const
|
|
8
|
+
const sdkAgent = getSDKAgent(versionNumber, platformInfo)
|
|
9
9
|
|
|
10
10
|
return new ApolloLink((operation, forward) => {
|
|
11
11
|
operation.setContext(({ headers = {} }) => ({
|
|
12
12
|
headers: {
|
|
13
13
|
...headers,
|
|
14
14
|
'Quiltt-Client-Version': version,
|
|
15
|
-
'Quiltt-SDK-Agent':
|
|
16
|
-
'User-Agent': userAgent,
|
|
15
|
+
'Quiltt-SDK-Agent': sdkAgent,
|
|
17
16
|
},
|
|
18
17
|
}))
|
|
19
18
|
return forward(operation)
|
package/src/api/rest/auth.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { endpointAuth } from '@/config'
|
|
1
|
+
import { endpointAuth, version } from '@/config'
|
|
2
|
+
import { extractVersionNumber, getSDKAgent } from '@/utils/telemetry'
|
|
2
3
|
|
|
3
4
|
import type { FetchResponse } from './fetchWithRetry'
|
|
4
5
|
import { fetchWithRetry } from './fetchWithRetry'
|
|
@@ -35,11 +36,23 @@ export type SessionResponse = FetchResponse<SessionData>
|
|
|
35
36
|
export class AuthAPI {
|
|
36
37
|
/** The Connector ID, required for identify & authenticate calls */
|
|
37
38
|
clientId: string | undefined
|
|
39
|
+
/** The SDK Agent string for telemetry */
|
|
40
|
+
sdkAgent: string
|
|
41
|
+
/**
|
|
42
|
+
* Custom headers to include with every request.
|
|
43
|
+
* For Quiltt internal usage. Not intended for public use.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
customHeaders: Record<string, string> | undefined
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
constructor(
|
|
49
|
+
clientId?: string | undefined,
|
|
50
|
+
customHeaders?: Record<string, string>,
|
|
51
|
+
sdkAgent: string = getSDKAgent(extractVersionNumber(version), 'Unknown')
|
|
52
|
+
) {
|
|
42
53
|
this.clientId = clientId
|
|
54
|
+
this.customHeaders = customHeaders
|
|
55
|
+
this.sdkAgent = sdkAgent
|
|
43
56
|
}
|
|
44
57
|
|
|
45
58
|
/**
|
|
@@ -102,6 +115,14 @@ export class AuthAPI {
|
|
|
102
115
|
const headers = new Headers()
|
|
103
116
|
headers.set('Content-Type', 'application/json')
|
|
104
117
|
headers.set('Accept', 'application/json')
|
|
118
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent)
|
|
119
|
+
|
|
120
|
+
// Apply custom headers
|
|
121
|
+
if (this.customHeaders) {
|
|
122
|
+
Object.entries(this.customHeaders).forEach(([key, value]) => {
|
|
123
|
+
headers.set(key, value)
|
|
124
|
+
})
|
|
125
|
+
}
|
|
105
126
|
|
|
106
127
|
if (token) {
|
|
107
128
|
headers.set('Authorization', `Bearer ${token}`)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { endpointRest, version } from '@/config'
|
|
2
|
-
import { extractVersionNumber,
|
|
2
|
+
import { extractVersionNumber, getSDKAgent } from '@/utils/telemetry'
|
|
3
3
|
|
|
4
4
|
import type { FetchResponse } from './fetchWithRetry'
|
|
5
5
|
import { fetchWithRetry } from './fetchWithRetry'
|
|
@@ -18,14 +18,22 @@ export type ResolvableResponse = FetchResponse<ResolvableData>
|
|
|
18
18
|
|
|
19
19
|
export class ConnectorsAPI {
|
|
20
20
|
clientId: string
|
|
21
|
-
|
|
21
|
+
sdkAgent: string
|
|
22
|
+
/**
|
|
23
|
+
* Custom headers to include with every request.
|
|
24
|
+
* For Quiltt internal usage. Not intended for public use.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
customHeaders: Record<string, string> | undefined
|
|
22
28
|
|
|
23
29
|
constructor(
|
|
24
30
|
clientId: string,
|
|
25
|
-
|
|
31
|
+
sdkAgent: string = getSDKAgent(extractVersionNumber(version), 'Unknown'),
|
|
32
|
+
customHeaders?: Record<string, string>
|
|
26
33
|
) {
|
|
27
34
|
this.clientId = clientId
|
|
28
|
-
this.
|
|
35
|
+
this.sdkAgent = sdkAgent
|
|
36
|
+
this.customHeaders = customHeaders
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
/**
|
|
@@ -91,9 +99,18 @@ export class ConnectorsAPI {
|
|
|
91
99
|
const headers = new Headers()
|
|
92
100
|
headers.set('Content-Type', 'application/json')
|
|
93
101
|
headers.set('Accept', 'application/json')
|
|
94
|
-
headers.set('
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
headers.set('Quiltt-SDK-Agent', this.sdkAgent)
|
|
103
|
+
|
|
104
|
+
// Apply custom headers
|
|
105
|
+
if (this.customHeaders) {
|
|
106
|
+
Object.entries(this.customHeaders).forEach(([key, value]) => {
|
|
107
|
+
headers.set(key, value)
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (token) {
|
|
112
|
+
headers.set('Authorization', `Bearer ${token}`)
|
|
113
|
+
}
|
|
97
114
|
|
|
98
115
|
return {
|
|
99
116
|
headers,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { name as
|
|
1
|
+
import { name as PACKAGE_NAME, version as PACKAGE_VERSION } from '../../package.json'
|
|
2
2
|
|
|
3
3
|
const QUILTT_API_INSECURE = (() => {
|
|
4
4
|
try {
|
|
@@ -29,7 +29,7 @@ const protocolHttp = `http${QUILTT_API_INSECURE ? '' : 's'}`
|
|
|
29
29
|
const protocolWebsockets = `ws${QUILTT_API_INSECURE ? '' : 's'}`
|
|
30
30
|
|
|
31
31
|
export const debugging = QUILTT_DEBUG
|
|
32
|
-
export const version = `${
|
|
32
|
+
export const version = `${PACKAGE_NAME}: v${PACKAGE_VERSION}`
|
|
33
33
|
|
|
34
34
|
export const cdnBase = `${protocolHttp}://cdn.${domain}`
|
|
35
35
|
export const endpointAuth = `${protocolHttp}://auth.${domain}/v1/users/session`
|
package/src/utils/telemetry.ts
CHANGED
|
@@ -25,15 +25,15 @@ export const extractVersionNumber = (formattedVersion: string): string => {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Generates a
|
|
28
|
+
* Generates a custom SDK Agent string following standard format
|
|
29
29
|
* Format: Quiltt/<version> (<platform-info>)
|
|
30
30
|
*/
|
|
31
|
-
export const
|
|
31
|
+
export const getSDKAgent = (sdkVersion: string, platformInfo: string): string => {
|
|
32
32
|
return `Quiltt/${sdkVersion} (${platformInfo})`
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* Detects browser information from user agent string
|
|
36
|
+
* Detects browser information from Browser's user agent string
|
|
37
37
|
* Returns browser name and version, or 'Unknown' if not detected
|
|
38
38
|
*/
|
|
39
39
|
export const getBrowserInfo = (): string => {
|