@quiltt/core 5.0.0 → 5.0.2

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +19 -12
  3. package/dist/api/browser.cjs +14 -0
  4. package/dist/api/browser.d.ts +128 -0
  5. package/dist/api/browser.js +12 -0
  6. package/dist/api/graphql/SubscriptionLink-12s-ufJBKwu1.js +149 -0
  7. package/dist/api/graphql/SubscriptionLink-12s-wjkChfxO.cjs +150 -0
  8. package/dist/api/graphql/index.cjs +218 -0
  9. package/dist/api/graphql/index.d.ts +82 -0
  10. package/dist/api/graphql/index.js +184 -0
  11. package/dist/api/index.cjs +26 -0
  12. package/dist/api/index.d.ts +3 -0
  13. package/dist/api/index.js +3 -0
  14. package/dist/api/rest/index.cjs +225 -0
  15. package/dist/api/rest/index.d.ts +128 -0
  16. package/dist/api/rest/index.js +217 -0
  17. package/dist/auth/index.cjs +21 -0
  18. package/dist/auth/index.d.ts +29 -0
  19. package/dist/auth/index.js +19 -0
  20. package/dist/config/index.cjs +44 -0
  21. package/dist/config/index.d.ts +9 -0
  22. package/dist/config/index.js +36 -0
  23. package/dist/index.cjs +61 -0
  24. package/dist/index.d.ts +8 -524
  25. package/dist/index.js +8 -449
  26. package/dist/observables/index.cjs +30 -0
  27. package/dist/observables/index.d.ts +21 -0
  28. package/dist/observables/index.js +28 -0
  29. package/dist/storage/index.cjs +272 -0
  30. package/dist/storage/index.d.ts +91 -0
  31. package/dist/{SubscriptionLink-12s-C2VbF8Tf.js → storage/index.js} +2 -139
  32. package/dist/timing/index.cjs +30 -0
  33. package/dist/timing/index.d.ts +15 -0
  34. package/dist/timing/index.js +28 -0
  35. package/dist/types.cjs +1 -0
  36. package/dist/types.d.ts +28 -0
  37. package/dist/types.js +1 -0
  38. package/dist/utils/index.cjs +61 -0
  39. package/dist/utils/index.d.ts +18 -0
  40. package/dist/utils/index.js +57 -0
  41. package/package.json +62 -6
  42. package/src/api/graphql/client.ts +1 -1
  43. package/src/api/graphql/links/ActionCableLink.ts +7 -6
  44. package/src/api/graphql/links/AuthLink.ts +13 -9
  45. package/src/api/graphql/links/BatchHttpLink.ts +1 -1
  46. package/src/api/graphql/links/ErrorLink.ts +4 -0
  47. package/src/api/graphql/links/HttpLink.ts +1 -1
  48. package/src/api/graphql/links/VersionLink.ts +1 -1
  49. package/src/api/rest/auth.ts +1 -1
  50. package/src/api/rest/connectors.ts +1 -1
  51. package/src/auth/index.ts +1 -0
  52. package/src/{JsonWebToken.ts → auth/json-web-token.ts} +1 -1
  53. package/src/{configuration.ts → config/configuration.ts} +1 -1
  54. package/src/config/index.ts +1 -0
  55. package/src/index.ts +5 -5
  56. package/src/observables/index.ts +1 -0
  57. package/src/{Observable.ts → observables/observable.ts} +1 -1
  58. package/src/storage/Local.ts +1 -1
  59. package/src/storage/Memory.ts +2 -2
  60. package/src/storage/Storage.ts +1 -1
  61. package/src/timing/index.ts +1 -0
  62. package/src/{Timeoutable.ts → timing/timeoutable.ts} +1 -1
  63. package/src/utils/index.ts +1 -0
  64. package/src/utils/token-validation.ts +67 -0
