@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.esm.js
CHANGED
|
@@ -29,11 +29,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
29
29
|
"node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
|
|
30
30
|
(function(self2) {
|
|
31
31
|
var irrelevant = function(exports2) {
|
|
32
|
-
var
|
|
32
|
+
var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
|
|
33
|
+
typeof global !== "undefined" && global || {};
|
|
33
34
|
var support = {
|
|
34
|
-
searchParams: "URLSearchParams" in
|
|
35
|
-
iterable: "Symbol" in
|
|
36
|
-
blob: "FileReader" in
|
|
35
|
+
searchParams: "URLSearchParams" in g,
|
|
36
|
+
iterable: "Symbol" in g && "iterator" in Symbol,
|
|
37
|
+
blob: "FileReader" in g && "Blob" in g && function() {
|
|
37
38
|
try {
|
|
38
39
|
new Blob();
|
|
39
40
|
return true;
|
|
@@ -41,8 +42,8 @@ var require_browser_polyfill = __commonJS({
|
|
|
41
42
|
return false;
|
|
42
43
|
}
|
|
43
44
|
}(),
|
|
44
|
-
formData: "FormData" in
|
|
45
|
-
arrayBuffer: "ArrayBuffer" in
|
|
45
|
+
formData: "FormData" in g,
|
|
46
|
+
arrayBuffer: "ArrayBuffer" in g
|
|
46
47
|
};
|
|
47
48
|
function isDataView(obj) {
|
|
48
49
|
return obj && DataView.prototype.isPrototypeOf(obj);
|
|
@@ -100,6 +101,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
100
101
|
}, this);
|
|
101
102
|
} else if (Array.isArray(headers)) {
|
|
102
103
|
headers.forEach(function(header) {
|
|
104
|
+
if (header.length != 2) {
|
|
105
|
+
throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
|
|
106
|
+
}
|
|
103
107
|
this.append(header[0], header[1]);
|
|
104
108
|
}, this);
|
|
105
109
|
} else if (headers) {
|
|
@@ -159,6 +163,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
159
163
|
Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
|
|
160
164
|
}
|
|
161
165
|
function consumed(body) {
|
|
166
|
+
if (body._noBody) return;
|
|
162
167
|
if (body.bodyUsed) {
|
|
163
168
|
return Promise.reject(new TypeError("Already read"));
|
|
164
169
|
}
|
|
@@ -183,7 +188,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
183
188
|
function readBlobAsText(blob) {
|
|
184
189
|
var reader = new FileReader();
|
|
185
190
|
var promise = fileReaderReady(reader);
|
|
186
|
-
|
|
191
|
+
var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
|
|
192
|
+
var encoding = match ? match[1] : "utf-8";
|
|
193
|
+
reader.readAsText(blob, encoding);
|
|
187
194
|
return promise;
|
|
188
195
|
}
|
|
189
196
|
function readArrayBufferAsText(buf) {
|
|
@@ -209,6 +216,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
209
216
|
this.bodyUsed = this.bodyUsed;
|
|
210
217
|
this._bodyInit = body;
|
|
211
218
|
if (!body) {
|
|
219
|
+
this._noBody = true;
|
|
212
220
|
this._bodyText = "";
|
|
213
221
|
} else if (typeof body === "string") {
|
|
214
222
|
this._bodyText = body;
|
|
@@ -252,27 +260,28 @@ var require_browser_polyfill = __commonJS({
|
|
|
252
260
|
return Promise.resolve(new Blob([this._bodyText]));
|
|
253
261
|
}
|
|
254
262
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
} else {
|
|
269
|
-
return Promise.resolve(this._bodyArrayBuffer);
|
|
270
|
-
}
|
|
263
|
+
}
|
|
264
|
+
this.arrayBuffer = function() {
|
|
265
|
+
if (this._bodyArrayBuffer) {
|
|
266
|
+
var isConsumed = consumed(this);
|
|
267
|
+
if (isConsumed) {
|
|
268
|
+
return isConsumed;
|
|
269
|
+
} else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
|
|
270
|
+
return Promise.resolve(
|
|
271
|
+
this._bodyArrayBuffer.buffer.slice(
|
|
272
|
+
this._bodyArrayBuffer.byteOffset,
|
|
273
|
+
this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
|
|
274
|
+
)
|
|
275
|
+
);
|
|
271
276
|
} else {
|
|
272
|
-
return
|
|
277
|
+
return Promise.resolve(this._bodyArrayBuffer);
|
|
273
278
|
}
|
|
274
|
-
}
|
|
275
|
-
|
|
279
|
+
} else if (support.blob) {
|
|
280
|
+
return this.blob().then(readBlobAsArrayBuffer);
|
|
281
|
+
} else {
|
|
282
|
+
throw new Error("could not read as ArrayBuffer");
|
|
283
|
+
}
|
|
284
|
+
};
|
|
276
285
|
this.text = function() {
|
|
277
286
|
var rejected = consumed(this);
|
|
278
287
|
if (rejected) {
|
|
@@ -298,7 +307,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
298
307
|
};
|
|
299
308
|
return this;
|
|
300
309
|
}
|
|
301
|
-
var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"];
|
|
310
|
+
var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
|
|
302
311
|
function normalizeMethod(method) {
|
|
303
312
|
var upcased = method.toUpperCase();
|
|
304
313
|
return methods.indexOf(upcased) > -1 ? upcased : method;
|
|
@@ -334,7 +343,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
334
343
|
}
|
|
335
344
|
this.method = normalizeMethod(options.method || this.method || "GET");
|
|
336
345
|
this.mode = options.mode || this.mode || null;
|
|
337
|
-
this.signal = options.signal || this.signal
|
|
346
|
+
this.signal = options.signal || this.signal || function() {
|
|
347
|
+
if ("AbortController" in g) {
|
|
348
|
+
var ctrl = new AbortController();
|
|
349
|
+
return ctrl.signal;
|
|
350
|
+
}
|
|
351
|
+
}();
|
|
338
352
|
this.referrer = null;
|
|
339
353
|
if ((this.method === "GET" || this.method === "HEAD") && body) {
|
|
340
354
|
throw new TypeError("Body not allowed for GET or HEAD requests");
|
|
@@ -377,7 +391,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
377
391
|
var key = parts.shift().trim();
|
|
378
392
|
if (key) {
|
|
379
393
|
var value = parts.join(":").trim();
|
|
380
|
-
|
|
394
|
+
try {
|
|
395
|
+
headers.append(key, value);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
console.warn("Response " + error.message);
|
|
398
|
+
}
|
|
381
399
|
}
|
|
382
400
|
});
|
|
383
401
|
return headers;
|
|
@@ -392,6 +410,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
392
410
|
}
|
|
393
411
|
this.type = "default";
|
|
394
412
|
this.status = options.status === void 0 ? 200 : options.status;
|
|
413
|
+
if (this.status < 200 || this.status > 599) {
|
|
414
|
+
throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
|
|
415
|
+
}
|
|
395
416
|
this.ok = this.status >= 200 && this.status < 300;
|
|
396
417
|
this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
|
|
397
418
|
this.headers = new Headers(options.headers);
|
|
@@ -408,7 +429,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
408
429
|
});
|
|
409
430
|
};
|
|
410
431
|
Response.error = function() {
|
|
411
|
-
var response = new Response(null, { status:
|
|
432
|
+
var response = new Response(null, { status: 200, statusText: "" });
|
|
433
|
+
response.ok = false;
|
|
434
|
+
response.status = 0;
|
|
412
435
|
response.type = "error";
|
|
413
436
|
return response;
|
|
414
437
|
};
|
|
@@ -419,7 +442,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
419
442
|
}
|
|
420
443
|
return new Response(null, { status, headers: { location: url } });
|
|
421
444
|
};
|
|
422
|
-
exports2.DOMException =
|
|
445
|
+
exports2.DOMException = g.DOMException;
|
|
423
446
|
try {
|
|
424
447
|
new exports2.DOMException();
|
|
425
448
|
} catch (err) {
|
|
@@ -444,10 +467,14 @@ var require_browser_polyfill = __commonJS({
|
|
|
444
467
|
}
|
|
445
468
|
xhr.onload = function() {
|
|
446
469
|
var options = {
|
|
447
|
-
status: xhr.status,
|
|
448
470
|
statusText: xhr.statusText,
|
|
449
471
|
headers: parseHeaders(xhr.getAllResponseHeaders() || "")
|
|
450
472
|
};
|
|
473
|
+
if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
|
|
474
|
+
options.status = 200;
|
|
475
|
+
} else {
|
|
476
|
+
options.status = xhr.status;
|
|
477
|
+
}
|
|
451
478
|
options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
|
|
452
479
|
var body = "response" in xhr ? xhr.response : xhr.responseText;
|
|
453
480
|
setTimeout(function() {
|
|
@@ -461,7 +488,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
461
488
|
};
|
|
462
489
|
xhr.ontimeout = function() {
|
|
463
490
|
setTimeout(function() {
|
|
464
|
-
reject(new TypeError("Network request
|
|
491
|
+
reject(new TypeError("Network request timed out"));
|
|
465
492
|
}, 0);
|
|
466
493
|
};
|
|
467
494
|
xhr.onabort = function() {
|
|
@@ -471,7 +498,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
471
498
|
};
|
|
472
499
|
function fixUrl(url) {
|
|
473
500
|
try {
|
|
474
|
-
return url === "" &&
|
|
501
|
+
return url === "" && g.location.href ? g.location.href : url;
|
|
475
502
|
} catch (e) {
|
|
476
503
|
return url;
|
|
477
504
|
}
|
|
@@ -485,14 +512,21 @@ var require_browser_polyfill = __commonJS({
|
|
|
485
512
|
if ("responseType" in xhr) {
|
|
486
513
|
if (support.blob) {
|
|
487
514
|
xhr.responseType = "blob";
|
|
488
|
-
} else if (support.arrayBuffer
|
|
515
|
+
} else if (support.arrayBuffer) {
|
|
489
516
|
xhr.responseType = "arraybuffer";
|
|
490
517
|
}
|
|
491
518
|
}
|
|
492
|
-
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers)) {
|
|
519
|
+
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
|
|
520
|
+
var names = [];
|
|
493
521
|
Object.getOwnPropertyNames(init.headers).forEach(function(name) {
|
|
522
|
+
names.push(normalizeName(name));
|
|
494
523
|
xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
|
|
495
524
|
});
|
|
525
|
+
request.headers.forEach(function(value, name) {
|
|
526
|
+
if (names.indexOf(name) === -1) {
|
|
527
|
+
xhr.setRequestHeader(name, value);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
496
530
|
} else {
|
|
497
531
|
request.headers.forEach(function(value, name) {
|
|
498
532
|
xhr.setRequestHeader(name, value);
|
|
@@ -510,11 +544,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
510
544
|
});
|
|
511
545
|
}
|
|
512
546
|
fetch2.polyfill = true;
|
|
513
|
-
if (!
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
547
|
+
if (!g.fetch) {
|
|
548
|
+
g.fetch = fetch2;
|
|
549
|
+
g.Headers = Headers;
|
|
550
|
+
g.Request = Request;
|
|
551
|
+
g.Response = Response;
|
|
518
552
|
}
|
|
519
553
|
exports2.Headers = Headers;
|
|
520
554
|
exports2.Request = Request;
|
|
@@ -528,10 +562,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
528
562
|
|
|
529
563
|
// node_modules/uuid/dist/esm-browser/stringify.js
|
|
530
564
|
var byteToHex = [];
|
|
531
|
-
for (i = 0; i < 256; ++i) {
|
|
565
|
+
for (let i = 0; i < 256; ++i) {
|
|
532
566
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
533
567
|
}
|
|
534
|
-
var i;
|
|
535
568
|
function unsafeStringify(arr, offset = 0) {
|
|
536
569
|
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();
|
|
537
570
|
}
|
|
@@ -541,19 +574,17 @@ var getRandomValues;
|
|
|
541
574
|
var rnds8 = new Uint8Array(16);
|
|
542
575
|
function rng() {
|
|
543
576
|
if (!getRandomValues) {
|
|
544
|
-
|
|
545
|
-
if (!getRandomValues) {
|
|
577
|
+
if (typeof crypto === "undefined" || !crypto.getRandomValues) {
|
|
546
578
|
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
547
579
|
}
|
|
580
|
+
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
548
581
|
}
|
|
549
582
|
return getRandomValues(rnds8);
|
|
550
583
|
}
|
|
551
584
|
|
|
552
585
|
// node_modules/uuid/dist/esm-browser/native.js
|
|
553
586
|
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
554
|
-
var native_default = {
|
|
555
|
-
randomUUID
|
|
556
|
-
};
|
|
587
|
+
var native_default = { randomUUID };
|
|
557
588
|
|
|
558
589
|
// node_modules/uuid/dist/esm-browser/v4.js
|
|
559
590
|
function v4(options, buf, offset) {
|
|
@@ -561,12 +592,18 @@ function v4(options, buf, offset) {
|
|
|
561
592
|
return native_default.randomUUID();
|
|
562
593
|
}
|
|
563
594
|
options = options || {};
|
|
564
|
-
|
|
595
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
596
|
+
if (rnds.length < 16) {
|
|
597
|
+
throw new Error("Random bytes length must be >= 16");
|
|
598
|
+
}
|
|
565
599
|
rnds[6] = rnds[6] & 15 | 64;
|
|
566
600
|
rnds[8] = rnds[8] & 63 | 128;
|
|
567
601
|
if (buf) {
|
|
568
602
|
offset = offset || 0;
|
|
569
|
-
|
|
603
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
604
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
605
|
+
}
|
|
606
|
+
for (let i = 0; i < 16; ++i) {
|
|
570
607
|
buf[offset + i] = rnds[i];
|
|
571
608
|
}
|
|
572
609
|
return buf;
|
|
@@ -578,6 +615,127 @@ var v4_default = v4;
|
|
|
578
615
|
// src/index.ts
|
|
579
616
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
580
617
|
|
|
618
|
+
// src/types/api/models/CheckFlagResponseData.ts
|
|
619
|
+
function CheckFlagResponseDataFromJSON(json) {
|
|
620
|
+
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
621
|
+
}
|
|
622
|
+
function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
623
|
+
if (json == null) {
|
|
624
|
+
return json;
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
companyId: json["company_id"] == null ? void 0 : json["company_id"],
|
|
628
|
+
error: json["error"] == null ? void 0 : json["error"],
|
|
629
|
+
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
630
|
+
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
631
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
632
|
+
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
633
|
+
flag: json["flag"],
|
|
634
|
+
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
635
|
+
reason: json["reason"],
|
|
636
|
+
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
637
|
+
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
638
|
+
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
639
|
+
value: json["value"]
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// src/types/api/models/CheckFlagResponse.ts
|
|
644
|
+
function CheckFlagResponseFromJSON(json) {
|
|
645
|
+
return CheckFlagResponseFromJSONTyped(json, false);
|
|
646
|
+
}
|
|
647
|
+
function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
648
|
+
if (json == null) {
|
|
649
|
+
return json;
|
|
650
|
+
}
|
|
651
|
+
return {
|
|
652
|
+
data: CheckFlagResponseDataFromJSON(json["data"]),
|
|
653
|
+
params: json["params"]
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/types/api/models/CheckFlagsResponseData.ts
|
|
658
|
+
function CheckFlagsResponseDataFromJSON(json) {
|
|
659
|
+
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
660
|
+
}
|
|
661
|
+
function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
662
|
+
if (json == null) {
|
|
663
|
+
return json;
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
flags: json["flags"].map(CheckFlagResponseDataFromJSON)
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/types/api/models/CheckFlagsResponse.ts
|
|
671
|
+
function CheckFlagsResponseFromJSON(json) {
|
|
672
|
+
return CheckFlagsResponseFromJSONTyped(json, false);
|
|
673
|
+
}
|
|
674
|
+
function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
675
|
+
if (json == null) {
|
|
676
|
+
return json;
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
data: CheckFlagsResponseDataFromJSON(json["data"]),
|
|
680
|
+
params: json["params"]
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// src/types/index.ts
|
|
685
|
+
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
686
|
+
RuleType2["GLOBAL_OVERRIDE"] = "global_override";
|
|
687
|
+
RuleType2["COMPANY_OVERRIDE"] = "company_override";
|
|
688
|
+
RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
|
|
689
|
+
RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
|
|
690
|
+
RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
|
|
691
|
+
RuleType2["STANDARD"] = "standard";
|
|
692
|
+
RuleType2["DEFAULT"] = "default";
|
|
693
|
+
return RuleType2;
|
|
694
|
+
})(RuleType || {});
|
|
695
|
+
var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
|
|
696
|
+
UsagePeriod2["ALL_TIME"] = "all_time";
|
|
697
|
+
UsagePeriod2["CURRENT_DAY"] = "current_day";
|
|
698
|
+
UsagePeriod2["CURRENT_MONTH"] = "current_month";
|
|
699
|
+
UsagePeriod2["CURRENT_WEEK"] = "current_week";
|
|
700
|
+
return UsagePeriod2;
|
|
701
|
+
})(UsagePeriod || {});
|
|
702
|
+
var CheckFlagReturnFromJSON = (json) => {
|
|
703
|
+
const {
|
|
704
|
+
companyId,
|
|
705
|
+
error,
|
|
706
|
+
featureAllocation,
|
|
707
|
+
featureUsage,
|
|
708
|
+
featureUsagePeriod,
|
|
709
|
+
featureUsageResetAt,
|
|
710
|
+
flag,
|
|
711
|
+
flagId,
|
|
712
|
+
reason,
|
|
713
|
+
ruleId,
|
|
714
|
+
ruleType,
|
|
715
|
+
userId,
|
|
716
|
+
value
|
|
717
|
+
} = CheckFlagResponseDataFromJSON(json);
|
|
718
|
+
const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
|
|
719
|
+
(ruleType == "company_override_usage_exceeded" /* COMPANY_OVERRIDE_USAGE_EXCEEDED */ || // if the rule type is one of these, then we have exceeded usage
|
|
720
|
+
ruleType == "plan_entitlement_usage_exceeded" /* PLAN_ENTITLEMENT_USAGE_EXCEEDED */);
|
|
721
|
+
return {
|
|
722
|
+
featureUsageExceeded,
|
|
723
|
+
companyId: companyId == null ? void 0 : companyId,
|
|
724
|
+
error: error == null ? void 0 : error,
|
|
725
|
+
featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
|
|
726
|
+
featureUsage: featureUsage == null ? void 0 : featureUsage,
|
|
727
|
+
featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
|
|
728
|
+
featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
|
|
729
|
+
flag,
|
|
730
|
+
flagId: flagId == null ? void 0 : flagId,
|
|
731
|
+
reason,
|
|
732
|
+
ruleId: ruleId == null ? void 0 : ruleId,
|
|
733
|
+
ruleType: ruleType == null ? void 0 : ruleType,
|
|
734
|
+
userId: userId == null ? void 0 : userId,
|
|
735
|
+
value
|
|
736
|
+
};
|
|
737
|
+
};
|
|
738
|
+
|
|
581
739
|
// src/utils.ts
|
|
582
740
|
function contextString(context) {
|
|
583
741
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
@@ -604,19 +762,18 @@ var Schematic = class {
|
|
|
604
762
|
context = {};
|
|
605
763
|
eventQueue;
|
|
606
764
|
eventUrl = "https://c.schematichq.com";
|
|
607
|
-
|
|
765
|
+
flagCheckListeners = {};
|
|
608
766
|
flagValueListeners = {};
|
|
609
767
|
isPending = true;
|
|
610
768
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
611
769
|
storage;
|
|
612
770
|
useWebSocket = false;
|
|
613
|
-
|
|
771
|
+
checks = {};
|
|
614
772
|
webSocketUrl = "wss://api.schematichq.com";
|
|
615
773
|
constructor(apiKey, options) {
|
|
616
774
|
this.apiKey = apiKey;
|
|
617
775
|
this.eventQueue = [];
|
|
618
776
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
619
|
-
this.flagListener = options?.flagListener;
|
|
620
777
|
if (options?.additionalHeaders) {
|
|
621
778
|
this.additionalHeaders = options.additionalHeaders;
|
|
622
779
|
}
|
|
@@ -640,37 +797,89 @@ var Schematic = class {
|
|
|
640
797
|
});
|
|
641
798
|
}
|
|
642
799
|
}
|
|
643
|
-
|
|
644
|
-
|
|
800
|
+
/**
|
|
801
|
+
* Get value for a single flag.
|
|
802
|
+
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
803
|
+
* new connection and then returns the requestedvalue. Falls back to REST API if WebSocket
|
|
804
|
+
* connection fails.
|
|
805
|
+
* In REST mode, makes an API call for each check.
|
|
806
|
+
*/
|
|
645
807
|
async checkFlag(options) {
|
|
646
808
|
const { fallback = false, key } = options;
|
|
647
809
|
const context = options.context || this.context;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
810
|
+
const contextStr = contextString(context);
|
|
811
|
+
if (!this.useWebSocket) {
|
|
812
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
813
|
+
return fetch(requestUrl, {
|
|
814
|
+
method: "POST",
|
|
815
|
+
headers: {
|
|
816
|
+
...this.additionalHeaders ?? {},
|
|
817
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
818
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
819
|
+
},
|
|
820
|
+
body: JSON.stringify(context)
|
|
821
|
+
}).then((response) => {
|
|
822
|
+
if (!response.ok) {
|
|
823
|
+
throw new Error("Network response was not ok");
|
|
824
|
+
}
|
|
825
|
+
return response.json();
|
|
826
|
+
}).then((response) => {
|
|
827
|
+
return CheckFlagResponseFromJSON(response).data.value;
|
|
828
|
+
}).catch((error) => {
|
|
829
|
+
console.error("There was a problem with the fetch operation:", error);
|
|
830
|
+
return fallback;
|
|
831
|
+
});
|
|
651
832
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
833
|
+
try {
|
|
834
|
+
const existingVals = this.checks[contextStr];
|
|
835
|
+
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
|
836
|
+
return existingVals[key].value;
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
await this.setContext(context);
|
|
840
|
+
} catch (error) {
|
|
841
|
+
console.error(
|
|
842
|
+
"WebSocket connection failed, falling back to REST:",
|
|
843
|
+
error
|
|
844
|
+
);
|
|
845
|
+
return this.fallbackToRest(key, context, fallback);
|
|
846
|
+
}
|
|
847
|
+
const contextVals = this.checks[contextStr] ?? {};
|
|
848
|
+
return contextVals[key]?.value ?? fallback;
|
|
849
|
+
} catch (error) {
|
|
850
|
+
console.error("Unexpected error in checkFlag:", error);
|
|
851
|
+
return fallback;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Helper method for falling back to REST API when WebSocket connection fails
|
|
856
|
+
*/
|
|
857
|
+
async fallbackToRest(key, context, fallback) {
|
|
858
|
+
try {
|
|
859
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
860
|
+
const response = await fetch(requestUrl, {
|
|
861
|
+
method: "POST",
|
|
862
|
+
headers: {
|
|
863
|
+
...this.additionalHeaders ?? {},
|
|
864
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
865
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
866
|
+
},
|
|
867
|
+
body: JSON.stringify(context)
|
|
868
|
+
});
|
|
662
869
|
if (!response.ok) {
|
|
663
870
|
throw new Error("Network response was not ok");
|
|
664
871
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
console.error("There was a problem with the fetch operation:", error);
|
|
872
|
+
const data = CheckFlagResponseFromJSON(await response.json());
|
|
873
|
+
return data?.data?.value ?? false;
|
|
874
|
+
} catch (error) {
|
|
875
|
+
console.error("REST API call failed, using fallback value:", error);
|
|
670
876
|
return fallback;
|
|
671
|
-
}
|
|
877
|
+
}
|
|
672
878
|
}
|
|
673
|
-
|
|
879
|
+
/**
|
|
880
|
+
* Make an API call to fetch all flag values for a given context.
|
|
881
|
+
* Recommended for use in REST mode only.
|
|
882
|
+
*/
|
|
674
883
|
checkFlags = async (context) => {
|
|
675
884
|
context = context || this.context;
|
|
676
885
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
|
@@ -688,8 +897,9 @@ var Schematic = class {
|
|
|
688
897
|
throw new Error("Network response was not ok");
|
|
689
898
|
}
|
|
690
899
|
return response.json();
|
|
691
|
-
}).then((
|
|
692
|
-
|
|
900
|
+
}).then((responseJson) => {
|
|
901
|
+
const resp = CheckFlagsResponseFromJSON(responseJson);
|
|
902
|
+
return (resp?.data?.flags ?? []).reduce(
|
|
693
903
|
(accum, flag) => {
|
|
694
904
|
accum[flag.flag] = flag.value;
|
|
695
905
|
return accum;
|
|
@@ -698,21 +908,33 @@ var Schematic = class {
|
|
|
698
908
|
);
|
|
699
909
|
}).catch((error) => {
|
|
700
910
|
console.error("There was a problem with the fetch operation:", error);
|
|
701
|
-
return
|
|
911
|
+
return {};
|
|
702
912
|
});
|
|
703
913
|
};
|
|
704
|
-
|
|
914
|
+
/**
|
|
915
|
+
* Send an identify event.
|
|
916
|
+
* This will set the context for subsequent flag evaluation and events, and will also
|
|
917
|
+
* send an identify event to the Schematic API which will upsert a user and company.
|
|
918
|
+
*/
|
|
705
919
|
identify = (body) => {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
920
|
+
try {
|
|
921
|
+
this.setContext({
|
|
922
|
+
company: body.company?.keys,
|
|
923
|
+
user: body.keys
|
|
924
|
+
});
|
|
925
|
+
} catch (error) {
|
|
926
|
+
console.error("Error setting context:", error);
|
|
927
|
+
}
|
|
710
928
|
return this.handleEvent("identify", body);
|
|
711
929
|
};
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
930
|
+
/**
|
|
931
|
+
* Set the flag evaluation context.
|
|
932
|
+
* In WebSocket mode, this will:
|
|
933
|
+
* 1. Open a websocket connection if not already open
|
|
934
|
+
* 2. Send the context to the server
|
|
935
|
+
* 3. Wait for initial flag values to be returned
|
|
936
|
+
* The promise resolves when initial flag values are received.
|
|
937
|
+
*/
|
|
716
938
|
setContext = async (context) => {
|
|
717
939
|
if (!this.useWebSocket) {
|
|
718
940
|
this.context = context;
|
|
@@ -726,10 +948,14 @@ var Schematic = class {
|
|
|
726
948
|
const socket = await this.conn;
|
|
727
949
|
await this.wsSendMessage(socket, context);
|
|
728
950
|
} catch (error) {
|
|
729
|
-
console.error("
|
|
951
|
+
console.error("Failed to establish WebSocket connection:", error);
|
|
952
|
+
throw error;
|
|
730
953
|
}
|
|
731
954
|
};
|
|
732
|
-
|
|
955
|
+
/**
|
|
956
|
+
* Send a track event
|
|
957
|
+
* Track usage for a company and/or user.
|
|
958
|
+
*/
|
|
733
959
|
track = (body) => {
|
|
734
960
|
const { company, user, event, traits } = body;
|
|
735
961
|
return this.handleEvent("track", {
|
|
@@ -801,6 +1027,9 @@ var Schematic = class {
|
|
|
801
1027
|
/**
|
|
802
1028
|
* Websocket management
|
|
803
1029
|
*/
|
|
1030
|
+
/**
|
|
1031
|
+
* If using websocket mode, close the connection when done.
|
|
1032
|
+
*/
|
|
804
1033
|
cleanup = async () => {
|
|
805
1034
|
if (this.conn) {
|
|
806
1035
|
try {
|
|
@@ -841,18 +1070,15 @@ var Schematic = class {
|
|
|
841
1070
|
let resolved = false;
|
|
842
1071
|
const messageHandler = (event) => {
|
|
843
1072
|
const message = JSON.parse(event.data);
|
|
844
|
-
if (!(contextString(context) in this.
|
|
845
|
-
this.
|
|
846
|
-
}
|
|
847
|
-
(message.flags ?? []).forEach(
|
|
848
|
-
(flag) => {
|
|
849
|
-
this.values[contextString(context)][flag.flag] = flag.value;
|
|
850
|
-
this.notifyFlagValueListeners(flag.flag, flag.value);
|
|
851
|
-
}
|
|
852
|
-
);
|
|
853
|
-
if (this.flagListener) {
|
|
854
|
-
this.flagListener(this.getFlagValues());
|
|
1073
|
+
if (!(contextString(context) in this.checks)) {
|
|
1074
|
+
this.checks[contextString(context)] = {};
|
|
855
1075
|
}
|
|
1076
|
+
(message.flags ?? []).forEach((flag) => {
|
|
1077
|
+
const flagCheck = CheckFlagReturnFromJSON(flag);
|
|
1078
|
+
this.checks[contextString(context)][flagCheck.flag] = flagCheck;
|
|
1079
|
+
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
|
1080
|
+
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
|
1081
|
+
});
|
|
856
1082
|
this.setIsPending(false);
|
|
857
1083
|
if (!resolved) {
|
|
858
1084
|
resolved = true;
|
|
@@ -892,18 +1118,21 @@ var Schematic = class {
|
|
|
892
1118
|
setIsPending = (isPending) => {
|
|
893
1119
|
this.isPending = isPending;
|
|
894
1120
|
this.isPendingListeners.forEach(
|
|
895
|
-
(listener) =>
|
|
1121
|
+
(listener) => notifyPendingListener(listener, isPending)
|
|
896
1122
|
);
|
|
897
1123
|
};
|
|
1124
|
+
// flag checks state
|
|
1125
|
+
getFlagCheck = (flagKey) => {
|
|
1126
|
+
const contextStr = contextString(this.context);
|
|
1127
|
+
const checks = this.checks[contextStr] ?? {};
|
|
1128
|
+
return checks[flagKey];
|
|
1129
|
+
};
|
|
898
1130
|
// flagValues state
|
|
899
1131
|
getFlagValue = (flagKey) => {
|
|
900
|
-
const
|
|
901
|
-
return
|
|
902
|
-
};
|
|
903
|
-
getFlagValues = () => {
|
|
904
|
-
const contextStr = contextString(this.context);
|
|
905
|
-
return this.values[contextStr] ?? {};
|
|
1132
|
+
const check = this.getFlagCheck(flagKey);
|
|
1133
|
+
return check?.value;
|
|
906
1134
|
};
|
|
1135
|
+
/** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
|
|
907
1136
|
addFlagValueListener = (flagKey, listener) => {
|
|
908
1137
|
if (!(flagKey in this.flagValueListeners)) {
|
|
909
1138
|
this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
@@ -913,12 +1142,40 @@ var Schematic = class {
|
|
|
913
1142
|
this.flagValueListeners[flagKey].delete(listener);
|
|
914
1143
|
};
|
|
915
1144
|
};
|
|
1145
|
+
/** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
|
|
1146
|
+
addFlagCheckListener = (flagKey, listener) => {
|
|
1147
|
+
if (!(flagKey in this.flagCheckListeners)) {
|
|
1148
|
+
this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
1149
|
+
}
|
|
1150
|
+
this.flagCheckListeners[flagKey].add(listener);
|
|
1151
|
+
return () => {
|
|
1152
|
+
this.flagCheckListeners[flagKey].delete(listener);
|
|
1153
|
+
};
|
|
1154
|
+
};
|
|
1155
|
+
notifyFlagCheckListeners = (flagKey, check) => {
|
|
1156
|
+
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
1157
|
+
listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
|
|
1158
|
+
};
|
|
916
1159
|
notifyFlagValueListeners = (flagKey, value) => {
|
|
917
1160
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
|
918
|
-
listeners.forEach((listener) =>
|
|
1161
|
+
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
|
919
1162
|
};
|
|
920
1163
|
};
|
|
921
|
-
var
|
|
1164
|
+
var notifyPendingListener = (listener, value) => {
|
|
1165
|
+
if (listener.length > 0) {
|
|
1166
|
+
listener(value);
|
|
1167
|
+
} else {
|
|
1168
|
+
listener();
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
var notifyFlagCheckListener = (listener, value) => {
|
|
1172
|
+
if (listener.length > 0) {
|
|
1173
|
+
listener(value);
|
|
1174
|
+
} else {
|
|
1175
|
+
listener();
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
var notifyFlagValueListener = (listener, value) => {
|
|
922
1179
|
if (listener.length > 0) {
|
|
923
1180
|
listener(value);
|
|
924
1181
|
} else {
|
|
@@ -926,6 +1183,11 @@ var notifyListener = (listener, value) => {
|
|
|
926
1183
|
}
|
|
927
1184
|
};
|
|
928
1185
|
export {
|
|
929
|
-
|
|
1186
|
+
CheckFlagResponseFromJSON,
|
|
1187
|
+
CheckFlagReturnFromJSON,
|
|
1188
|
+
CheckFlagsResponseFromJSON,
|
|
1189
|
+
RuleType,
|
|
1190
|
+
Schematic,
|
|
1191
|
+
UsagePeriod
|
|
930
1192
|
};
|
|
931
1193
|
/* @preserve */
|