@c15t/node-sdk 2.2.0 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs DELETED
@@ -1,427 +0,0 @@
1
- "use strict";
2
- var __webpack_require__ = {};
3
- (()=>{
4
- __webpack_require__.d = (exports1, getters, values)=>{
5
- var define = (defs, kind)=>{
6
- for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- [kind]: defs[key]
9
- });
10
- };
11
- define(getters, "get");
12
- define(values, "value");
13
- };
14
- })();
15
- (()=>{
16
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
- })();
18
- (()=>{
19
- __webpack_require__.r = (exports1)=>{
20
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
- value: 'Module'
22
- });
23
- Object.defineProperty(exports1, '__esModule', {
24
- value: true
25
- });
26
- };
27
- })();
28
- var __webpack_exports__ = {};
29
- __webpack_require__.r(__webpack_exports__);
30
- __webpack_require__.d(__webpack_exports__, {
31
- C15TClient: ()=>C15TClient,
32
- C15TError: ()=>C15TError,
33
- c15tClient: ()=>c15tClient,
34
- createResponseContext: ()=>createResponseContext,
35
- fetcher: ()=>fetcher,
36
- isC15TError: ()=>isC15TError,
37
- resolveUrl: ()=>resolveUrl
38
- });
39
- class C15TError extends Error {
40
- status;
41
- code;
42
- details;
43
- cause;
44
- constructor(options){
45
- super(options.message);
46
- this.name = 'C15TError';
47
- this.status = options.status;
48
- this.code = options.code;
49
- this.details = options.details;
50
- this.cause = options.cause;
51
- if (Error.captureStackTrace) Error.captureStackTrace(this, C15TError);
52
- }
53
- isStatus(status) {
54
- return this.status === status;
55
- }
56
- isNotFound() {
57
- return 404 === this.status || 'NOT_FOUND' === this.code;
58
- }
59
- isValidationError() {
60
- return 400 === this.status || 'VALIDATION_ERROR' === this.code;
61
- }
62
- isUnauthorized() {
63
- return 401 === this.status || 'UNAUTHORIZED' === this.code;
64
- }
65
- isForbidden() {
66
- return 403 === this.status || 'FORBIDDEN' === this.code;
67
- }
68
- isServerError() {
69
- return this.status >= 500 && this.status < 600;
70
- }
71
- isNetworkError() {
72
- return 0 === this.status || 'NETWORK_ERROR' === this.code;
73
- }
74
- toJSON() {
75
- return {
76
- name: this.name,
77
- message: this.message,
78
- status: this.status,
79
- code: this.code,
80
- details: this.details
81
- };
82
- }
83
- }
84
- function isC15TError(error) {
85
- return error instanceof C15TError;
86
- }
87
- const C15T_VERSION_HEADERS = {
88
- 'x-c15t-version': "2.2.0"
89
- };
90
- const DEFAULT_RETRY_CONFIG = {
91
- maxRetries: 3,
92
- initialDelayMs: 100,
93
- backoffFactor: 2,
94
- retryableStatusCodes: [
95
- 500,
96
- 502,
97
- 503,
98
- 504
99
- ],
100
- nonRetryableStatusCodes: [
101
- 400,
102
- 401,
103
- 403,
104
- 404
105
- ],
106
- retryOnNetworkError: true
107
- };
108
- function debugLog(debug, method, path, durationMs, status) {
109
- if (!debug) return;
110
- const timestamp = new Date().toISOString();
111
- console.log(`[c15t] ${timestamp} ${method} ${path} (${durationMs}ms) -> ${status}`);
112
- }
113
- const delay = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
114
- function generateUUID() {
115
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c)=>{
116
- const r = 16 * Math.random() | 0;
117
- const v = 'x' === c ? r : 0x3 & r | 0x8;
118
- return v.toString(16);
119
- });
120
- }
121
- function createResponseContext(isSuccess, data = null, error = null, response = null) {
122
- return {
123
- data,
124
- error,
125
- ok: isSuccess,
126
- response,
127
- unwrap () {
128
- if (!isSuccess || null === data) throw new C15TError({
129
- message: error?.message || 'Request failed',
130
- status: error?.status || 0,
131
- code: error?.code,
132
- details: error?.details,
133
- cause: error?.cause
134
- });
135
- return data;
136
- },
137
- unwrapOr (defaultValue) {
138
- if (!isSuccess || null === data) return defaultValue;
139
- return data;
140
- },
141
- expect (message) {
142
- if (!isSuccess || null === data) throw new C15TError({
143
- message,
144
- status: error?.status || 0,
145
- code: error?.code,
146
- details: error?.details,
147
- cause: error?.cause
148
- });
149
- return data;
150
- },
151
- map (fn) {
152
- if (!isSuccess || null === data) return createResponseContext(false, null, error, response);
153
- return createResponseContext(true, fn(data), null, response);
154
- }
155
- };
156
- }
157
- function resolveUrl(baseUrl, path) {
158
- const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
159
- const cleanPath = path.startsWith('/') ? path.slice(1) : path;
160
- return `${cleanBase}/${cleanPath}`;
161
- }
162
- async function fetcher(context, path, options) {
163
- const finalRetryConfig = {
164
- ...DEFAULT_RETRY_CONFIG,
165
- ...context.retryConfig,
166
- ...options?.retryConfig || {}
167
- };
168
- const { maxRetries = 3, initialDelayMs = 100, backoffFactor = 2, retryableStatusCodes = [
169
- 500,
170
- 502,
171
- 503,
172
- 504
173
- ], nonRetryableStatusCodes = [
174
- 400,
175
- 401,
176
- 403,
177
- 404
178
- ], retryOnNetworkError = true } = finalRetryConfig;
179
- let attemptsMade = 0;
180
- let currentDelay = initialDelayMs;
181
- let lastErrorResponse = null;
182
- while(attemptsMade <= maxRetries){
183
- const requestId = generateUUID();
184
- const resolvedUrl = resolveUrl(context.baseUrl, path);
185
- const url = new URL(resolvedUrl);
186
- if (options?.query) {
187
- for (const [key, value] of Object.entries(options.query))if (null != value) url.searchParams.append(key, String(value));
188
- }
189
- const timeoutMs = options?.timeout ?? context.timeout;
190
- const controller = new AbortController();
191
- let timeoutId;
192
- if (timeoutMs > 0) timeoutId = setTimeout(()=>controller.abort(), timeoutMs);
193
- const requestOptions = {
194
- method: options?.method || 'GET',
195
- headers: {
196
- 'Content-Type': 'application/json',
197
- ...C15T_VERSION_HEADERS,
198
- ...context.headers,
199
- 'X-Request-ID': requestId,
200
- ...options?.headers
201
- },
202
- signal: controller.signal
203
- };
204
- if (options?.body && 'GET' !== requestOptions.method) requestOptions.body = JSON.stringify(options.body);
205
- const startTime = Date.now();
206
- try {
207
- const response = await fetch(url.toString(), requestOptions);
208
- if (timeoutId) clearTimeout(timeoutId);
209
- const durationMs = Date.now() - startTime;
210
- let data = null;
211
- let parseError = null;
212
- try {
213
- const contentType = response.headers.get('content-type');
214
- if (contentType?.includes('application/json') && 204 !== response.status && '0' !== response.headers.get('content-length')) data = await response.json();
215
- else if (204 === response.status) data = null;
216
- } catch (err) {
217
- parseError = err;
218
- }
219
- if (parseError) {
220
- const errorResponse = createResponseContext(false, null, {
221
- message: 'Failed to parse response',
222
- status: response.status,
223
- code: 'PARSE_ERROR',
224
- cause: parseError
225
- }, response);
226
- options?.onError?.(errorResponse, path);
227
- if (options?.throw) throw new Error('Failed to parse response');
228
- return errorResponse;
229
- }
230
- const isSuccess = response.status >= 200 && response.status < 300;
231
- if (isSuccess) {
232
- debugLog(context.debug, requestOptions.method || 'GET', path, durationMs, response.status);
233
- const successResponse = createResponseContext(true, data, null, response);
234
- options?.onSuccess?.(successResponse);
235
- return successResponse;
236
- }
237
- const errorData = data;
238
- const errorResponse = createResponseContext(false, null, {
239
- message: errorData?.message || `Request failed with status ${response.status}`,
240
- status: response.status,
241
- code: errorData?.code || 'API_ERROR',
242
- details: errorData?.details || null
243
- }, response);
244
- lastErrorResponse = errorResponse;
245
- let shouldRetryThisRequest = false;
246
- shouldRetryThisRequest = nonRetryableStatusCodes.includes(response.status) ? false : retryableStatusCodes.includes(response.status);
247
- if (!shouldRetryThisRequest || attemptsMade >= maxRetries) {
248
- debugLog(context.debug, requestOptions.method || 'GET', path, durationMs, response.status);
249
- options?.onError?.(errorResponse, path);
250
- if (options?.throw) throw new Error(errorResponse.error?.message || 'Request failed');
251
- return errorResponse;
252
- }
253
- attemptsMade++;
254
- await delay(currentDelay);
255
- currentDelay *= backoffFactor;
256
- } catch (fetchError) {
257
- if (timeoutId) clearTimeout(timeoutId);
258
- if (fetchError instanceof Error && 'Failed to parse response' === fetchError.message) throw fetchError;
259
- const isAbortError = fetchError instanceof Error && 'AbortError' === fetchError.name;
260
- const isNetworkError = !(fetchError instanceof Response);
261
- const errorResponse = createResponseContext(false, null, {
262
- message: isAbortError ? `Request timed out after ${timeoutMs}ms` : fetchError instanceof Error ? fetchError.message : String(fetchError),
263
- status: 0,
264
- code: isAbortError ? 'TIMEOUT' : 'NETWORK_ERROR',
265
- cause: fetchError
266
- }, null);
267
- lastErrorResponse = errorResponse;
268
- const shouldRetryThisRequest = isNetworkError && retryOnNetworkError;
269
- if (!shouldRetryThisRequest || attemptsMade >= maxRetries) {
270
- debugLog(context.debug, requestOptions.method || 'GET', path, Date.now() - startTime, 'ERROR');
271
- options?.onError?.(errorResponse, path);
272
- if (options?.throw) throw fetchError;
273
- return errorResponse;
274
- }
275
- attemptsMade++;
276
- await delay(currentDelay);
277
- currentDelay *= backoffFactor;
278
- }
279
- }
280
- const maxRetriesErrorResponse = lastErrorResponse || createResponseContext(false, null, {
281
- message: `Request failed after ${maxRetries} retries`,
282
- status: 0,
283
- code: 'MAX_RETRIES_EXCEEDED'
284
- }, null);
285
- options?.onError?.(maxRetriesErrorResponse, path);
286
- if (options?.throw) throw new Error(`Request failed after ${maxRetries} retries`);
287
- return maxRetriesErrorResponse;
288
- }
289
- const CONSENT_CHECK_PATH = '/consents/check';
290
- async function checkConsent(context, query, options) {
291
- return fetcher(context, CONSENT_CHECK_PATH, {
292
- method: 'GET',
293
- query,
294
- ...options
295
- });
296
- }
297
- const INIT_PATH = '/init';
298
- async function init(context, options) {
299
- return fetcher(context, INIT_PATH, {
300
- method: 'GET',
301
- ...options
302
- });
303
- }
304
- const STATUS_PATH = '/status';
305
- async function status_status(context, options) {
306
- return fetcher(context, STATUS_PATH, {
307
- method: 'GET',
308
- ...options
309
- });
310
- }
311
- const SUBJECTS_PATH = '/subjects';
312
- async function createSubject(context, input, options) {
313
- return fetcher(context, SUBJECTS_PATH, {
314
- method: 'POST',
315
- body: input,
316
- ...options
317
- });
318
- }
319
- async function getSubject(context, id, query, options) {
320
- return fetcher(context, `${SUBJECTS_PATH}/${id}`, {
321
- method: 'GET',
322
- query,
323
- ...options
324
- });
325
- }
326
- async function patchSubject(context, id, input, options) {
327
- return fetcher(context, `${SUBJECTS_PATH}/${id}`, {
328
- method: 'PATCH',
329
- body: input,
330
- ...options
331
- });
332
- }
333
- async function listSubjects(context, query, options) {
334
- return fetcher(context, SUBJECTS_PATH, {
335
- method: 'GET',
336
- query,
337
- ...options
338
- });
339
- }
340
- class C15TClient {
341
- context;
342
- constructor(options = {}){
343
- const baseUrlString = options.baseUrl || ("u" > typeof process ? process.env?.C15T_API_URL : void 0);
344
- if (!baseUrlString) throw new TypeError('baseUrl is required. Provide it in options or set C15T_API_URL environment variable.');
345
- const baseUrl = new URL(baseUrlString);
346
- if (options.prefix) baseUrl.pathname = options.prefix;
347
- const token = options.token || ("u" > typeof process ? process.env?.C15T_API_TOKEN : void 0);
348
- const authHeaders = token ? {
349
- Authorization: `Bearer ${token}`
350
- } : {};
351
- const retryConfig = {
352
- ...DEFAULT_RETRY_CONFIG,
353
- ...options.retryConfig
354
- };
355
- const debug = options.debug ?? ("u" > typeof process ? process.env?.C15T_DEBUG === 'true' : false);
356
- const timeout = options.timeout ?? 30000;
357
- this.context = {
358
- baseUrl: baseUrl.toString(),
359
- headers: {
360
- ...authHeaders,
361
- ...options.headers
362
- },
363
- retryConfig,
364
- debug,
365
- timeout
366
- };
367
- }
368
- async status(options) {
369
- return status_status(this.context, options);
370
- }
371
- async init(options) {
372
- return init(this.context, options);
373
- }
374
- async createSubject(input, options) {
375
- return createSubject(this.context, input, options);
376
- }
377
- async getSubject(id, query, options) {
378
- return getSubject(this.context, id, query, options);
379
- }
380
- async patchSubject(id, input, options) {
381
- return patchSubject(this.context, id, input, options);
382
- }
383
- async listSubjects(query, options) {
384
- return listSubjects(this.context, query, options);
385
- }
386
- async checkConsent(query, options) {
387
- return checkConsent(this.context, query, options);
388
- }
389
- async $fetch(path, options) {
390
- return fetcher(this.context, path, options);
391
- }
392
- consent = {
393
- check: (query, options)=>this.checkConsent(query, options)
394
- };
395
- subjects = {
396
- create: (input, options)=>this.createSubject(input, options),
397
- get: (id, query, options)=>this.getSubject(id, query, options),
398
- patch: (id, input, options)=>this.patchSubject(id, input, options),
399
- list: (query, options)=>this.listSubjects(query, options)
400
- };
401
- meta = {
402
- status: (options)=>this.status(options),
403
- init: (options)=>this.init(options)
404
- };
405
- }
406
- function c15tClient(options) {
407
- return new C15TClient(options);
408
- }
409
- exports.C15TClient = __webpack_exports__.C15TClient;
410
- exports.C15TError = __webpack_exports__.C15TError;
411
- exports.c15tClient = __webpack_exports__.c15tClient;
412
- exports.createResponseContext = __webpack_exports__.createResponseContext;
413
- exports.fetcher = __webpack_exports__.fetcher;
414
- exports.isC15TError = __webpack_exports__.isC15TError;
415
- exports.resolveUrl = __webpack_exports__.resolveUrl;
416
- for(var __rspack_i in __webpack_exports__)if (-1 === [
417
- "C15TClient",
418
- "C15TError",
419
- "c15tClient",
420
- "createResponseContext",
421
- "fetcher",
422
- "isC15TError",
423
- "resolveUrl"
424
- ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
425
- Object.defineProperty(exports, '__esModule', {
426
- value: true
427
- });
package/dist/testing.cjs DELETED
@@ -1,123 +0,0 @@
1
- "use strict";
2
- var __webpack_require__ = {};
3
- (()=>{
4
- __webpack_require__.d = (exports1, getters, values)=>{
5
- var define = (defs, kind)=>{
6
- for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- [kind]: defs[key]
9
- });
10
- };
11
- define(getters, "get");
12
- define(values, "value");
13
- };
14
- })();
15
- (()=>{
16
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
- })();
18
- (()=>{
19
- __webpack_require__.r = (exports1)=>{
20
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
- value: 'Module'
22
- });
23
- Object.defineProperty(exports1, '__esModule', {
24
- value: true
25
- });
26
- };
27
- })();
28
- var __webpack_exports__ = {};
29
- __webpack_require__.r(__webpack_exports__);
30
- function createMockResponse(data, options = {}) {
31
- const isSuccess = options.ok ?? true;
32
- const error = options.error ?? null;
33
- const response = options.response ?? null;
34
- return {
35
- data: isSuccess ? data : null,
36
- error,
37
- ok: isSuccess,
38
- response,
39
- unwrap () {
40
- if (!isSuccess || null === data) throw new Error(error?.message || 'Request failed');
41
- return data;
42
- },
43
- unwrapOr (defaultValue) {
44
- if (!isSuccess || null === data) return defaultValue;
45
- return data;
46
- },
47
- expect (message) {
48
- if (!isSuccess || null === data) throw new Error(message);
49
- return data;
50
- },
51
- map (fn) {
52
- if (!isSuccess || null === data) return createMockResponse(null, {
53
- ok: false,
54
- error: error ?? void 0
55
- });
56
- return createMockResponse(fn(data));
57
- }
58
- };
59
- }
60
- function createMockErrorResponse(error) {
61
- return createMockResponse(null, {
62
- ok: false,
63
- error
64
- });
65
- }
66
- function createMockClient(overrides = {}) {
67
- const defaultNotImplemented = ()=>createMockErrorResponse({
68
- message: 'Method not implemented in mock',
69
- status: 501,
70
- code: 'NOT_IMPLEMENTED'
71
- });
72
- const status = overrides.status ?? defaultNotImplemented;
73
- const init = overrides.init ?? defaultNotImplemented;
74
- const checkConsent = overrides.checkConsent ?? defaultNotImplemented;
75
- const createSubject = overrides.createSubject ?? defaultNotImplemented;
76
- const getSubject = overrides.getSubject ?? defaultNotImplemented;
77
- const patchSubject = overrides.patchSubject ?? defaultNotImplemented;
78
- const listSubjects = overrides.listSubjects ?? defaultNotImplemented;
79
- return {
80
- status: ()=>Promise.resolve(status()),
81
- init: ()=>Promise.resolve(init()),
82
- checkConsent: (query)=>Promise.resolve(checkConsent(query)),
83
- createSubject: (input)=>Promise.resolve(createSubject(input)),
84
- getSubject: (id)=>Promise.resolve(getSubject(id)),
85
- patchSubject: (id, input)=>Promise.resolve(patchSubject({
86
- id,
87
- ...'object' == typeof input && null !== input ? input : {}
88
- })),
89
- listSubjects: (query)=>Promise.resolve(listSubjects(query)),
90
- consent: {
91
- check: (query)=>Promise.resolve(checkConsent(query))
92
- },
93
- subjects: {
94
- create: (input)=>Promise.resolve(createSubject(input)),
95
- get: (id)=>Promise.resolve(getSubject(id)),
96
- patch: (id, input)=>Promise.resolve(patchSubject({
97
- id,
98
- ...'object' == typeof input && null !== input ? input : {}
99
- })),
100
- list: (query)=>Promise.resolve(listSubjects(query))
101
- },
102
- meta: {
103
- status: ()=>Promise.resolve(status()),
104
- init: ()=>Promise.resolve(init())
105
- }
106
- };
107
- }
108
- __webpack_require__.d(__webpack_exports__, {
109
- createMockClient: ()=>createMockClient,
110
- createMockErrorResponse: ()=>createMockErrorResponse,
111
- createMockResponse: ()=>createMockResponse
112
- });
113
- exports.createMockClient = __webpack_exports__.createMockClient;
114
- exports.createMockErrorResponse = __webpack_exports__.createMockErrorResponse;
115
- exports.createMockResponse = __webpack_exports__.createMockResponse;
116
- for(var __rspack_i in __webpack_exports__)if (-1 === [
117
- "createMockClient",
118
- "createMockErrorResponse",
119
- "createMockResponse"
120
- ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
121
- Object.defineProperty(exports, '__esModule', {
122
- value: true
123
- });