@@ -0,0 +1,225 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var index_cjs = require('../../config/index.cjs');
4
+ var crossfetch = require('cross-fetch');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var crossfetch__default = /*#__PURE__*/_interopDefault(crossfetch);
9
+
10
+ // Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
11
+ const effectiveFetch = typeof fetch === 'undefined' ? crossfetch__default.default : fetch;
12
+ const RETRY_DELAY = 150 // ms
13
+ ;
14
+ const RETRIES = 10 // 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500 = 8.250s
15
+ ;
16
+ /**
17
+ * A wrapper around the native `fetch` function that adds automatic retries on failure, including network errors and HTTP 429 responses.
18
+ * Now treats any response with status < 500 as valid.
19
+ */ const fetchWithRetry = async (url, options = {
20
+ retry: false
21
+ })=>{
22
+ const { retry, retriesRemaining, validateStatus = (status)=>status >= 200 && status < 300, ...fetchOptions } = options;
23
+ try {
24
+ const response = await effectiveFetch(url, fetchOptions);
25
+ const isResponseOk = validateStatus(response.status);
26
+ if (isResponseOk) {
27
+ return {
28
+ data: await response.json().catch(()=>null),
29
+ status: response.status,
30
+ statusText: response.statusText,
31
+ headers: response.headers,
32
+ ok: isResponseOk
33
+ };
34
+ }
35
+ // If validateStatus fails, and retry is enabled, prepare to retry for eligible status codes
36
+ if (retry && (response.status >= 500 || response.status === 429)) {
37
+ throw new Error('Retryable failure');
38
+ }
39
+ throw new Error(`HTTP error with status ${response.status}`);
40
+ } catch (error) {
41
+ if (retry) {
42
+ const currentRetriesRemaining = retriesRemaining !== undefined ? retriesRemaining : RETRIES;
43
+ if (currentRetriesRemaining > 0) {
44
+ const delayTime = RETRY_DELAY * (RETRIES - currentRetriesRemaining);
45
+ await new Promise((resolve)=>setTimeout(resolve, delayTime));
46
+ return fetchWithRetry(url, {
47
+ ...options,
48
+ retriesRemaining: currentRetriesRemaining - 1
49
+ });
50
+ }
51
+ }
52
+ return Promise.reject(error);
53
+ }
54
+ };
55
+
56
+ var AuthStrategies = /*#__PURE__*/ function(AuthStrategies) {
57
+ AuthStrategies["Email"] = "email";
58
+ AuthStrategies["Phone"] = "phone";
59
+ return AuthStrategies;
60
+ }({});
61
+ // https://www.quiltt.dev/api-reference/auth
62
+ class AuthAPI {
63
+ constructor(clientId){
64
+ /**
65
+ * Response Statuses:
66
+ * - 200: OK -> Session is Valid
67
+ * - 401: Unauthorized -> Session is Invalid
68
+ */ this.ping = async (token)=>{
69
+ const response = await fetchWithRetry(index_cjs.endpointAuth, {
70
+ method: 'GET',
71
+ ...this.config(token)
72
+ });
73
+ return response;
74
+ };
75
+ /**
76
+ * Response Statuses:
77
+ * - 201: Created -> Profile Created, New Session Returned
78
+ * - 202: Accepted -> Profile Found, MFA Code Sent for `authenticate`
79
+ * - 422: Unprocessable Entity -> Invalid Payload
80
+ */ this.identify = async (payload)=>{
81
+ const response = await fetchWithRetry(index_cjs.endpointAuth, {
82
+ method: 'POST',
83
+ body: JSON.stringify(this.body(payload)),
84
+ ...this.config()
85
+ });
86
+ return response;
87
+ };
88
+ /**
89
+ * Response Statuses:
90
+ * - 201: Created -> MFA Validated, New Session Returned
91
+ * - 401: Unauthorized -> MFA Invalid
92
+ * - 422: Unprocessable Entity -> Invalid Payload
93
+ */ this.authenticate = async (payload)=>{
94
+ const response = await fetchWithRetry(index_cjs.endpointAuth, {
95
+ method: 'PUT',
96
+ body: JSON.stringify(this.body(payload)),
97
+ ...this.config()
98
+ });
99
+ return response;
100
+ };
101
+ /**
102
+ * Response Statuses:
103
+ * - 204: No Content -> Session Revoked
104
+ * - 401: Unauthorized -> Session Not Found
105
+ */ this.revoke = async (token)=>{
106
+ const response = await fetchWithRetry(index_cjs.endpointAuth, {
107
+ method: 'DELETE',
108
+ ...this.config(token)
109
+ });
110
+ return response;
111
+ };
112
+ this.config = (token)=>{
113
+ const headers = new Headers();
114
+ headers.set('Content-Type', 'application/json');
115
+ headers.set('Accept', 'application/json');
116
+ if (token) {
117
+ headers.set('Authorization', `Bearer ${token}`);
118
+ }
119
+ return {
120
+ headers,
121
+ validateStatus: this.validateStatus,
122
+ retry: true
123
+ };
124
+ };
125
+ this.validateStatus = (status)=>status < 500 && status !== 429;
126
+ this.body = (payload)=>{
127
+ if (!this.clientId) {
128
+ console.error('Quiltt Client ID is not set. Unable to identify & authenticate');
129
+ }
130
+ return {
131
+ session: {
132
+ clientId: this.clientId,
133
+ ...payload
134
+ }
135
+ };
136
+ };
137
+ this.clientId = clientId;
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Extracts version number from formatted version string
143
+ * @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
144
+ * @returns Version number like "4.5.1" or "unknown" if not found
145
+ */ const extractVersionNumber = (formattedVersion)=>{
146
+ // Find the 'v' prefix and extract version after it
147
+ const vIndex = formattedVersion.indexOf('v');
148
+ if (vIndex === -1) return 'unknown';
149
+ const versionPart = formattedVersion.substring(vIndex + 1);
150
+ const parts = versionPart.split('.');
151
+ // Validate we have at least major.minor.patch
152
+ if (parts.length < 3) return 'unknown';
153
+ // Extract numeric parts (handles cases like "4.5.1-beta")
154
+ const major = parts[0].match(/^\d+/)?.[0];
155
+ const minor = parts[1].match(/^\d+/)?.[0];
156
+ const patch = parts[2].match(/^\d+/)?.[0];
157
+ if (!major || !minor || !patch) return 'unknown';
158
+ return `${major}.${minor}.${patch}`;
159
+ };
160
+ /**
161
+ * Generates a User-Agent string following standard format
162
+ * Format: Quiltt/<version> (<platform-info>)
163
+ */ const getUserAgent = (sdkVersion, platformInfo)=>{
164
+ return `Quiltt/${sdkVersion} (${platformInfo})`;
165
+ };
166
+
167
+ class ConnectorsAPI {
168
+ constructor(clientId, userAgent = getUserAgent(extractVersionNumber(index_cjs.version), 'Unknown')){
169
+ /**
170
+ * Response Statuses:
171
+ * - 200: OK -> Institutions Found
172
+ * - 401: Unauthorized -> Invalid Token
173
+ * - 403: Forbidden -> Unsupported SDK
174
+ * - 400: Bad Request -> Invalid Request
175
+ */ this.searchInstitutions = async (token, connectorId, term, signal)=>{
176
+ const params = new URLSearchParams();
177
+ params.append('term', term);
178
+ const response = await fetchWithRetry(`${index_cjs.endpointRest}/sdk/connectors/${connectorId}/institutions?${params}`, {
179
+ method: 'GET',
180
+ signal,
181
+ ...this.config(token)
182
+ });
183
+ return response;
184
+ };
185
+ /**
186
+ * Response Statuses:
187
+ * - 200: OK -> Provider API ID is resolvable or not
188
+ * - 401: Unauthorized -> Invalid Token
189
+ * - 403: Forbidden -> Unsupported SDK
190
+ * - 400: Bad Request -> Missing provider API ID parameter
191
+ * - 404: Not Found -> Connector not found
192
+ */ this.checkResolvable = async (token, connectorId, providerId, signal)=>{
193
+ const params = new URLSearchParams();
194
+ const providerKey = Object.keys(providerId)[0];
195
+ if (providerKey && providerId[providerKey]) {
196
+ params.append(providerKey, providerId[providerKey]);
197
+ }
198
+ const response = await fetchWithRetry(`${index_cjs.endpointRest}/sdk/connectors/${connectorId}/resolvable?${params}`, {
199
+ method: 'GET',
200
+ signal,
201
+ ...this.config(token)
202
+ });
203
+ return response;
204
+ };
205
+ this.config = (token)=>{
206
+ const headers = new Headers();
207
+ headers.set('Content-Type', 'application/json');
208
+ headers.set('Accept', 'application/json');
209
+ headers.set('User-Agent', this.userAgent);
210
+ headers.set('Authorization', `Bearer ${token}`);
211
+ return {
212
+ headers,
213
+ validateStatus: this.validateStatus,
214
+ retry: true
215
+ };
216
+ };
217
+ this.validateStatus = (status)=>status < 500 && status !== 429;
218
+ this.clientId = clientId;
219
+ this.userAgent = userAgent;
220
+ }
221
+ }
222
+
223
+ exports.AuthAPI = AuthAPI;
224
+ exports.AuthStrategies = AuthStrategies;
225
+ exports.ConnectorsAPI = ConnectorsAPI;
@@ -0,0 +1,128 @@
1
+ type FetchResponse<T> = {
2
+ data: T;
3
+ status: number;
4
+ statusText: string;
5
+ headers: Headers;
6
+ ok: boolean;
7
+ };
8
+
9
+ type NoContentData = null;
10
+ type ErrorData = {
11
+ message: string;
12
+ instruction: string;
13
+ error_id: string;
14
+ };
15
+ type UnauthorizedData = {
16
+ message: string;
17
+ instruction: string;
18
+ };
19
+ type UnprocessableData = {
20
+ [attribute: string]: Array<string>;
21
+ };
22
+ type BadRequestResponse = FetchResponse<ErrorData>;
23
+ type UnauthorizedResponse = FetchResponse<UnauthorizedData>;
24
+ type UnprocessableResponse = FetchResponse<UnprocessableData>;
25
+
26
+ declare enum AuthStrategies {
27
+ Email = "email",
28
+ Phone = "phone"
29
+ }
30
+ interface EmailInput {
31
+ email: string;
32
+ phone?: never;
33
+ }
34
+ interface PhoneInput {
35
+ phone: string;
36
+ email?: never;
37
+ }
38
+ type UsernamePayload = EmailInput | PhoneInput;
39
+ type PasscodePayload = UsernamePayload & {
40
+ passcode: string;
41
+ };
42
+ type SessionData = {
43
+ token: string;
44
+ };
45
+ type Ping = SessionData | UnauthorizedData;
46
+ type Identify = SessionData | NoContentData | UnprocessableData;
47
+ type Authenticate = SessionData | UnauthorizedData | UnprocessableData;
48
+ type Revoke = NoContentData | UnauthorizedData;
49
+ type SessionResponse = FetchResponse<SessionData>;
50
+ declare class AuthAPI {
51
+ clientId: string | undefined;
52
+ constructor(clientId?: string | undefined);
53
+ /**
54
+ * Response Statuses:
55
+ * - 200: OK -> Session is Valid
56
+ * - 401: Unauthorized -> Session is Invalid
57
+ */
58
+ ping: (token: string) => Promise<FetchResponse<Ping>>;
59
+ /**
60
+ * Response Statuses:
61
+ * - 201: Created -> Profile Created, New Session Returned
62
+ * - 202: Accepted -> Profile Found, MFA Code Sent for `authenticate`
63
+ * - 422: Unprocessable Entity -> Invalid Payload
64
+ */
65
+ identify: (payload: UsernamePayload) => Promise<FetchResponse<Identify>>;
66
+ /**
67
+ * Response Statuses:
68
+ * - 201: Created -> MFA Validated, New Session Returned
69
+ * - 401: Unauthorized -> MFA Invalid
70
+ * - 422: Unprocessable Entity -> Invalid Payload
71
+ */
72
+ authenticate: (payload: PasscodePayload) => Promise<FetchResponse<Authenticate>>;
73
+ /**
74
+ * Response Statuses:
75
+ * - 204: No Content -> Session Revoked
76
+ * - 401: Unauthorized -> Session Not Found
77
+ */
78
+ revoke: (token: string) => Promise<FetchResponse<Revoke>>;
79
+ private config;
80
+ private validateStatus;
81
+ private body;
82
+ }
83
+
84
+ type InstitutionData = {
85
+ name: string;
86
+ logoUrl: string;
87
+ };
88
+ type InstitutionsData = Array<InstitutionData>;
89
+ type ResolvableData = {
90
+ resolvable: boolean;
91
+ };
92
+ type Search = InstitutionsData | ErrorData | UnauthorizedData;
93
+ type Resolvable = ResolvableData | ErrorData | UnauthorizedData;
94
+ type SearchResponse = FetchResponse<InstitutionsData>;
95
+ type ResolvableResponse = FetchResponse<ResolvableData>;
96
+ declare class ConnectorsAPI {
97
+ clientId: string;
98
+ userAgent: string;
99
+ constructor(clientId: string, userAgent?: string);
100
+ /**
101
+ * Response Statuses:
102
+ * - 200: OK -> Institutions Found
103
+ * - 401: Unauthorized -> Invalid Token
104
+ * - 403: Forbidden -> Unsupported SDK
105
+ * - 400: Bad Request -> Invalid Request
106
+ */
107
+ searchInstitutions: (token: string, connectorId: string, term: string, signal?: AbortSignal) => Promise<FetchResponse<Search>>;
108
+ /**
109
+ * Response Statuses:
110
+ * - 200: OK -> Provider API ID is resolvable or not
111
+ * - 401: Unauthorized -> Invalid Token
112
+ * - 403: Forbidden -> Unsupported SDK
113
+ * - 400: Bad Request -> Missing provider API ID parameter
114
+ * - 404: Not Found -> Connector not found
115
+ */
116
+ checkResolvable: (token: string, connectorId: string, providerId: {
117
+ plaid?: string;
118
+ mock?: string;
119
+ mx?: string;
120
+ finicity?: string;
121
+ akoya?: string;
122
+ }, signal?: AbortSignal) => Promise<FetchResponse<Resolvable>>;
123
+ private config;
124
+ private validateStatus;
125
+ }
126
+
127
+ export { AuthAPI, AuthStrategies, ConnectorsAPI };
128
+ export type { BadRequestResponse, ErrorData, InstitutionData, InstitutionsData, NoContentData, PasscodePayload, ResolvableData, ResolvableResponse, SearchResponse, SessionResponse, UnauthorizedData, UnauthorizedResponse, UnprocessableData, UnprocessableResponse, UsernamePayload };
@@ -0,0 +1,217 @@
1
+ import { endpointAuth, endpointRest, version } from '../../config/index.js';
2
+ import crossfetch from 'cross-fetch';
3
+
4
+ // Use `cross-fetch` only if `fetch` is not available on the `globalThis` object
5
+ const effectiveFetch = typeof fetch === 'undefined' ? crossfetch : fetch;
6
+ const RETRY_DELAY = 150 // ms
7
+ ;
8
+ const RETRIES = 10 // 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500 = 8.250s
9
+ ;
10
+ /**
11
+ * A wrapper around the native `fetch` function that adds automatic retries on failure, including network errors and HTTP 429 responses.
12
+ * Now treats any response with status < 500 as valid.
13
+ */ const fetchWithRetry = async (url, options = {
14
+ retry: false
15
+ })=>{
16
+ const { retry, retriesRemaining, validateStatus = (status)=>status >= 200 && status < 300, ...fetchOptions } = options;
17
+ try {
18
+ const response = await effectiveFetch(url, fetchOptions);
19
+ const isResponseOk = validateStatus(response.status);
20
+ if (isResponseOk) {
21
+ return {
22
+ data: await response.json().catch(()=>null),
23
+ status: response.status,
24
+ statusText: response.statusText,
25
+ headers: response.headers,
26
+ ok: isResponseOk
27
+ };
28
+ }
29
+ // If validateStatus fails, and retry is enabled, prepare to retry for eligible status codes
30
+ if (retry && (response.status >= 500 || response.status === 429)) {
31
+ throw new Error('Retryable failure');
32
+ }
33
+ throw new Error(`HTTP error with status ${response.status}`);
34
+ } catch (error) {
35
+ if (retry) {
36
+ const currentRetriesRemaining = retriesRemaining !== undefined ? retriesRemaining : RETRIES;
37
+ if (currentRetriesRemaining > 0) {
38
+ const delayTime = RETRY_DELAY * (RETRIES - currentRetriesRemaining);
39
+ await new Promise((resolve)=>setTimeout(resolve, delayTime));
40
+ return fetchWithRetry(url, {
41
+ ...options,
42
+ retriesRemaining: currentRetriesRemaining - 1
43
+ });
44
+ }
45
+ }
46
+ return Promise.reject(error);
47
+ }
48
+ };
49
+
50
+ var AuthStrategies = /*#__PURE__*/ function(AuthStrategies) {
51
+ AuthStrategies["Email"] = "email";
52
+ AuthStrategies["Phone"] = "phone";
53
+ return AuthStrategies;
54
+ }({});
55
+ // https://www.quiltt.dev/api-reference/auth
56
+ class AuthAPI {
57
+ constructor(clientId){
58
+ /**
59
+ * Response Statuses:
60
+ * - 200: OK -> Session is Valid
61
+ * - 401: Unauthorized -> Session is Invalid
62
+ */ this.ping = async (token)=>{
63
+ const response = await fetchWithRetry(endpointAuth, {
64
+ method: 'GET',
65
+ ...this.config(token)
66
+ });
67
+ return response;
68
+ };
69
+ /**
70
+ * Response Statuses:
71
+ * - 201: Created -> Profile Created, New Session Returned
72
+ * - 202: Accepted -> Profile Found, MFA Code Sent for `authenticate`
73
+ * - 422: Unprocessable Entity -> Invalid Payload
74
+ */ this.identify = async (payload)=>{
75
+ const response = await fetchWithRetry(endpointAuth, {
76
+ method: 'POST',
77
+ body: JSON.stringify(this.body(payload)),
78
+ ...this.config()
79
+ });
80
+ return response;
81
+ };
82
+ /**
83
+ * Response Statuses:
84
+ * - 201: Created -> MFA Validated, New Session Returned
85
+ * - 401: Unauthorized -> MFA Invalid
86
+ * - 422: Unprocessable Entity -> Invalid Payload
87
+ */ this.authenticate = async (payload)=>{
88
+ const response = await fetchWithRetry(endpointAuth, {
89
+ method: 'PUT',
90
+ body: JSON.stringify(this.body(payload)),
91
+ ...this.config()
92
+ });
93
+ return response;
94
+ };
95
+ /**
96
+ * Response Statuses:
97
+ * - 204: No Content -> Session Revoked
98
+ * - 401: Unauthorized -> Session Not Found
99
+ */ this.revoke = async (token)=>{
100
+ const response = await fetchWithRetry(endpointAuth, {
101
+ method: 'DELETE',
102
+ ...this.config(token)
103
+ });
104
+ return response;
105
+ };
106
+ this.config = (token)=>{
107
+ const headers = new Headers();
108
+ headers.set('Content-Type', 'application/json');
109
+ headers.set('Accept', 'application/json');
110
+ if (token) {
111
+ headers.set('Authorization', `Bearer ${token}`);
112
+ }
113
+ return {
114
+ headers,
115
+ validateStatus: this.validateStatus,
116
+ retry: true
117
+ };
118
+ };
119
+ this.validateStatus = (status)=>status < 500 && status !== 429;
120
+ this.body = (payload)=>{
121
+ if (!this.clientId) {
122
+ console.error('Quiltt Client ID is not set. Unable to identify & authenticate');
123
+ }
124
+ return {
125
+ session: {
126
+ clientId: this.clientId,
127
+ ...payload
128
+ }
129
+ };
130
+ };
131
+ this.clientId = clientId;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Extracts version number from formatted version string
137
+ * @param formattedVersion - Formatted version like "@quiltt/core: v4.5.1"
138
+ * @returns Version number like "4.5.1" or "unknown" if not found
139
+ */ const extractVersionNumber = (formattedVersion)=>{
140
+ // Find the 'v' prefix and extract version after it
141
+ const vIndex = formattedVersion.indexOf('v');
142
+ if (vIndex === -1) return 'unknown';
143
+ const versionPart = formattedVersion.substring(vIndex + 1);
144
+ const parts = versionPart.split('.');
145
+ // Validate we have at least major.minor.patch
146
+ if (parts.length < 3) return 'unknown';
147
+ // Extract numeric parts (handles cases like "4.5.1-beta")
148
+ const major = parts[0].match(/^\d+/)?.[0];
149
+ const minor = parts[1].match(/^\d+/)?.[0];
150
+ const patch = parts[2].match(/^\d+/)?.[0];
151
+ if (!major || !minor || !patch) return 'unknown';
152
+ return `${major}.${minor}.${patch}`;
153
+ };
154
+ /**
155
+ * Generates a User-Agent string following standard format
156
+ * Format: Quiltt/<version> (<platform-info>)
157
+ */ const getUserAgent = (sdkVersion, platformInfo)=>{
158
+ return `Quiltt/${sdkVersion} (${platformInfo})`;
159
+ };
160
+
161
+ class ConnectorsAPI {
162
+ constructor(clientId, userAgent = getUserAgent(extractVersionNumber(version), 'Unknown')){
163
+ /**
164
+ * Response Statuses:
165
+ * - 200: OK -> Institutions Found
166
+ * - 401: Unauthorized -> Invalid Token
167
+ * - 403: Forbidden -> Unsupported SDK
168
+ * - 400: Bad Request -> Invalid Request
169
+ */ this.searchInstitutions = async (token, connectorId, term, signal)=>{
170
+ const params = new URLSearchParams();
171
+ params.append('term', term);
172
+ const response = await fetchWithRetry(`${endpointRest}/sdk/connectors/${connectorId}/institutions?${params}`, {
173
+ method: 'GET',
174
+ signal,
175
+ ...this.config(token)
176
+ });
177
+ return response;
178
+ };
179
+ /**
180
+ * Response Statuses:
181
+ * - 200: OK -> Provider API ID is resolvable or not
182
+ * - 401: Unauthorized -> Invalid Token
183
+ * - 403: Forbidden -> Unsupported SDK
184
+ * - 400: Bad Request -> Missing provider API ID parameter
185
+ * - 404: Not Found -> Connector not found
186
+ */ this.checkResolvable = async (token, connectorId, providerId, signal)=>{
187
+ const params = new URLSearchParams();
188
+ const providerKey = Object.keys(providerId)[0];
189
+ if (providerKey && providerId[providerKey]) {
190
+ params.append(providerKey, providerId[providerKey]);
191
+ }
192
+ const response = await fetchWithRetry(`${endpointRest}/sdk/connectors/${connectorId}/resolvable?${params}`, {
193
+ method: 'GET',
194
+ signal,
195
+ ...this.config(token)
196
+ });
197
+ return response;
198
+ };
199
+ this.config = (token)=>{
200
+ const headers = new Headers();
201
+ headers.set('Content-Type', 'application/json');
202
+ headers.set('Accept', 'application/json');
203
+ headers.set('User-Agent', this.userAgent);
204
+ headers.set('Authorization', `Bearer ${token}`);
205
+ return {
206
+ headers,
207
+ validateStatus: this.validateStatus,
208
+ retry: true
209
+ };
210
+ };
211
+ this.validateStatus = (status)=>status < 500 && status !== 429;
212
+ this.clientId = clientId;
213
+ this.userAgent = userAgent;
214
+ }
215
+ }
216
+
217
+ export { AuthAPI, AuthStrategies, ConnectorsAPI };
@@ -0,0 +1,21 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ const MATCHER = /^(?:[\w-]+\.){2}[\w-]+$/;
4
+ const JsonWebTokenParse = (token)=>{
5
+ if (typeof token === 'undefined' || token === null) return token;
6
+ if (!MATCHER.test(token)) {
7
+ console.error(`Invalid Session Token: ${token}`);
8
+ return;
9
+ }
10
+ const [_header, payload, _signature] = token.split('.');
11
+ try {
12
+ return {
13
+ token,
14
+ claims: JSON.parse(atob(payload))
15
+ };
16
+ } catch (error) {
17
+ console.error(`Invalid Session Token: ${error}`);
18
+ }
19
+ };
20
+
21
+ exports.JsonWebTokenParse = JsonWebTokenParse;
@@ -0,0 +1,29 @@
1
+ import { Maybe } from '../types.js';
2
+
3
+ type RegisteredClaims = {
4
+ iss: string;
5
+ sub: string;
6
+ aud: string;
7
+ exp: number;
8
+ nbf: number;
9
+ iat: number;
10
+ jti: string;
11
+ };
12
+ type PrivateClaims = {
13
+ oid: string;
14
+ eid: string;
15
+ cid: string;
16
+ aid: string;
17
+ ver: number;
18
+ rol: 'basic' | 'core' | 'manager' | 'super-admin';
19
+ };
20
+ type Claims<T> = RegisteredClaims & T;
21
+ type JsonWebToken<T> = {
22
+ token: string;
23
+ claims: Claims<T>;
24
+ };
25
+ type QuilttJWT = JsonWebToken<PrivateClaims>;
26
+ declare const JsonWebTokenParse: <T>(token: Maybe<string> | undefined) => Maybe<JsonWebToken<T>> | undefined;
27
+
28
+ export { JsonWebTokenParse };
29
+ export type { Claims, JsonWebToken, PrivateClaims, QuilttJWT, RegisteredClaims };
@@ -0,0 +1,19 @@
1
+ const MATCHER = /^(?:[\w-]+\.){2}[\w-]+$/;
2
+ const JsonWebTokenParse = (token)=>{
3
+ if (typeof token === 'undefined' || token === null) return token;
4
+ if (!MATCHER.test(token)) {
5
+ console.error(`Invalid Session Token: ${token}`);
6
+ return;
7
+ }
8
+ const [_header, payload, _signature] = token.split('.');
9
+ try {
10
+ return {
11
+ token,
12
+ claims: JSON.parse(atob(payload))
13
+ };
14
+ } catch (error) {
15
+ console.error(`Invalid Session Token: ${error}`);
16
+ }
17
+ };
18
+
19
+ export { JsonWebTokenParse };
@@ -0,0 +1,44 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var name = "@quiltt/core";
4
+ var version$1 = "5.0.2";
5
+
6
+ const QUILTT_API_INSECURE = (()=>{
7
+ try {
8
+ return process.env.QUILTT_API_INSECURE === 'true';
9
+ } catch {
10
+ return false;
11
+ }
12
+ })();
13
+ const QUILTT_API_DOMAIN = (()=>{
14
+ try {
15
+ return process.env.QUILTT_API_DOMAIN;
16
+ } catch {
17
+ return undefined;
18
+ }
19
+ })();
20
+ const QUILTT_DEBUG = (()=>{
21
+ try {
22
+ return process.env.NODE_ENV !== 'production' && process.env.QUILTT_DEBUG === 'true';
23
+ } catch {
24
+ return false;
25
+ }
26
+ })();
27
+ const domain = QUILTT_API_DOMAIN || 'quiltt.io';
28
+ const protocolHttp = `http${QUILTT_API_INSECURE ? '' : 's'}`;
29
+ const protocolWebsockets = `ws${QUILTT_API_INSECURE ? '' : 's'}`;
30
+ const debugging = QUILTT_DEBUG;
31
+ const version = `${name}: v${version$1}`;
32
+ const cdnBase = `${protocolHttp}://cdn.${domain}`;
33
+ const endpointAuth = `${protocolHttp}://auth.${domain}/v1/users/session`;
34
+ const endpointGraphQL = `${protocolHttp}://api.${domain}/v1/graphql`;
35
+ const endpointRest = `${protocolHttp}://api.${domain}/v1`;
36
+ const endpointWebsockets = `${protocolWebsockets}://api.${domain}/websockets`;
37
+
38
+ exports.cdnBase = cdnBase;
39
+ exports.debugging = debugging;
40
+ exports.endpointAuth = endpointAuth;
41
+ exports.endpointGraphQL = endpointGraphQL;
42
+ exports.endpointRest = endpointRest;
43
+ exports.endpointWebsockets = endpointWebsockets;
44
+ exports.version = version;