@schematichq/schematic-js 1.0.2 → 1.1.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/README.md +7 -4
- package/dist/schematic.browser.js +2 -2
- package/dist/schematic.cjs.js +375 -113
- package/dist/schematic.d.ts +273 -18
- package/dist/schematic.esm.js +372 -110
- package/package.json +5 -2
package/dist/schematic.cjs.js
CHANGED
|
@@ -35,11 +35,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
35
35
|
"node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
|
|
36
36
|
(function(self2) {
|
|
37
37
|
var irrelevant = function(exports2) {
|
|
38
|
-
var
|
|
38
|
+
var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
|
|
39
|
+
typeof global !== "undefined" && global || {};
|
|
39
40
|
var support = {
|
|
40
|
-
searchParams: "URLSearchParams" in
|
|
41
|
-
iterable: "Symbol" in
|
|
42
|
-
blob: "FileReader" in
|
|
41
|
+
searchParams: "URLSearchParams" in g,
|
|
42
|
+
iterable: "Symbol" in g && "iterator" in Symbol,
|
|
43
|
+
blob: "FileReader" in g && "Blob" in g && function() {
|
|
43
44
|
try {
|
|
44
45
|
new Blob();
|
|
45
46
|
return true;
|
|
@@ -47,8 +48,8 @@ var require_browser_polyfill = __commonJS({
|
|
|
47
48
|
return false;
|
|
48
49
|
}
|
|
49
50
|
}(),
|
|
50
|
-
formData: "FormData" in
|
|
51
|
-
arrayBuffer: "ArrayBuffer" in
|
|
51
|
+
formData: "FormData" in g,
|
|
52
|
+
arrayBuffer: "ArrayBuffer" in g
|
|
52
53
|
};
|
|
53
54
|
function isDataView(obj) {
|
|
54
55
|
return obj && DataView.prototype.isPrototypeOf(obj);
|
|
@@ -106,6 +107,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
106
107
|
}, this);
|
|
107
108
|
} else if (Array.isArray(headers)) {
|
|
108
109
|
headers.forEach(function(header) {
|
|
110
|
+
if (header.length != 2) {
|
|
111
|
+
throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
|
|
112
|
+
}
|
|
109
113
|
this.append(header[0], header[1]);
|
|
110
114
|
}, this);
|
|
111
115
|
} else if (headers) {
|
|
@@ -165,6 +169,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
165
169
|
Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
|
|
166
170
|
}
|
|
167
171
|
function consumed(body) {
|
|
172
|
+
if (body._noBody) return;
|
|
168
173
|
if (body.bodyUsed) {
|
|
169
174
|
return Promise.reject(new TypeError("Already read"));
|
|
170
175
|
}
|
|
@@ -189,7 +194,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
189
194
|
function readBlobAsText(blob) {
|
|
190
195
|
var reader = new FileReader();
|
|
191
196
|
var promise = fileReaderReady(reader);
|
|
192
|
-
|
|
197
|
+
var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
|
|
198
|
+
var encoding = match ? match[1] : "utf-8";
|
|
199
|
+
reader.readAsText(blob, encoding);
|
|
193
200
|
return promise;
|
|
194
201
|
}
|
|
195
202
|
function readArrayBufferAsText(buf) {
|
|
@@ -215,6 +222,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
215
222
|
this.bodyUsed = this.bodyUsed;
|
|
216
223
|
this._bodyInit = body;
|
|
217
224
|
if (!body) {
|
|
225
|
+
this._noBody = true;
|
|
218
226
|
this._bodyText = "";
|
|
219
227
|
} else if (typeof body === "string") {
|
|
220
228
|
this._bodyText = body;
|
|
@@ -258,27 +266,28 @@ var require_browser_polyfill = __commonJS({
|
|
|
258
266
|
return Promise.resolve(new Blob([this._bodyText]));
|
|
259
267
|
}
|
|
260
268
|
};
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
} else {
|
|
275
|
-
return Promise.resolve(this._bodyArrayBuffer);
|
|
276
|
-
}
|
|
269
|
+
}
|
|
270
|
+
this.arrayBuffer = function() {
|
|
271
|
+
if (this._bodyArrayBuffer) {
|
|
272
|
+
var isConsumed = consumed(this);
|
|
273
|
+
if (isConsumed) {
|
|
274
|
+
return isConsumed;
|
|
275
|
+
} else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
|
|
276
|
+
return Promise.resolve(
|
|
277
|
+
this._bodyArrayBuffer.buffer.slice(
|
|
278
|
+
this._bodyArrayBuffer.byteOffset,
|
|
279
|
+
this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
|
|
280
|
+
)
|
|
281
|
+
);
|
|
277
282
|
} else {
|
|
278
|
-
return
|
|
283
|
+
return Promise.resolve(this._bodyArrayBuffer);
|
|
279
284
|
}
|
|
280
|
-
}
|
|
281
|
-
|
|
285
|
+
} else if (support.blob) {
|
|
286
|
+
return this.blob().then(readBlobAsArrayBuffer);
|
|
287
|
+
} else {
|
|
288
|
+
throw new Error("could not read as ArrayBuffer");
|
|
289
|
+
}
|
|
290
|
+
};
|
|
282
291
|
this.text = function() {
|
|
283
292
|
var rejected = consumed(this);
|
|
284
293
|
if (rejected) {
|
|
@@ -304,7 +313,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
304
313
|
};
|
|
305
314
|
return this;
|
|
306
315
|
}
|
|
307
|
-
var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"];
|
|
316
|
+
var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
|
|
308
317
|
function normalizeMethod(method) {
|
|
309
318
|
var upcased = method.toUpperCase();
|
|
310
319
|
return methods.indexOf(upcased) > -1 ? upcased : method;
|
|
@@ -340,7 +349,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
340
349
|
}
|
|
341
350
|
this.method = normalizeMethod(options.method || this.method || "GET");
|
|
342
351
|
this.mode = options.mode || this.mode || null;
|
|
343
|
-
this.signal = options.signal || this.signal
|
|
352
|
+
this.signal = options.signal || this.signal || function() {
|
|
353
|
+
if ("AbortController" in g) {
|
|
354
|
+
var ctrl = new AbortController();
|
|
355
|
+
return ctrl.signal;
|
|
356
|
+
}
|
|
357
|
+
}();
|
|
344
358
|
this.referrer = null;
|
|
345
359
|
if ((this.method === "GET" || this.method === "HEAD") && body) {
|
|
346
360
|
throw new TypeError("Body not allowed for GET or HEAD requests");
|
|
@@ -383,7 +397,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
383
397
|
var key = parts.shift().trim();
|
|
384
398
|
if (key) {
|
|
385
399
|
var value = parts.join(":").trim();
|
|
386
|
-
|
|
400
|
+
try {
|
|
401
|
+
headers.append(key, value);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
console.warn("Response " + error.message);
|
|
404
|
+
}
|
|
387
405
|
}
|
|
388
406
|
});
|
|
389
407
|
return headers;
|
|
@@ -398,6 +416,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
398
416
|
}
|
|
399
417
|
this.type = "default";
|
|
400
418
|
this.status = options.status === void 0 ? 200 : options.status;
|
|
419
|
+
if (this.status < 200 || this.status > 599) {
|
|
420
|
+
throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
|
|
421
|
+
}
|
|
401
422
|
this.ok = this.status >= 200 && this.status < 300;
|
|
402
423
|
this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
|
|
403
424
|
this.headers = new Headers(options.headers);
|
|
@@ -414,7 +435,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
414
435
|
});
|
|
415
436
|
};
|
|
416
437
|
Response.error = function() {
|
|
417
|
-
var response = new Response(null, { status:
|
|
438
|
+
var response = new Response(null, { status: 200, statusText: "" });
|
|
439
|
+
response.ok = false;
|
|
440
|
+
response.status = 0;
|
|
418
441
|
response.type = "error";
|
|
419
442
|
return response;
|
|
420
443
|
};
|
|
@@ -425,7 +448,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
425
448
|
}
|
|
426
449
|
return new Response(null, { status, headers: { location: url } });
|
|
427
450
|
};
|
|
428
|
-
exports2.DOMException =
|
|
451
|
+
exports2.DOMException = g.DOMException;
|
|
429
452
|
try {
|
|
430
453
|
new exports2.DOMException();
|
|
431
454
|
} catch (err) {
|
|
@@ -450,10 +473,14 @@ var require_browser_polyfill = __commonJS({
|
|
|
450
473
|
}
|
|
451
474
|
xhr.onload = function() {
|
|
452
475
|
var options = {
|
|
453
|
-
status: xhr.status,
|
|
454
476
|
statusText: xhr.statusText,
|
|
455
477
|
headers: parseHeaders(xhr.getAllResponseHeaders() || "")
|
|
456
478
|
};
|
|
479
|
+
if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
|
|
480
|
+
options.status = 200;
|
|
481
|
+
} else {
|
|
482
|
+
options.status = xhr.status;
|
|
483
|
+
}
|
|
457
484
|
options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
|
|
458
485
|
var body = "response" in xhr ? xhr.response : xhr.responseText;
|
|
459
486
|
setTimeout(function() {
|
|
@@ -467,7 +494,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
467
494
|
};
|
|
468
495
|
xhr.ontimeout = function() {
|
|
469
496
|
setTimeout(function() {
|
|
470
|
-
reject(new TypeError("Network request
|
|
497
|
+
reject(new TypeError("Network request timed out"));
|
|
471
498
|
}, 0);
|
|
472
499
|
};
|
|
473
500
|
xhr.onabort = function() {
|
|
@@ -477,7 +504,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
477
504
|
};
|
|
478
505
|
function fixUrl(url) {
|
|
479
506
|
try {
|
|
480
|
-
return url === "" &&
|
|
507
|
+
return url === "" && g.location.href ? g.location.href : url;
|
|
481
508
|
} catch (e) {
|
|
482
509
|
return url;
|
|
483
510
|
}
|
|
@@ -491,14 +518,21 @@ var require_browser_polyfill = __commonJS({
|
|
|
491
518
|
if ("responseType" in xhr) {
|
|
492
519
|
if (support.blob) {
|
|
493
520
|
xhr.responseType = "blob";
|
|
494
|
-
} else if (support.arrayBuffer
|
|
521
|
+
} else if (support.arrayBuffer) {
|
|
495
522
|
xhr.responseType = "arraybuffer";
|
|
496
523
|
}
|
|
497
524
|
}
|
|
498
|
-
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers)) {
|
|
525
|
+
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
|
|
526
|
+
var names = [];
|
|
499
527
|
Object.getOwnPropertyNames(init.headers).forEach(function(name) {
|
|
528
|
+
names.push(normalizeName(name));
|
|
500
529
|
xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
|
|
501
530
|
});
|
|
531
|
+
request.headers.forEach(function(value, name) {
|
|
532
|
+
if (names.indexOf(name) === -1) {
|
|
533
|
+
xhr.setRequestHeader(name, value);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
502
536
|
} else {
|
|
503
537
|
request.headers.forEach(function(value, name) {
|
|
504
538
|
xhr.setRequestHeader(name, value);
|
|
@@ -516,11 +550,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
516
550
|
});
|
|
517
551
|
}
|
|
518
552
|
fetch2.polyfill = true;
|
|
519
|
-
if (!
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
553
|
+
if (!g.fetch) {
|
|
554
|
+
g.fetch = fetch2;
|
|
555
|
+
g.Headers = Headers;
|
|
556
|
+
g.Request = Request;
|
|
557
|
+
g.Response = Response;
|
|
524
558
|
}
|
|
525
559
|
exports2.Headers = Headers;
|
|
526
560
|
exports2.Request = Request;
|
|
@@ -533,18 +567,22 @@ var require_browser_polyfill = __commonJS({
|
|
|
533
567
|
});
|
|
534
568
|
|
|
535
569
|
// src/index.ts
|
|
536
|
-
var
|
|
537
|
-
__export(
|
|
538
|
-
|
|
570
|
+
var index_exports = {};
|
|
571
|
+
__export(index_exports, {
|
|
572
|
+
CheckFlagResponseFromJSON: () => CheckFlagResponseFromJSON,
|
|
573
|
+
CheckFlagReturnFromJSON: () => CheckFlagReturnFromJSON,
|
|
574
|
+
CheckFlagsResponseFromJSON: () => CheckFlagsResponseFromJSON,
|
|
575
|
+
RuleType: () => RuleType,
|
|
576
|
+
Schematic: () => Schematic,
|
|
577
|
+
UsagePeriod: () => UsagePeriod
|
|
539
578
|
});
|
|
540
|
-
module.exports = __toCommonJS(
|
|
579
|
+
module.exports = __toCommonJS(index_exports);
|
|
541
580
|
|
|
542
581
|
// node_modules/uuid/dist/esm-browser/stringify.js
|
|
543
582
|
var byteToHex = [];
|
|
544
|
-
for (i = 0; i < 256; ++i) {
|
|
583
|
+
for (let i = 0; i < 256; ++i) {
|
|
545
584
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
546
585
|
}
|
|
547
|
-
var i;
|
|
548
586
|
function unsafeStringify(arr, offset = 0) {
|
|
549
587
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
550
588
|
}
|
|
@@ -554,19 +592,17 @@ var getRandomValues;
|
|
|
554
592
|
var rnds8 = new Uint8Array(16);
|
|
555
593
|
function rng() {
|
|
556
594
|
if (!getRandomValues) {
|
|
557
|
-
|
|
558
|
-
if (!getRandomValues) {
|
|
595
|
+
if (typeof crypto === "undefined" || !crypto.getRandomValues) {
|
|
559
596
|
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
560
597
|
}
|
|
598
|
+
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
561
599
|
}
|
|
562
600
|
return getRandomValues(rnds8);
|
|
563
601
|
}
|
|
564
602
|
|
|
565
603
|
// node_modules/uuid/dist/esm-browser/native.js
|
|
566
604
|
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
567
|
-
var native_default = {
|
|
568
|
-
randomUUID
|
|
569
|
-
};
|
|
605
|
+
var native_default = { randomUUID };
|
|
570
606
|
|
|
571
607
|
// node_modules/uuid/dist/esm-browser/v4.js
|
|
572
608
|
function v4(options, buf, offset) {
|
|
@@ -574,12 +610,18 @@ function v4(options, buf, offset) {
|
|
|
574
610
|
return native_default.randomUUID();
|
|
575
611
|
}
|
|
576
612
|
options = options || {};
|
|
577
|
-
|
|
613
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
614
|
+
if (rnds.length < 16) {
|
|
615
|
+
throw new Error("Random bytes length must be >= 16");
|
|
616
|
+
}
|
|
578
617
|
rnds[6] = rnds[6] & 15 | 64;
|
|
579
618
|
rnds[8] = rnds[8] & 63 | 128;
|
|
580
619
|
if (buf) {
|
|
581
620
|
offset = offset || 0;
|
|
582
|
-
|
|
621
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
622
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
623
|
+
}
|
|
624
|
+
for (let i = 0; i < 16; ++i) {
|
|
583
625
|
buf[offset + i] = rnds[i];
|
|
584
626
|
}
|
|
585
627
|
return buf;
|
|
@@ -591,6 +633,127 @@ var v4_default = v4;
|
|
|
591
633
|
// src/index.ts
|
|
592
634
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
593
635
|
|
|
636
|
+
// src/types/api/models/CheckFlagResponseData.ts
|
|
637
|
+
function CheckFlagResponseDataFromJSON(json) {
|
|
638
|
+
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
639
|
+
}
|
|
640
|
+
function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
641
|
+
if (json == null) {
|
|
642
|
+
return json;
|
|
643
|
+
}
|
|
644
|
+
return {
|
|
645
|
+
companyId: json["company_id"] == null ? void 0 : json["company_id"],
|
|
646
|
+
error: json["error"] == null ? void 0 : json["error"],
|
|
647
|
+
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
648
|
+
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
649
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
650
|
+
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
651
|
+
flag: json["flag"],
|
|
652
|
+
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
653
|
+
reason: json["reason"],
|
|
654
|
+
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
655
|
+
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
656
|
+
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
657
|
+
value: json["value"]
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// src/types/api/models/CheckFlagResponse.ts
|
|
662
|
+
function CheckFlagResponseFromJSON(json) {
|
|
663
|
+
return CheckFlagResponseFromJSONTyped(json, false);
|
|
664
|
+
}
|
|
665
|
+
function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
666
|
+
if (json == null) {
|
|
667
|
+
return json;
|
|
668
|
+
}
|
|
669
|
+
return {
|
|
670
|
+
data: CheckFlagResponseDataFromJSON(json["data"]),
|
|
671
|
+
params: json["params"]
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// src/types/api/models/CheckFlagsResponseData.ts
|
|
676
|
+
function CheckFlagsResponseDataFromJSON(json) {
|
|
677
|
+
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
678
|
+
}
|
|
679
|
+
function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
680
|
+
if (json == null) {
|
|
681
|
+
return json;
|
|
682
|
+
}
|
|
683
|
+
return {
|
|
684
|
+
flags: json["flags"].map(CheckFlagResponseDataFromJSON)
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// src/types/api/models/CheckFlagsResponse.ts
|
|
689
|
+
function CheckFlagsResponseFromJSON(json) {
|
|
690
|
+
return CheckFlagsResponseFromJSONTyped(json, false);
|
|
691
|
+
}
|
|
692
|
+
function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
693
|
+
if (json == null) {
|
|
694
|
+
return json;
|
|
695
|
+
}
|
|
696
|
+
return {
|
|
697
|
+
data: CheckFlagsResponseDataFromJSON(json["data"]),
|
|
698
|
+
params: json["params"]
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/types/index.ts
|
|
703
|
+
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
704
|
+
RuleType2["GLOBAL_OVERRIDE"] = "global_override";
|
|
705
|
+
RuleType2["COMPANY_OVERRIDE"] = "company_override";
|
|
706
|
+
RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
|
|
707
|
+
RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
|
|
708
|
+
RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
|
|
709
|
+
RuleType2["STANDARD"] = "standard";
|
|
710
|
+
RuleType2["DEFAULT"] = "default";
|
|
711
|
+
return RuleType2;
|
|
712
|
+
})(RuleType || {});
|
|
713
|
+
var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
|
|
714
|
+
UsagePeriod2["ALL_TIME"] = "all_time";
|
|
715
|
+
UsagePeriod2["CURRENT_DAY"] = "current_day";
|
|
716
|
+
UsagePeriod2["CURRENT_MONTH"] = "current_month";
|
|
717
|
+
UsagePeriod2["CURRENT_WEEK"] = "current_week";
|
|
718
|
+
return UsagePeriod2;
|
|
719
|
+
})(UsagePeriod || {});
|
|
720
|
+
var CheckFlagReturnFromJSON = (json) => {
|
|
721
|
+
const {
|
|
722
|
+
companyId,
|
|
723
|
+
error,
|
|
724
|
+
featureAllocation,
|
|
725
|
+
featureUsage,
|
|
726
|
+
featureUsagePeriod,
|
|
727
|
+
featureUsageResetAt,
|
|
728
|
+
flag,
|
|
729
|
+
flagId,
|
|
730
|
+
reason,
|
|
731
|
+
ruleId,
|
|
732
|
+
ruleType,
|
|
733
|
+
userId,
|
|
734
|
+
value
|
|
735
|
+
} = CheckFlagResponseDataFromJSON(json);
|
|
736
|
+
const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
|
|
737
|
+
(ruleType == "company_override_usage_exceeded" /* COMPANY_OVERRIDE_USAGE_EXCEEDED */ || // if the rule type is one of these, then we have exceeded usage
|
|
738
|
+
ruleType == "plan_entitlement_usage_exceeded" /* PLAN_ENTITLEMENT_USAGE_EXCEEDED */);
|
|
739
|
+
return {
|
|
740
|
+
featureUsageExceeded,
|
|
741
|
+
companyId: companyId == null ? void 0 : companyId,
|
|
742
|
+
error: error == null ? void 0 : error,
|
|
743
|
+
featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
|
|
744
|
+
featureUsage: featureUsage == null ? void 0 : featureUsage,
|
|
745
|
+
featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
|
|
746
|
+
featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
|
|
747
|
+
flag,
|
|
748
|
+
flagId: flagId == null ? void 0 : flagId,
|
|
749
|
+
reason,
|
|
750
|
+
ruleId: ruleId == null ? void 0 : ruleId,
|
|
751
|
+
ruleType: ruleType == null ? void 0 : ruleType,
|
|
752
|
+
userId: userId == null ? void 0 : userId,
|
|
753
|
+
value
|
|
754
|
+
};
|
|
755
|
+
};
|
|
756
|
+
|
|
594
757
|
// src/utils.ts
|
|
595
758
|
function contextString(context) {
|
|
596
759
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
@@ -617,19 +780,18 @@ var Schematic = class {
|
|
|
617
780
|
context = {};
|
|
618
781
|
eventQueue;
|
|
619
782
|
eventUrl = "https://c.schematichq.com";
|
|
620
|
-
|
|
783
|
+
flagCheckListeners = {};
|
|
621
784
|
flagValueListeners = {};
|
|
622
785
|
isPending = true;
|
|
623
786
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
624
787
|
storage;
|
|
625
788
|
useWebSocket = false;
|
|
626
|
-
|
|
789
|
+
checks = {};
|
|
627
790
|
webSocketUrl = "wss://api.schematichq.com";
|
|
628
791
|
constructor(apiKey, options) {
|
|
629
792
|
this.apiKey = apiKey;
|
|
630
793
|
this.eventQueue = [];
|
|
631
794
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
632
|
-
this.flagListener = options?.flagListener;
|
|
633
795
|
if (options?.additionalHeaders) {
|
|
634
796
|
this.additionalHeaders = options.additionalHeaders;
|
|
635
797
|
}
|
|
@@ -653,37 +815,89 @@ var Schematic = class {
|
|
|
653
815
|
});
|
|
654
816
|
}
|
|
655
817
|
}
|
|
656
|
-
|
|
657
|
-
|
|
818
|
+
/**
|
|
819
|
+
* Get value for a single flag.
|
|
820
|
+
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
821
|
+
* new connection and then returns the requestedvalue. Falls back to REST API if WebSocket
|
|
822
|
+
* connection fails.
|
|
823
|
+
* In REST mode, makes an API call for each check.
|
|
824
|
+
*/
|
|
658
825
|
async checkFlag(options) {
|
|
659
826
|
const { fallback = false, key } = options;
|
|
660
827
|
const context = options.context || this.context;
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
828
|
+
const contextStr = contextString(context);
|
|
829
|
+
if (!this.useWebSocket) {
|
|
830
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
831
|
+
return fetch(requestUrl, {
|
|
832
|
+
method: "POST",
|
|
833
|
+
headers: {
|
|
834
|
+
...this.additionalHeaders ?? {},
|
|
835
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
836
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
837
|
+
},
|
|
838
|
+
body: JSON.stringify(context)
|
|
839
|
+
}).then((response) => {
|
|
840
|
+
if (!response.ok) {
|
|
841
|
+
throw new Error("Network response was not ok");
|
|
842
|
+
}
|
|
843
|
+
return response.json();
|
|
844
|
+
}).then((response) => {
|
|
845
|
+
return CheckFlagResponseFromJSON(response).data.value;
|
|
846
|
+
}).catch((error) => {
|
|
847
|
+
console.error("There was a problem with the fetch operation:", error);
|
|
848
|
+
return fallback;
|
|
849
|
+
});
|
|
664
850
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
851
|
+
try {
|
|
852
|
+
const existingVals = this.checks[contextStr];
|
|
853
|
+
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
|
854
|
+
return existingVals[key].value;
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
await this.setContext(context);
|
|
858
|
+
} catch (error) {
|
|
859
|
+
console.error(
|
|
860
|
+
"WebSocket connection failed, falling back to REST:",
|
|
861
|
+
error
|
|
862
|
+
);
|
|
863
|
+
return this.fallbackToRest(key, context, fallback);
|
|
864
|
+
}
|
|
865
|
+
const contextVals = this.checks[contextStr] ?? {};
|
|
866
|
+
return contextVals[key]?.value ?? fallback;
|
|
867
|
+
} catch (error) {
|
|
868
|
+
console.error("Unexpected error in checkFlag:", error);
|
|
869
|
+
return fallback;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Helper method for falling back to REST API when WebSocket connection fails
|
|
874
|
+
*/
|
|
875
|
+
async fallbackToRest(key, context, fallback) {
|
|
876
|
+
try {
|
|
877
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
878
|
+
const response = await fetch(requestUrl, {
|
|
879
|
+
method: "POST",
|
|
880
|
+
headers: {
|
|
881
|
+
...this.additionalHeaders ?? {},
|
|
882
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
883
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
884
|
+
},
|
|
885
|
+
body: JSON.stringify(context)
|
|
886
|
+
});
|
|
675
887
|
if (!response.ok) {
|
|
676
888
|
throw new Error("Network response was not ok");
|
|
677
889
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
console.error("There was a problem with the fetch operation:", error);
|
|
890
|
+
const data = CheckFlagResponseFromJSON(await response.json());
|
|
891
|
+
return data?.data?.value ?? false;
|
|
892
|
+
} catch (error) {
|
|
893
|
+
console.error("REST API call failed, using fallback value:", error);
|
|
683
894
|
return fallback;
|
|
684
|
-
}
|
|
895
|
+
}
|
|
685
896
|
}
|
|
686
|
-
|
|
897
|
+
/**
|
|
898
|
+
* Make an API call to fetch all flag values for a given context.
|
|
899
|
+
* Recommended for use in REST mode only.
|
|
900
|
+
*/
|
|
687
901
|
checkFlags = async (context) => {
|
|
688
902
|
context = context || this.context;
|
|
689
903
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
|
@@ -701,8 +915,9 @@ var Schematic = class {
|
|
|
701
915
|
throw new Error("Network response was not ok");
|
|
702
916
|
}
|
|
703
917
|
return response.json();
|
|
704
|
-
}).then((
|
|
705
|
-
|
|
918
|
+
}).then((responseJson) => {
|
|
919
|
+
const resp = CheckFlagsResponseFromJSON(responseJson);
|
|
920
|
+
return (resp?.data?.flags ?? []).reduce(
|
|
706
921
|
(accum, flag) => {
|
|
707
922
|
accum[flag.flag] = flag.value;
|
|
708
923
|
return accum;
|
|
@@ -711,21 +926,33 @@ var Schematic = class {
|
|
|
711
926
|
);
|
|
712
927
|
}).catch((error) => {
|
|
713
928
|
console.error("There was a problem with the fetch operation:", error);
|
|
714
|
-
return
|
|
929
|
+
return {};
|
|
715
930
|
});
|
|
716
931
|
};
|
|
717
|
-
|
|
932
|
+
/**
|
|
933
|
+
* Send an identify event.
|
|
934
|
+
* This will set the context for subsequent flag evaluation and events, and will also
|
|
935
|
+
* send an identify event to the Schematic API which will upsert a user and company.
|
|
936
|
+
*/
|
|
718
937
|
identify = (body) => {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
938
|
+
try {
|
|
939
|
+
this.setContext({
|
|
940
|
+
company: body.company?.keys,
|
|
941
|
+
user: body.keys
|
|
942
|
+
});
|
|
943
|
+
} catch (error) {
|
|
944
|
+
console.error("Error setting context:", error);
|
|
945
|
+
}
|
|
723
946
|
return this.handleEvent("identify", body);
|
|
724
947
|
};
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
948
|
+
/**
|
|
949
|
+
* Set the flag evaluation context.
|
|
950
|
+
* In WebSocket mode, this will:
|
|
951
|
+
* 1. Open a websocket connection if not already open
|
|
952
|
+
* 2. Send the context to the server
|
|
953
|
+
* 3. Wait for initial flag values to be returned
|
|
954
|
+
* The promise resolves when initial flag values are received.
|
|
955
|
+
*/
|
|
729
956
|
setContext = async (context) => {
|
|
730
957
|
if (!this.useWebSocket) {
|
|
731
958
|
this.context = context;
|
|
@@ -739,10 +966,14 @@ var Schematic = class {
|
|
|
739
966
|
const socket = await this.conn;
|
|
740
967
|
await this.wsSendMessage(socket, context);
|
|
741
968
|
} catch (error) {
|
|
742
|
-
console.error("
|
|
969
|
+
console.error("Failed to establish WebSocket connection:", error);
|
|
970
|
+
throw error;
|
|
743
971
|
}
|
|
744
972
|
};
|
|
745
|
-
|
|
973
|
+
/**
|
|
974
|
+
* Send a track event
|
|
975
|
+
* Track usage for a company and/or user.
|
|
976
|
+
*/
|
|
746
977
|
track = (body) => {
|
|
747
978
|
const { company, user, event, traits } = body;
|
|
748
979
|
return this.handleEvent("track", {
|
|
@@ -814,6 +1045,9 @@ var Schematic = class {
|
|
|
814
1045
|
/**
|
|
815
1046
|
* Websocket management
|
|
816
1047
|
*/
|
|
1048
|
+
/**
|
|
1049
|
+
* If using websocket mode, close the connection when done.
|
|
1050
|
+
*/
|
|
817
1051
|
cleanup = async () => {
|
|
818
1052
|
if (this.conn) {
|
|
819
1053
|
try {
|
|
@@ -854,18 +1088,15 @@ var Schematic = class {
|
|
|
854
1088
|
let resolved = false;
|
|
855
1089
|
const messageHandler = (event) => {
|
|
856
1090
|
const message = JSON.parse(event.data);
|
|
857
|
-
if (!(contextString(context) in this.
|
|
858
|
-
this.
|
|
859
|
-
}
|
|
860
|
-
(message.flags ?? []).forEach(
|
|
861
|
-
(flag) => {
|
|
862
|
-
this.values[contextString(context)][flag.flag] = flag.value;
|
|
863
|
-
this.notifyFlagValueListeners(flag.flag, flag.value);
|
|
864
|
-
}
|
|
865
|
-
);
|
|
866
|
-
if (this.flagListener) {
|
|
867
|
-
this.flagListener(this.getFlagValues());
|
|
1091
|
+
if (!(contextString(context) in this.checks)) {
|
|
1092
|
+
this.checks[contextString(context)] = {};
|
|
868
1093
|
}
|
|
1094
|
+
(message.flags ?? []).forEach((flag) => {
|
|
1095
|
+
const flagCheck = CheckFlagReturnFromJSON(flag);
|
|
1096
|
+
this.checks[contextString(context)][flagCheck.flag] = flagCheck;
|
|
1097
|
+
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
|
1098
|
+
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
|
1099
|
+
});
|
|
869
1100
|
this.setIsPending(false);
|
|
870
1101
|
if (!resolved) {
|
|
871
1102
|
resolved = true;
|
|
@@ -905,18 +1136,21 @@ var Schematic = class {
|
|
|
905
1136
|
setIsPending = (isPending) => {
|
|
906
1137
|
this.isPending = isPending;
|
|
907
1138
|
this.isPendingListeners.forEach(
|
|
908
|
-
(listener) =>
|
|
1139
|
+
(listener) => notifyPendingListener(listener, isPending)
|
|
909
1140
|
);
|
|
910
1141
|
};
|
|
1142
|
+
// flag checks state
|
|
1143
|
+
getFlagCheck = (flagKey) => {
|
|
1144
|
+
const contextStr = contextString(this.context);
|
|
1145
|
+
const checks = this.checks[contextStr] ?? {};
|
|
1146
|
+
return checks[flagKey];
|
|
1147
|
+
};
|
|
911
1148
|
// flagValues state
|
|
912
1149
|
getFlagValue = (flagKey) => {
|
|
913
|
-
const
|
|
914
|
-
return
|
|
915
|
-
};
|
|
916
|
-
getFlagValues = () => {
|
|
917
|
-
const contextStr = contextString(this.context);
|
|
918
|
-
return this.values[contextStr] ?? {};
|
|
1150
|
+
const check = this.getFlagCheck(flagKey);
|
|
1151
|
+
return check?.value;
|
|
919
1152
|
};
|
|
1153
|
+
/** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
|
|
920
1154
|
addFlagValueListener = (flagKey, listener) => {
|
|
921
1155
|
if (!(flagKey in this.flagValueListeners)) {
|
|
922
1156
|
this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
@@ -926,12 +1160,40 @@ var Schematic = class {
|
|
|
926
1160
|
this.flagValueListeners[flagKey].delete(listener);
|
|
927
1161
|
};
|
|
928
1162
|
};
|
|
1163
|
+
/** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
|
|
1164
|
+
addFlagCheckListener = (flagKey, listener) => {
|
|
1165
|
+
if (!(flagKey in this.flagCheckListeners)) {
|
|
1166
|
+
this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
1167
|
+
}
|
|
1168
|
+
this.flagCheckListeners[flagKey].add(listener);
|
|
1169
|
+
return () => {
|
|
1170
|
+
this.flagCheckListeners[flagKey].delete(listener);
|
|
1171
|
+
};
|
|
1172
|
+
};
|
|
1173
|
+
notifyFlagCheckListeners = (flagKey, check) => {
|
|
1174
|
+
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
1175
|
+
listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
|
|
1176
|
+
};
|
|
929
1177
|
notifyFlagValueListeners = (flagKey, value) => {
|
|
930
1178
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
|
931
|
-
listeners.forEach((listener) =>
|
|
1179
|
+
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
|
932
1180
|
};
|
|
933
1181
|
};
|
|
934
|
-
var
|
|
1182
|
+
var notifyPendingListener = (listener, value) => {
|
|
1183
|
+
if (listener.length > 0) {
|
|
1184
|
+
listener(value);
|
|
1185
|
+
} else {
|
|
1186
|
+
listener();
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
var notifyFlagCheckListener = (listener, value) => {
|
|
1190
|
+
if (listener.length > 0) {
|
|
1191
|
+
listener(value);
|
|
1192
|
+
} else {
|
|
1193
|
+
listener();
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
var notifyFlagValueListener = (listener, value) => {
|
|
935
1197
|
if (listener.length > 0) {
|
|
936
1198
|
listener(value);
|
|
937
1199
|
} else {
|