@schematichq/schematic-vue 0.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.
@@ -0,0 +1,1669 @@
1
+ // node_modules/@schematichq/schematic-js/dist/schematic.esm.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var require_browser_polyfill = __commonJS({
28
+ "node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
29
+ (function(self2) {
30
+ var irrelevant = (function(exports2) {
31
+ var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
32
+ typeof global !== "undefined" && global || {};
33
+ var support = {
34
+ searchParams: "URLSearchParams" in g,
35
+ iterable: "Symbol" in g && "iterator" in Symbol,
36
+ blob: "FileReader" in g && "Blob" in g && (function() {
37
+ try {
38
+ new Blob();
39
+ return true;
40
+ } catch (e) {
41
+ return false;
42
+ }
43
+ })(),
44
+ formData: "FormData" in g,
45
+ arrayBuffer: "ArrayBuffer" in g
46
+ };
47
+ function isDataView(obj) {
48
+ return obj && DataView.prototype.isPrototypeOf(obj);
49
+ }
50
+ if (support.arrayBuffer) {
51
+ var viewClasses = [
52
+ "[object Int8Array]",
53
+ "[object Uint8Array]",
54
+ "[object Uint8ClampedArray]",
55
+ "[object Int16Array]",
56
+ "[object Uint16Array]",
57
+ "[object Int32Array]",
58
+ "[object Uint32Array]",
59
+ "[object Float32Array]",
60
+ "[object Float64Array]"
61
+ ];
62
+ var isArrayBufferView = ArrayBuffer.isView || function(obj) {
63
+ return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
64
+ };
65
+ }
66
+ function normalizeName(name) {
67
+ if (typeof name !== "string") {
68
+ name = String(name);
69
+ }
70
+ if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === "") {
71
+ throw new TypeError('Invalid character in header field name: "' + name + '"');
72
+ }
73
+ return name.toLowerCase();
74
+ }
75
+ function normalizeValue(value) {
76
+ if (typeof value !== "string") {
77
+ value = String(value);
78
+ }
79
+ return value;
80
+ }
81
+ function iteratorFor(items) {
82
+ var iterator = {
83
+ next: function() {
84
+ var value = items.shift();
85
+ return { done: value === void 0, value };
86
+ }
87
+ };
88
+ if (support.iterable) {
89
+ iterator[Symbol.iterator] = function() {
90
+ return iterator;
91
+ };
92
+ }
93
+ return iterator;
94
+ }
95
+ function Headers(headers) {
96
+ this.map = {};
97
+ if (headers instanceof Headers) {
98
+ headers.forEach(function(value, name) {
99
+ this.append(name, value);
100
+ }, this);
101
+ } else if (Array.isArray(headers)) {
102
+ headers.forEach(function(header) {
103
+ if (header.length != 2) {
104
+ throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
105
+ }
106
+ this.append(header[0], header[1]);
107
+ }, this);
108
+ } else if (headers) {
109
+ Object.getOwnPropertyNames(headers).forEach(function(name) {
110
+ this.append(name, headers[name]);
111
+ }, this);
112
+ }
113
+ }
114
+ Headers.prototype.append = function(name, value) {
115
+ name = normalizeName(name);
116
+ value = normalizeValue(value);
117
+ var oldValue = this.map[name];
118
+ this.map[name] = oldValue ? oldValue + ", " + value : value;
119
+ };
120
+ Headers.prototype["delete"] = function(name) {
121
+ delete this.map[normalizeName(name)];
122
+ };
123
+ Headers.prototype.get = function(name) {
124
+ name = normalizeName(name);
125
+ return this.has(name) ? this.map[name] : null;
126
+ };
127
+ Headers.prototype.has = function(name) {
128
+ return this.map.hasOwnProperty(normalizeName(name));
129
+ };
130
+ Headers.prototype.set = function(name, value) {
131
+ this.map[normalizeName(name)] = normalizeValue(value);
132
+ };
133
+ Headers.prototype.forEach = function(callback, thisArg) {
134
+ for (var name in this.map) {
135
+ if (this.map.hasOwnProperty(name)) {
136
+ callback.call(thisArg, this.map[name], name, this);
137
+ }
138
+ }
139
+ };
140
+ Headers.prototype.keys = function() {
141
+ var items = [];
142
+ this.forEach(function(value, name) {
143
+ items.push(name);
144
+ });
145
+ return iteratorFor(items);
146
+ };
147
+ Headers.prototype.values = function() {
148
+ var items = [];
149
+ this.forEach(function(value) {
150
+ items.push(value);
151
+ });
152
+ return iteratorFor(items);
153
+ };
154
+ Headers.prototype.entries = function() {
155
+ var items = [];
156
+ this.forEach(function(value, name) {
157
+ items.push([name, value]);
158
+ });
159
+ return iteratorFor(items);
160
+ };
161
+ if (support.iterable) {
162
+ Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
163
+ }
164
+ function consumed(body) {
165
+ if (body._noBody) return;
166
+ if (body.bodyUsed) {
167
+ return Promise.reject(new TypeError("Already read"));
168
+ }
169
+ body.bodyUsed = true;
170
+ }
171
+ function fileReaderReady(reader) {
172
+ return new Promise(function(resolve, reject) {
173
+ reader.onload = function() {
174
+ resolve(reader.result);
175
+ };
176
+ reader.onerror = function() {
177
+ reject(reader.error);
178
+ };
179
+ });
180
+ }
181
+ function readBlobAsArrayBuffer(blob) {
182
+ var reader = new FileReader();
183
+ var promise = fileReaderReady(reader);
184
+ reader.readAsArrayBuffer(blob);
185
+ return promise;
186
+ }
187
+ function readBlobAsText(blob) {
188
+ var reader = new FileReader();
189
+ var promise = fileReaderReady(reader);
190
+ var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
191
+ var encoding = match ? match[1] : "utf-8";
192
+ reader.readAsText(blob, encoding);
193
+ return promise;
194
+ }
195
+ function readArrayBufferAsText(buf) {
196
+ var view = new Uint8Array(buf);
197
+ var chars = new Array(view.length);
198
+ for (var i = 0; i < view.length; i++) {
199
+ chars[i] = String.fromCharCode(view[i]);
200
+ }
201
+ return chars.join("");
202
+ }
203
+ function bufferClone(buf) {
204
+ if (buf.slice) {
205
+ return buf.slice(0);
206
+ } else {
207
+ var view = new Uint8Array(buf.byteLength);
208
+ view.set(new Uint8Array(buf));
209
+ return view.buffer;
210
+ }
211
+ }
212
+ function Body() {
213
+ this.bodyUsed = false;
214
+ this._initBody = function(body) {
215
+ this.bodyUsed = this.bodyUsed;
216
+ this._bodyInit = body;
217
+ if (!body) {
218
+ this._noBody = true;
219
+ this._bodyText = "";
220
+ } else if (typeof body === "string") {
221
+ this._bodyText = body;
222
+ } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
223
+ this._bodyBlob = body;
224
+ } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
225
+ this._bodyFormData = body;
226
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
227
+ this._bodyText = body.toString();
228
+ } else if (support.arrayBuffer && support.blob && isDataView(body)) {
229
+ this._bodyArrayBuffer = bufferClone(body.buffer);
230
+ this._bodyInit = new Blob([this._bodyArrayBuffer]);
231
+ } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
232
+ this._bodyArrayBuffer = bufferClone(body);
233
+ } else {
234
+ this._bodyText = body = Object.prototype.toString.call(body);
235
+ }
236
+ if (!this.headers.get("content-type")) {
237
+ if (typeof body === "string") {
238
+ this.headers.set("content-type", "text/plain;charset=UTF-8");
239
+ } else if (this._bodyBlob && this._bodyBlob.type) {
240
+ this.headers.set("content-type", this._bodyBlob.type);
241
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
242
+ this.headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8");
243
+ }
244
+ }
245
+ };
246
+ if (support.blob) {
247
+ this.blob = function() {
248
+ var rejected = consumed(this);
249
+ if (rejected) {
250
+ return rejected;
251
+ }
252
+ if (this._bodyBlob) {
253
+ return Promise.resolve(this._bodyBlob);
254
+ } else if (this._bodyArrayBuffer) {
255
+ return Promise.resolve(new Blob([this._bodyArrayBuffer]));
256
+ } else if (this._bodyFormData) {
257
+ throw new Error("could not read FormData body as blob");
258
+ } else {
259
+ return Promise.resolve(new Blob([this._bodyText]));
260
+ }
261
+ };
262
+ }
263
+ this.arrayBuffer = function() {
264
+ if (this._bodyArrayBuffer) {
265
+ var isConsumed = consumed(this);
266
+ if (isConsumed) {
267
+ return isConsumed;
268
+ } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
269
+ return Promise.resolve(
270
+ this._bodyArrayBuffer.buffer.slice(
271
+ this._bodyArrayBuffer.byteOffset,
272
+ this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
273
+ )
274
+ );
275
+ } else {
276
+ return Promise.resolve(this._bodyArrayBuffer);
277
+ }
278
+ } else if (support.blob) {
279
+ return this.blob().then(readBlobAsArrayBuffer);
280
+ } else {
281
+ throw new Error("could not read as ArrayBuffer");
282
+ }
283
+ };
284
+ this.text = function() {
285
+ var rejected = consumed(this);
286
+ if (rejected) {
287
+ return rejected;
288
+ }
289
+ if (this._bodyBlob) {
290
+ return readBlobAsText(this._bodyBlob);
291
+ } else if (this._bodyArrayBuffer) {
292
+ return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
293
+ } else if (this._bodyFormData) {
294
+ throw new Error("could not read FormData body as text");
295
+ } else {
296
+ return Promise.resolve(this._bodyText);
297
+ }
298
+ };
299
+ if (support.formData) {
300
+ this.formData = function() {
301
+ return this.text().then(decode);
302
+ };
303
+ }
304
+ this.json = function() {
305
+ return this.text().then(JSON.parse);
306
+ };
307
+ return this;
308
+ }
309
+ var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
310
+ function normalizeMethod(method) {
311
+ var upcased = method.toUpperCase();
312
+ return methods.indexOf(upcased) > -1 ? upcased : method;
313
+ }
314
+ function Request(input, options) {
315
+ if (!(this instanceof Request)) {
316
+ throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
317
+ }
318
+ options = options || {};
319
+ var body = options.body;
320
+ if (input instanceof Request) {
321
+ if (input.bodyUsed) {
322
+ throw new TypeError("Already read");
323
+ }
324
+ this.url = input.url;
325
+ this.credentials = input.credentials;
326
+ if (!options.headers) {
327
+ this.headers = new Headers(input.headers);
328
+ }
329
+ this.method = input.method;
330
+ this.mode = input.mode;
331
+ this.signal = input.signal;
332
+ if (!body && input._bodyInit != null) {
333
+ body = input._bodyInit;
334
+ input.bodyUsed = true;
335
+ }
336
+ } else {
337
+ this.url = String(input);
338
+ }
339
+ this.credentials = options.credentials || this.credentials || "same-origin";
340
+ if (options.headers || !this.headers) {
341
+ this.headers = new Headers(options.headers);
342
+ }
343
+ this.method = normalizeMethod(options.method || this.method || "GET");
344
+ this.mode = options.mode || this.mode || null;
345
+ this.signal = options.signal || this.signal || (function() {
346
+ if ("AbortController" in g) {
347
+ var ctrl = new AbortController();
348
+ return ctrl.signal;
349
+ }
350
+ })();
351
+ this.referrer = null;
352
+ if ((this.method === "GET" || this.method === "HEAD") && body) {
353
+ throw new TypeError("Body not allowed for GET or HEAD requests");
354
+ }
355
+ this._initBody(body);
356
+ if (this.method === "GET" || this.method === "HEAD") {
357
+ if (options.cache === "no-store" || options.cache === "no-cache") {
358
+ var reParamSearch = /([?&])_=[^&]*/;
359
+ if (reParamSearch.test(this.url)) {
360
+ this.url = this.url.replace(reParamSearch, "$1_=" + (/* @__PURE__ */ new Date()).getTime());
361
+ } else {
362
+ var reQueryString = /\?/;
363
+ this.url += (reQueryString.test(this.url) ? "&" : "?") + "_=" + (/* @__PURE__ */ new Date()).getTime();
364
+ }
365
+ }
366
+ }
367
+ }
368
+ Request.prototype.clone = function() {
369
+ return new Request(this, { body: this._bodyInit });
370
+ };
371
+ function decode(body) {
372
+ var form = new FormData();
373
+ body.trim().split("&").forEach(function(bytes) {
374
+ if (bytes) {
375
+ var split = bytes.split("=");
376
+ var name = split.shift().replace(/\+/g, " ");
377
+ var value = split.join("=").replace(/\+/g, " ");
378
+ form.append(decodeURIComponent(name), decodeURIComponent(value));
379
+ }
380
+ });
381
+ return form;
382
+ }
383
+ function parseHeaders(rawHeaders) {
384
+ var headers = new Headers();
385
+ var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, " ");
386
+ preProcessedHeaders.split("\r").map(function(header) {
387
+ return header.indexOf("\n") === 0 ? header.substr(1, header.length) : header;
388
+ }).forEach(function(line) {
389
+ var parts = line.split(":");
390
+ var key = parts.shift().trim();
391
+ if (key) {
392
+ var value = parts.join(":").trim();
393
+ try {
394
+ headers.append(key, value);
395
+ } catch (error) {
396
+ console.warn("Response " + error.message);
397
+ }
398
+ }
399
+ });
400
+ return headers;
401
+ }
402
+ Body.call(Request.prototype);
403
+ function Response(bodyInit, options) {
404
+ if (!(this instanceof Response)) {
405
+ throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
406
+ }
407
+ if (!options) {
408
+ options = {};
409
+ }
410
+ this.type = "default";
411
+ this.status = options.status === void 0 ? 200 : options.status;
412
+ if (this.status < 200 || this.status > 599) {
413
+ throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
414
+ }
415
+ this.ok = this.status >= 200 && this.status < 300;
416
+ this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
417
+ this.headers = new Headers(options.headers);
418
+ this.url = options.url || "";
419
+ this._initBody(bodyInit);
420
+ }
421
+ Body.call(Response.prototype);
422
+ Response.prototype.clone = function() {
423
+ return new Response(this._bodyInit, {
424
+ status: this.status,
425
+ statusText: this.statusText,
426
+ headers: new Headers(this.headers),
427
+ url: this.url
428
+ });
429
+ };
430
+ Response.error = function() {
431
+ var response = new Response(null, { status: 200, statusText: "" });
432
+ response.ok = false;
433
+ response.status = 0;
434
+ response.type = "error";
435
+ return response;
436
+ };
437
+ var redirectStatuses = [301, 302, 303, 307, 308];
438
+ Response.redirect = function(url, status) {
439
+ if (redirectStatuses.indexOf(status) === -1) {
440
+ throw new RangeError("Invalid status code");
441
+ }
442
+ return new Response(null, { status, headers: { location: url } });
443
+ };
444
+ exports2.DOMException = g.DOMException;
445
+ try {
446
+ new exports2.DOMException();
447
+ } catch (err) {
448
+ exports2.DOMException = function(message, name) {
449
+ this.message = message;
450
+ this.name = name;
451
+ var error = Error(message);
452
+ this.stack = error.stack;
453
+ };
454
+ exports2.DOMException.prototype = Object.create(Error.prototype);
455
+ exports2.DOMException.prototype.constructor = exports2.DOMException;
456
+ }
457
+ function fetch2(input, init) {
458
+ return new Promise(function(resolve, reject) {
459
+ var request = new Request(input, init);
460
+ if (request.signal && request.signal.aborted) {
461
+ return reject(new exports2.DOMException("Aborted", "AbortError"));
462
+ }
463
+ var xhr = new XMLHttpRequest();
464
+ function abortXhr() {
465
+ xhr.abort();
466
+ }
467
+ xhr.onload = function() {
468
+ var options = {
469
+ statusText: xhr.statusText,
470
+ headers: parseHeaders(xhr.getAllResponseHeaders() || "")
471
+ };
472
+ if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
473
+ options.status = 200;
474
+ } else {
475
+ options.status = xhr.status;
476
+ }
477
+ options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
478
+ var body = "response" in xhr ? xhr.response : xhr.responseText;
479
+ setTimeout(function() {
480
+ resolve(new Response(body, options));
481
+ }, 0);
482
+ };
483
+ xhr.onerror = function() {
484
+ setTimeout(function() {
485
+ reject(new TypeError("Network request failed"));
486
+ }, 0);
487
+ };
488
+ xhr.ontimeout = function() {
489
+ setTimeout(function() {
490
+ reject(new TypeError("Network request timed out"));
491
+ }, 0);
492
+ };
493
+ xhr.onabort = function() {
494
+ setTimeout(function() {
495
+ reject(new exports2.DOMException("Aborted", "AbortError"));
496
+ }, 0);
497
+ };
498
+ function fixUrl(url) {
499
+ try {
500
+ return url === "" && g.location.href ? g.location.href : url;
501
+ } catch (e) {
502
+ return url;
503
+ }
504
+ }
505
+ xhr.open(request.method, fixUrl(request.url), true);
506
+ if (request.credentials === "include") {
507
+ xhr.withCredentials = true;
508
+ } else if (request.credentials === "omit") {
509
+ xhr.withCredentials = false;
510
+ }
511
+ if ("responseType" in xhr) {
512
+ if (support.blob) {
513
+ xhr.responseType = "blob";
514
+ } else if (support.arrayBuffer) {
515
+ xhr.responseType = "arraybuffer";
516
+ }
517
+ }
518
+ if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
519
+ var names = [];
520
+ Object.getOwnPropertyNames(init.headers).forEach(function(name) {
521
+ names.push(normalizeName(name));
522
+ xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
523
+ });
524
+ request.headers.forEach(function(value, name) {
525
+ if (names.indexOf(name) === -1) {
526
+ xhr.setRequestHeader(name, value);
527
+ }
528
+ });
529
+ } else {
530
+ request.headers.forEach(function(value, name) {
531
+ xhr.setRequestHeader(name, value);
532
+ });
533
+ }
534
+ if (request.signal) {
535
+ request.signal.addEventListener("abort", abortXhr);
536
+ xhr.onreadystatechange = function() {
537
+ if (xhr.readyState === 4) {
538
+ request.signal.removeEventListener("abort", abortXhr);
539
+ }
540
+ };
541
+ }
542
+ xhr.send(typeof request._bodyInit === "undefined" ? null : request._bodyInit);
543
+ });
544
+ }
545
+ fetch2.polyfill = true;
546
+ if (!g.fetch) {
547
+ g.fetch = fetch2;
548
+ g.Headers = Headers;
549
+ g.Request = Request;
550
+ g.Response = Response;
551
+ }
552
+ exports2.Headers = Headers;
553
+ exports2.Request = Request;
554
+ exports2.Response = Response;
555
+ exports2.fetch = fetch2;
556
+ return exports2;
557
+ })({});
558
+ })(typeof self !== "undefined" ? self : exports);
559
+ }
560
+ });
561
+ var byteToHex = [];
562
+ for (let i = 0; i < 256; ++i) {
563
+ byteToHex.push((i + 256).toString(16).slice(1));
564
+ }
565
+ function unsafeStringify(arr, offset = 0) {
566
+ 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();
567
+ }
568
+ var getRandomValues;
569
+ var rnds8 = new Uint8Array(16);
570
+ function rng() {
571
+ if (!getRandomValues) {
572
+ if (typeof crypto === "undefined" || !crypto.getRandomValues) {
573
+ throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
574
+ }
575
+ getRandomValues = crypto.getRandomValues.bind(crypto);
576
+ }
577
+ return getRandomValues(rnds8);
578
+ }
579
+ var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
580
+ var native_default = { randomUUID };
581
+ function _v4(options, buf, offset) {
582
+ options = options || {};
583
+ const rnds = options.random ?? options.rng?.() ?? rng();
584
+ if (rnds.length < 16) {
585
+ throw new Error("Random bytes length must be >= 16");
586
+ }
587
+ rnds[6] = rnds[6] & 15 | 64;
588
+ rnds[8] = rnds[8] & 63 | 128;
589
+ if (buf) {
590
+ offset = offset || 0;
591
+ if (offset < 0 || offset + 16 > buf.length) {
592
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
593
+ }
594
+ for (let i = 0; i < 16; ++i) {
595
+ buf[offset + i] = rnds[i];
596
+ }
597
+ return buf;
598
+ }
599
+ return unsafeStringify(rnds);
600
+ }
601
+ function v4(options, buf, offset) {
602
+ if (native_default.randomUUID && !buf && !options) {
603
+ return native_default.randomUUID();
604
+ }
605
+ return _v4(options, buf, offset);
606
+ }
607
+ var v4_default = v4;
608
+ var import_polyfill = __toESM(require_browser_polyfill());
609
+ function CheckFlagResponseDataFromJSON(json) {
610
+ return CheckFlagResponseDataFromJSONTyped(json, false);
611
+ }
612
+ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
613
+ if (json == null) {
614
+ return json;
615
+ }
616
+ return {
617
+ companyId: json["company_id"] == null ? void 0 : json["company_id"],
618
+ error: json["error"] == null ? void 0 : json["error"],
619
+ featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
620
+ featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
621
+ featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
622
+ featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
623
+ featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
624
+ flag: json["flag"],
625
+ flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
626
+ reason: json["reason"],
627
+ ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
628
+ ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
629
+ userId: json["user_id"] == null ? void 0 : json["user_id"],
630
+ value: json["value"]
631
+ };
632
+ }
633
+ function EventBodyFlagCheckToJSON(json) {
634
+ return EventBodyFlagCheckToJSONTyped(json, false);
635
+ }
636
+ function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
637
+ if (value == null) {
638
+ return value;
639
+ }
640
+ return {
641
+ company_id: value["companyId"],
642
+ error: value["error"],
643
+ flag_id: value["flagId"],
644
+ flag_key: value["flagKey"],
645
+ reason: value["reason"],
646
+ req_company: value["reqCompany"],
647
+ req_user: value["reqUser"],
648
+ rule_id: value["ruleId"],
649
+ user_id: value["userId"],
650
+ value: value["value"]
651
+ };
652
+ }
653
+ function CheckFlagResponseFromJSON(json) {
654
+ return CheckFlagResponseFromJSONTyped(json, false);
655
+ }
656
+ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
657
+ if (json == null) {
658
+ return json;
659
+ }
660
+ return {
661
+ data: CheckFlagResponseDataFromJSON(json["data"]),
662
+ params: json["params"]
663
+ };
664
+ }
665
+ function CheckFlagsResponseDataFromJSON(json) {
666
+ return CheckFlagsResponseDataFromJSONTyped(json, false);
667
+ }
668
+ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
669
+ if (json == null) {
670
+ return json;
671
+ }
672
+ return {
673
+ flags: json["flags"].map(CheckFlagResponseDataFromJSON)
674
+ };
675
+ }
676
+ function CheckFlagsResponseFromJSON(json) {
677
+ return CheckFlagsResponseFromJSONTyped(json, false);
678
+ }
679
+ function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
680
+ if (json == null) {
681
+ return json;
682
+ }
683
+ return {
684
+ data: CheckFlagsResponseDataFromJSON(json["data"]),
685
+ params: json["params"]
686
+ };
687
+ }
688
+ var RuleType = /* @__PURE__ */ ((RuleType2) => {
689
+ RuleType2["GLOBAL_OVERRIDE"] = "global_override";
690
+ RuleType2["COMPANY_OVERRIDE"] = "company_override";
691
+ RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
692
+ RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
693
+ RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
694
+ RuleType2["STANDARD"] = "standard";
695
+ RuleType2["DEFAULT"] = "default";
696
+ return RuleType2;
697
+ })(RuleType || {});
698
+ var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
699
+ UsagePeriod2["ALL_TIME"] = "all_time";
700
+ UsagePeriod2["CURRENT_DAY"] = "current_day";
701
+ UsagePeriod2["CURRENT_MONTH"] = "current_month";
702
+ UsagePeriod2["CURRENT_WEEK"] = "current_week";
703
+ return UsagePeriod2;
704
+ })(UsagePeriod || {});
705
+ var CheckFlagReturnFromJSON = (json) => {
706
+ const {
707
+ companyId,
708
+ error,
709
+ featureAllocation,
710
+ featureUsage,
711
+ featureUsageEvent,
712
+ featureUsagePeriod,
713
+ featureUsageResetAt,
714
+ flag,
715
+ flagId,
716
+ reason,
717
+ ruleId,
718
+ ruleType,
719
+ userId,
720
+ value
721
+ } = CheckFlagResponseDataFromJSON(json);
722
+ const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
723
+ (ruleType == "company_override_usage_exceeded" || // if the rule type is one of these, then we have exceeded usage
724
+ ruleType == "plan_entitlement_usage_exceeded");
725
+ return {
726
+ featureUsageExceeded,
727
+ companyId: companyId == null ? void 0 : companyId,
728
+ error: error == null ? void 0 : error,
729
+ featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
730
+ featureUsage: featureUsage == null ? void 0 : featureUsage,
731
+ featureUsageEvent: featureUsageEvent === null ? void 0 : featureUsageEvent,
732
+ featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
733
+ featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
734
+ flag,
735
+ flagId: flagId == null ? void 0 : flagId,
736
+ reason,
737
+ ruleId: ruleId == null ? void 0 : ruleId,
738
+ ruleType: ruleType == null ? void 0 : ruleType,
739
+ userId: userId == null ? void 0 : userId,
740
+ value
741
+ };
742
+ };
743
+ function contextString(context) {
744
+ const sortedContext = Object.keys(context).reduce((acc, key) => {
745
+ const sortedKeys = Object.keys(
746
+ context[key] || {}
747
+ ).sort();
748
+ const sortedObj = sortedKeys.reduce((obj, sortedKey) => {
749
+ obj[sortedKey] = context[key][sortedKey];
750
+ return obj;
751
+ }, {});
752
+ acc[key] = sortedObj;
753
+ return acc;
754
+ }, {});
755
+ return JSON.stringify(sortedContext);
756
+ }
757
+ var version = "1.2.6";
758
+ var anonymousIdKey = "schematicId";
759
+ var Schematic = class {
760
+ additionalHeaders = {};
761
+ apiKey;
762
+ apiUrl = "https://api.schematichq.com";
763
+ conn = null;
764
+ context = {};
765
+ debugEnabled = false;
766
+ offlineEnabled = false;
767
+ eventQueue;
768
+ contextDependentEventQueue;
769
+ eventUrl = "https://c.schematichq.com";
770
+ flagCheckListeners = {};
771
+ flagValueListeners = {};
772
+ isPending = true;
773
+ isPendingListeners = /* @__PURE__ */ new Set();
774
+ storage;
775
+ useWebSocket = false;
776
+ checks = {};
777
+ featureUsageEventMap = {};
778
+ webSocketUrl = "wss://api.schematichq.com";
779
+ constructor(apiKey, options) {
780
+ this.apiKey = apiKey;
781
+ this.eventQueue = [];
782
+ this.contextDependentEventQueue = [];
783
+ this.useWebSocket = options?.useWebSocket ?? false;
784
+ this.debugEnabled = options?.debug ?? false;
785
+ this.offlineEnabled = options?.offline ?? false;
786
+ if (typeof window !== "undefined" && typeof window.location !== "undefined") {
787
+ const params = new URLSearchParams(window.location.search);
788
+ const debugParam = params.get("schematic_debug");
789
+ if (debugParam !== null && (debugParam === "" || debugParam === "true" || debugParam === "1")) {
790
+ this.debugEnabled = true;
791
+ }
792
+ const offlineParam = params.get("schematic_offline");
793
+ if (offlineParam !== null && (offlineParam === "" || offlineParam === "true" || offlineParam === "1")) {
794
+ this.offlineEnabled = true;
795
+ this.debugEnabled = true;
796
+ }
797
+ }
798
+ if (this.offlineEnabled && options?.debug !== false) {
799
+ this.debugEnabled = true;
800
+ }
801
+ if (this.offlineEnabled) {
802
+ this.setIsPending(false);
803
+ }
804
+ this.additionalHeaders = {
805
+ "X-Schematic-Client-Version": `schematic-js@${version}`,
806
+ ...options?.additionalHeaders ?? {}
807
+ };
808
+ if (options?.storage) {
809
+ this.storage = options.storage;
810
+ } else if (typeof localStorage !== "undefined") {
811
+ this.storage = localStorage;
812
+ }
813
+ if (options?.apiUrl !== void 0) {
814
+ this.apiUrl = options.apiUrl;
815
+ }
816
+ if (options?.eventUrl !== void 0) {
817
+ this.eventUrl = options.eventUrl;
818
+ }
819
+ if (options?.webSocketUrl !== void 0) {
820
+ this.webSocketUrl = options.webSocketUrl;
821
+ }
822
+ if (typeof window !== "undefined" && window?.addEventListener) {
823
+ window.addEventListener("beforeunload", () => {
824
+ this.flushEventQueue();
825
+ this.flushContextDependentEventQueue();
826
+ });
827
+ }
828
+ if (this.offlineEnabled) {
829
+ this.debug(
830
+ "Initialized with offline mode enabled - no network requests will be made"
831
+ );
832
+ } else if (this.debugEnabled) {
833
+ this.debug("Initialized with debug mode enabled");
834
+ }
835
+ }
836
+ /**
837
+ * Get value for a single flag.
838
+ * In WebSocket mode, returns cached values if connection is active, otherwise establishes
839
+ * new connection and then returns the requestedvalue. Falls back to REST API if WebSocket
840
+ * connection fails.
841
+ * In REST mode, makes an API call for each check.
842
+ */
843
+ async checkFlag(options) {
844
+ const { fallback = false, key } = options;
845
+ const context = options.context || this.context;
846
+ const contextStr = contextString(context);
847
+ this.debug(`checkFlag: ${key}`, { context, fallback });
848
+ if (this.isOffline()) {
849
+ this.debug(`checkFlag offline result: ${key}`, {
850
+ value: fallback,
851
+ offlineMode: true
852
+ });
853
+ return fallback;
854
+ }
855
+ if (!this.useWebSocket) {
856
+ const requestUrl = `${this.apiUrl}/flags/${key}/check`;
857
+ return fetch(requestUrl, {
858
+ method: "POST",
859
+ headers: {
860
+ ...this.additionalHeaders ?? {},
861
+ "Content-Type": "application/json;charset=UTF-8",
862
+ "X-Schematic-Api-Key": this.apiKey
863
+ },
864
+ body: JSON.stringify(context)
865
+ }).then((response) => {
866
+ if (!response.ok) {
867
+ throw new Error("Network response was not ok");
868
+ }
869
+ return response.json();
870
+ }).then((response) => {
871
+ const parsedResponse = CheckFlagResponseFromJSON(response);
872
+ this.debug(`checkFlag result: ${key}`, parsedResponse);
873
+ const result = CheckFlagReturnFromJSON(parsedResponse.data);
874
+ if (typeof result.featureUsageEvent === "string") {
875
+ this.updateFeatureUsageEventMap(result);
876
+ }
877
+ this.submitFlagCheckEvent(key, result, context);
878
+ return result.value;
879
+ }).catch((error) => {
880
+ console.error("There was a problem with the fetch operation:", error);
881
+ const errorResult = {
882
+ flag: key,
883
+ value: fallback,
884
+ reason: "API request failed",
885
+ error: error instanceof Error ? error.message : String(error)
886
+ };
887
+ this.submitFlagCheckEvent(key, errorResult, context);
888
+ return fallback;
889
+ });
890
+ }
891
+ try {
892
+ const existingVals = this.checks[contextStr];
893
+ if (this.conn !== null && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
894
+ this.debug(`checkFlag cached result: ${key}`, existingVals[key]);
895
+ return existingVals[key].value;
896
+ }
897
+ if (this.isOffline()) {
898
+ return fallback;
899
+ }
900
+ try {
901
+ await this.setContext(context);
902
+ } catch (error) {
903
+ console.error(
904
+ "WebSocket connection failed, falling back to REST:",
905
+ error
906
+ );
907
+ return this.fallbackToRest(key, context, fallback);
908
+ }
909
+ const contextVals = this.checks[contextStr] ?? {};
910
+ const flagCheck = contextVals[key];
911
+ const result = flagCheck?.value ?? fallback;
912
+ this.debug(
913
+ `checkFlag WebSocket result: ${key}`,
914
+ typeof flagCheck !== "undefined" ? flagCheck : { value: fallback, fallbackUsed: true }
915
+ );
916
+ if (typeof flagCheck !== "undefined") {
917
+ this.submitFlagCheckEvent(key, flagCheck, context);
918
+ }
919
+ return result;
920
+ } catch (error) {
921
+ console.error("Unexpected error in checkFlag:", error);
922
+ const errorResult = {
923
+ flag: key,
924
+ value: fallback,
925
+ reason: "Unexpected error in flag check",
926
+ error: error instanceof Error ? error.message : String(error)
927
+ };
928
+ this.submitFlagCheckEvent(key, errorResult, context);
929
+ return fallback;
930
+ }
931
+ }
932
+ /**
933
+ * Helper function to log debug messages
934
+ * Only logs if debug mode is enabled
935
+ */
936
+ debug(message, ...args) {
937
+ if (this.debugEnabled) {
938
+ console.log(`[Schematic] ${message}`, ...args);
939
+ }
940
+ }
941
+ /**
942
+ * Helper function to check if client is in offline mode
943
+ */
944
+ isOffline() {
945
+ return this.offlineEnabled;
946
+ }
947
+ /**
948
+ * Submit a flag check event
949
+ * Records data about a flag check for analytics
950
+ */
951
+ submitFlagCheckEvent(flagKey, result, context) {
952
+ const eventBody = {
953
+ flagKey,
954
+ value: result.value,
955
+ reason: result.reason,
956
+ flagId: result.flagId,
957
+ ruleId: result.ruleId,
958
+ companyId: result.companyId,
959
+ userId: result.userId,
960
+ error: result.error,
961
+ reqCompany: context.company,
962
+ reqUser: context.user
963
+ };
964
+ this.debug(`submitting flag check event:`, eventBody);
965
+ return this.handleEvent("flag_check", EventBodyFlagCheckToJSON(eventBody));
966
+ }
967
+ /**
968
+ * Helper method for falling back to REST API when WebSocket connection fails
969
+ */
970
+ async fallbackToRest(key, context, fallback) {
971
+ if (this.isOffline()) {
972
+ this.debug(`fallbackToRest offline result: ${key}`, {
973
+ value: fallback,
974
+ offlineMode: true
975
+ });
976
+ return fallback;
977
+ }
978
+ try {
979
+ const requestUrl = `${this.apiUrl}/flags/${key}/check`;
980
+ const response = await fetch(requestUrl, {
981
+ method: "POST",
982
+ headers: {
983
+ ...this.additionalHeaders ?? {},
984
+ "Content-Type": "application/json;charset=UTF-8",
985
+ "X-Schematic-Api-Key": this.apiKey
986
+ },
987
+ body: JSON.stringify(context)
988
+ });
989
+ if (!response.ok) {
990
+ throw new Error("Network response was not ok");
991
+ }
992
+ const responseJson = await response.json();
993
+ const data = CheckFlagResponseFromJSON(responseJson);
994
+ this.debug(`fallbackToRest result: ${key}`, data);
995
+ const result = CheckFlagReturnFromJSON(data.data);
996
+ if (typeof result.featureUsageEvent === "string") {
997
+ this.updateFeatureUsageEventMap(result);
998
+ }
999
+ this.submitFlagCheckEvent(key, result, context);
1000
+ return result.value;
1001
+ } catch (error) {
1002
+ console.error("REST API call failed, using fallback value:", error);
1003
+ const errorResult = {
1004
+ flag: key,
1005
+ value: fallback,
1006
+ reason: "API request failed (fallback)",
1007
+ error: error instanceof Error ? error.message : String(error)
1008
+ };
1009
+ this.submitFlagCheckEvent(key, errorResult, context);
1010
+ return fallback;
1011
+ }
1012
+ }
1013
+ /**
1014
+ * Make an API call to fetch all flag values for a given context.
1015
+ * Recommended for use in REST mode only.
1016
+ * In offline mode, returns an empty object.
1017
+ */
1018
+ checkFlags = async (context) => {
1019
+ context = context || this.context;
1020
+ this.debug(`checkFlags`, { context });
1021
+ if (this.isOffline()) {
1022
+ this.debug(`checkFlags offline result: returning empty object`);
1023
+ return {};
1024
+ }
1025
+ const requestUrl = `${this.apiUrl}/flags/check`;
1026
+ const requestBody = JSON.stringify(context);
1027
+ return fetch(requestUrl, {
1028
+ method: "POST",
1029
+ headers: {
1030
+ ...this.additionalHeaders ?? {},
1031
+ "Content-Type": "application/json;charset=UTF-8",
1032
+ "X-Schematic-Api-Key": this.apiKey
1033
+ },
1034
+ body: requestBody
1035
+ }).then((response) => {
1036
+ if (!response.ok) {
1037
+ throw new Error("Network response was not ok");
1038
+ }
1039
+ return response.json();
1040
+ }).then((responseJson) => {
1041
+ const resp = CheckFlagsResponseFromJSON(responseJson);
1042
+ this.debug(`checkFlags result:`, resp);
1043
+ return (resp?.data?.flags ?? []).reduce(
1044
+ (accum, flag) => {
1045
+ accum[flag.flag] = flag.value;
1046
+ return accum;
1047
+ },
1048
+ {}
1049
+ );
1050
+ }).catch((error) => {
1051
+ console.error("There was a problem with the fetch operation:", error);
1052
+ return {};
1053
+ });
1054
+ };
1055
+ /**
1056
+ * Send an identify event.
1057
+ * This will set the context for subsequent flag evaluation and events, and will also
1058
+ * send an identify event to the Schematic API which will upsert a user and company.
1059
+ */
1060
+ identify = (body) => {
1061
+ this.debug(`identify:`, body);
1062
+ try {
1063
+ this.setContext({
1064
+ company: body.company?.keys,
1065
+ user: body.keys
1066
+ });
1067
+ } catch (error) {
1068
+ console.error("Error setting context:", error);
1069
+ }
1070
+ return this.handleEvent("identify", body);
1071
+ };
1072
+ /**
1073
+ * Set the flag evaluation context.
1074
+ * In WebSocket mode, this will:
1075
+ * 1. Open a websocket connection if not already open
1076
+ * 2. Send the context to the server
1077
+ * 3. Wait for initial flag values to be returned
1078
+ * The promise resolves when initial flag values are received.
1079
+ * In offline mode, this will just set the context locally without connecting.
1080
+ */
1081
+ setContext = async (context) => {
1082
+ if (this.isOffline() || !this.useWebSocket) {
1083
+ this.context = context;
1084
+ this.flushContextDependentEventQueue();
1085
+ this.setIsPending(false);
1086
+ return Promise.resolve();
1087
+ }
1088
+ try {
1089
+ this.setIsPending(true);
1090
+ if (!this.conn) {
1091
+ this.conn = this.wsConnect();
1092
+ }
1093
+ const socket = await this.conn;
1094
+ await this.wsSendMessage(socket, context);
1095
+ } catch (error) {
1096
+ console.error("Failed to establish WebSocket connection:", error);
1097
+ throw error;
1098
+ }
1099
+ };
1100
+ /**
1101
+ * Send a track event
1102
+ * Track usage for a company and/or user.
1103
+ * Optimistically updates feature usage flags if tracking a featureUsageEvent.
1104
+ */
1105
+ track = (body) => {
1106
+ const { company, user, event, traits, quantity = 1 } = body;
1107
+ if (!this.hasContext(company, user)) {
1108
+ this.debug(`track: queuing event "${event}" until context is available`);
1109
+ const queuedEvent = {
1110
+ api_key: this.apiKey,
1111
+ body: {
1112
+ company,
1113
+ event,
1114
+ traits: traits ?? {},
1115
+ user,
1116
+ quantity
1117
+ },
1118
+ sent_at: (/* @__PURE__ */ new Date()).toISOString(),
1119
+ tracker_event_id: v4_default(),
1120
+ tracker_user_id: this.getAnonymousId(),
1121
+ type: "track"
1122
+ };
1123
+ this.contextDependentEventQueue.push(queuedEvent);
1124
+ return Promise.resolve();
1125
+ }
1126
+ const trackData = {
1127
+ company: company ?? this.context.company,
1128
+ event,
1129
+ traits: traits ?? {},
1130
+ user: user ?? this.context.user,
1131
+ quantity
1132
+ };
1133
+ this.debug(`track:`, trackData);
1134
+ if (event in this.featureUsageEventMap) {
1135
+ this.optimisticallyUpdateFeatureUsage(event, quantity);
1136
+ }
1137
+ return this.handleEvent("track", trackData);
1138
+ };
1139
+ /**
1140
+ * Optimistically update feature usage flags associated with a tracked event
1141
+ * This updates flags in memory with updated usage counts and value/featureUsageExceeded flags
1142
+ * before the network request completes
1143
+ */
1144
+ optimisticallyUpdateFeatureUsage = (eventName, quantity = 1) => {
1145
+ const flagsForEvent = this.featureUsageEventMap[eventName];
1146
+ if (flagsForEvent === void 0 || flagsForEvent === null) return;
1147
+ this.debug(
1148
+ `Optimistically updating feature usage for event: ${eventName}`,
1149
+ { quantity }
1150
+ );
1151
+ Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
1152
+ if (check === void 0) return;
1153
+ const updatedCheck = { ...check };
1154
+ if (typeof updatedCheck.featureUsage === "number") {
1155
+ updatedCheck.featureUsage += quantity;
1156
+ if (typeof updatedCheck.featureAllocation === "number") {
1157
+ const wasExceeded = updatedCheck.featureUsageExceeded === true;
1158
+ const nowExceeded = updatedCheck.featureUsage >= updatedCheck.featureAllocation;
1159
+ if (nowExceeded !== wasExceeded) {
1160
+ updatedCheck.featureUsageExceeded = nowExceeded;
1161
+ if (nowExceeded) {
1162
+ updatedCheck.value = false;
1163
+ }
1164
+ this.debug(`Usage limit status changed for flag: ${flagKey}`, {
1165
+ was: wasExceeded ? "exceeded" : "within limits",
1166
+ now: nowExceeded ? "exceeded" : "within limits",
1167
+ featureUsage: updatedCheck.featureUsage,
1168
+ featureAllocation: updatedCheck.featureAllocation,
1169
+ value: updatedCheck.value
1170
+ });
1171
+ }
1172
+ }
1173
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1174
+ this.featureUsageEventMap[eventName][flagKey] = updatedCheck;
1175
+ }
1176
+ const contextStr = contextString(this.context);
1177
+ if (this.checks[contextStr] !== void 0 && this.checks[contextStr] !== null) {
1178
+ this.checks[contextStr][flagKey] = updatedCheck;
1179
+ }
1180
+ this.notifyFlagCheckListeners(flagKey, updatedCheck);
1181
+ this.notifyFlagValueListeners(flagKey, updatedCheck.value);
1182
+ }
1183
+ });
1184
+ };
1185
+ /**
1186
+ * Event processing
1187
+ */
1188
+ hasContext = (company, user) => {
1189
+ const hasProvidedContext = company !== void 0 && company !== null && Object.keys(company).length > 0 || user !== void 0 && user !== null && Object.keys(user).length > 0;
1190
+ const hasInstanceContext = this.context.company !== void 0 && this.context.company !== null && Object.keys(this.context.company).length > 0 || this.context.user !== void 0 && this.context.user !== null && Object.keys(this.context.user).length > 0;
1191
+ return hasProvidedContext || hasInstanceContext;
1192
+ };
1193
+ flushContextDependentEventQueue = () => {
1194
+ this.debug(
1195
+ `flushing ${this.contextDependentEventQueue.length} context-dependent events`
1196
+ );
1197
+ while (this.contextDependentEventQueue.length > 0) {
1198
+ const event = this.contextDependentEventQueue.shift();
1199
+ if (event) {
1200
+ if (event.type === "track" && typeof event.body === "object" && event.body !== null) {
1201
+ const trackBody = event.body;
1202
+ const updatedBody = {
1203
+ ...trackBody,
1204
+ company: trackBody.company ?? this.context.company,
1205
+ user: trackBody.user ?? this.context.user
1206
+ };
1207
+ const updatedEvent = {
1208
+ ...event,
1209
+ body: updatedBody,
1210
+ sent_at: (/* @__PURE__ */ new Date()).toISOString()
1211
+ // Update timestamp to actual send time
1212
+ };
1213
+ this.sendEvent(updatedEvent);
1214
+ } else {
1215
+ this.sendEvent(event);
1216
+ }
1217
+ }
1218
+ }
1219
+ };
1220
+ flushEventQueue = () => {
1221
+ while (this.eventQueue.length > 0) {
1222
+ const event = this.eventQueue.shift();
1223
+ if (event) {
1224
+ this.sendEvent(event);
1225
+ }
1226
+ }
1227
+ };
1228
+ getAnonymousId = () => {
1229
+ if (!this.storage) {
1230
+ return v4_default();
1231
+ }
1232
+ const storedAnonymousId = this.storage.getItem(anonymousIdKey);
1233
+ if (typeof storedAnonymousId !== "undefined") {
1234
+ return storedAnonymousId;
1235
+ }
1236
+ const generatedAnonymousId = v4_default();
1237
+ this.storage.setItem(anonymousIdKey, generatedAnonymousId);
1238
+ return generatedAnonymousId;
1239
+ };
1240
+ handleEvent = (eventType, eventBody) => {
1241
+ const event = {
1242
+ api_key: this.apiKey,
1243
+ body: eventBody,
1244
+ sent_at: (/* @__PURE__ */ new Date()).toISOString(),
1245
+ tracker_event_id: v4_default(),
1246
+ tracker_user_id: this.getAnonymousId(),
1247
+ type: eventType
1248
+ };
1249
+ if (typeof document !== "undefined" && document?.hidden) {
1250
+ return this.storeEvent(event);
1251
+ } else {
1252
+ return this.sendEvent(event);
1253
+ }
1254
+ };
1255
+ sendEvent = async (event) => {
1256
+ const captureUrl = `${this.eventUrl}/e`;
1257
+ const payload = JSON.stringify(event);
1258
+ this.debug(`sending event:`, { url: captureUrl, event });
1259
+ if (this.isOffline()) {
1260
+ this.debug(`event not sent (offline mode):`, { event });
1261
+ return Promise.resolve();
1262
+ }
1263
+ try {
1264
+ const response = await fetch(captureUrl, {
1265
+ method: "POST",
1266
+ headers: {
1267
+ ...this.additionalHeaders ?? {},
1268
+ "Content-Type": "application/json;charset=UTF-8"
1269
+ },
1270
+ body: payload
1271
+ });
1272
+ this.debug(`event sent:`, {
1273
+ status: response.status,
1274
+ statusText: response.statusText
1275
+ });
1276
+ } catch (error) {
1277
+ console.error("Error sending Schematic event: ", error);
1278
+ }
1279
+ return Promise.resolve();
1280
+ };
1281
+ storeEvent = (event) => {
1282
+ this.eventQueue.push(event);
1283
+ return Promise.resolve();
1284
+ };
1285
+ /**
1286
+ * Websocket management
1287
+ */
1288
+ /**
1289
+ * If using websocket mode, close the connection when done.
1290
+ * In offline mode, this is a no-op.
1291
+ */
1292
+ cleanup = async () => {
1293
+ if (this.isOffline()) {
1294
+ this.debug("cleanup: skipped (offline mode)");
1295
+ return Promise.resolve();
1296
+ }
1297
+ if (this.conn) {
1298
+ try {
1299
+ const socket = await this.conn;
1300
+ socket.close();
1301
+ } catch (error) {
1302
+ console.error("Error during cleanup:", error);
1303
+ } finally {
1304
+ this.conn = null;
1305
+ }
1306
+ }
1307
+ };
1308
+ // Open a websocket connection
1309
+ wsConnect = () => {
1310
+ if (this.isOffline()) {
1311
+ this.debug("wsConnect: skipped (offline mode)");
1312
+ return Promise.reject(
1313
+ new Error("WebSocket connection skipped in offline mode")
1314
+ );
1315
+ }
1316
+ return new Promise((resolve, reject) => {
1317
+ const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
1318
+ this.debug(`connecting to WebSocket:`, wsUrl);
1319
+ const webSocket = new WebSocket(wsUrl);
1320
+ webSocket.onopen = () => {
1321
+ this.debug(`WebSocket connection opened`);
1322
+ resolve(webSocket);
1323
+ };
1324
+ webSocket.onerror = (error) => {
1325
+ this.debug(`WebSocket connection error:`, error);
1326
+ reject(error);
1327
+ };
1328
+ webSocket.onclose = () => {
1329
+ this.debug(`WebSocket connection closed`);
1330
+ this.conn = null;
1331
+ };
1332
+ });
1333
+ };
1334
+ // Send a message on the websocket indicating interest in a particular evaluation context
1335
+ // and wait for the initial set of flag values to be returned
1336
+ wsSendMessage = (socket, context) => {
1337
+ if (this.isOffline()) {
1338
+ this.debug("wsSendMessage: skipped (offline mode)");
1339
+ this.setIsPending(false);
1340
+ return Promise.resolve();
1341
+ }
1342
+ return new Promise((resolve, reject) => {
1343
+ if (contextString(context) == contextString(this.context)) {
1344
+ this.debug(`WebSocket context unchanged, skipping update`);
1345
+ return resolve(this.setIsPending(false));
1346
+ }
1347
+ this.debug(`WebSocket context updated:`, context);
1348
+ this.context = context;
1349
+ const sendMessage = () => {
1350
+ let resolved = false;
1351
+ const messageHandler = (event) => {
1352
+ const message = JSON.parse(event.data);
1353
+ this.debug(`WebSocket message received:`, message);
1354
+ if (!(contextString(context) in this.checks)) {
1355
+ this.checks[contextString(context)] = {};
1356
+ }
1357
+ (message.flags ?? []).forEach((flag) => {
1358
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1359
+ const contextStr = contextString(context);
1360
+ if (this.checks[contextStr] === void 0) {
1361
+ this.checks[contextStr] = {};
1362
+ }
1363
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1364
+ this.debug(`WebSocket flag update:`, {
1365
+ flag: flagCheck.flag,
1366
+ value: flagCheck.value,
1367
+ flagCheck
1368
+ });
1369
+ if (typeof flagCheck.featureUsageEvent === "string") {
1370
+ this.updateFeatureUsageEventMap(flagCheck);
1371
+ }
1372
+ if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
1373
+ this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
1374
+ }
1375
+ this.notifyFlagCheckListeners(flag.flag, flagCheck);
1376
+ this.notifyFlagValueListeners(flag.flag, flagCheck.value);
1377
+ });
1378
+ this.flushContextDependentEventQueue();
1379
+ this.setIsPending(false);
1380
+ if (!resolved) {
1381
+ resolved = true;
1382
+ resolve();
1383
+ }
1384
+ };
1385
+ socket.addEventListener("message", messageHandler);
1386
+ const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
1387
+ const messagePayload = {
1388
+ apiKey: this.apiKey,
1389
+ clientVersion,
1390
+ data: context
1391
+ };
1392
+ this.debug(`WebSocket sending message:`, messagePayload);
1393
+ socket.send(JSON.stringify(messagePayload));
1394
+ };
1395
+ if (socket.readyState === WebSocket.OPEN) {
1396
+ this.debug(`WebSocket already open, sending message`);
1397
+ sendMessage();
1398
+ } else if (socket.readyState === WebSocket.CONNECTING) {
1399
+ this.debug(`WebSocket connecting, waiting for open to send message`);
1400
+ socket.addEventListener("open", sendMessage);
1401
+ } else {
1402
+ this.debug(`WebSocket is closed, cannot send message`);
1403
+ reject("WebSocket is not open or connecting");
1404
+ }
1405
+ });
1406
+ };
1407
+ /**
1408
+ * State management
1409
+ */
1410
+ // isPending state
1411
+ getIsPending = () => {
1412
+ return this.isPending;
1413
+ };
1414
+ addIsPendingListener = (listener) => {
1415
+ this.isPendingListeners.add(listener);
1416
+ return () => {
1417
+ this.isPendingListeners.delete(listener);
1418
+ };
1419
+ };
1420
+ setIsPending = (isPending) => {
1421
+ this.isPending = isPending;
1422
+ this.isPendingListeners.forEach(
1423
+ (listener) => notifyPendingListener(listener, isPending)
1424
+ );
1425
+ };
1426
+ // flag checks state
1427
+ getFlagCheck = (flagKey) => {
1428
+ const contextStr = contextString(this.context);
1429
+ const checks = this.checks[contextStr] ?? {};
1430
+ return checks[flagKey];
1431
+ };
1432
+ // flagValues state
1433
+ getFlagValue = (flagKey) => {
1434
+ const check = this.getFlagCheck(flagKey);
1435
+ return check?.value;
1436
+ };
1437
+ /** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
1438
+ addFlagValueListener = (flagKey, listener) => {
1439
+ if (!(flagKey in this.flagValueListeners)) {
1440
+ this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
1441
+ }
1442
+ this.flagValueListeners[flagKey].add(listener);
1443
+ return () => {
1444
+ this.flagValueListeners[flagKey].delete(listener);
1445
+ };
1446
+ };
1447
+ /** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
1448
+ addFlagCheckListener = (flagKey, listener) => {
1449
+ if (!(flagKey in this.flagCheckListeners)) {
1450
+ this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
1451
+ }
1452
+ this.flagCheckListeners[flagKey].add(listener);
1453
+ return () => {
1454
+ this.flagCheckListeners[flagKey].delete(listener);
1455
+ };
1456
+ };
1457
+ notifyFlagCheckListeners = (flagKey, check) => {
1458
+ const listeners = this.flagCheckListeners?.[flagKey] ?? [];
1459
+ if (listeners.size > 0) {
1460
+ this.debug(
1461
+ `Notifying ${listeners.size} flag check listeners for ${flagKey}`,
1462
+ check
1463
+ );
1464
+ }
1465
+ if (typeof check.featureUsageEvent === "string") {
1466
+ this.updateFeatureUsageEventMap(check);
1467
+ }
1468
+ listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
1469
+ };
1470
+ /** Add or update a CheckFlagReturn in the featureUsageEventMap */
1471
+ updateFeatureUsageEventMap = (check) => {
1472
+ if (typeof check.featureUsageEvent !== "string") return;
1473
+ const eventName = check.featureUsageEvent;
1474
+ if (this.featureUsageEventMap[eventName] === void 0 || this.featureUsageEventMap[eventName] === null) {
1475
+ this.featureUsageEventMap[eventName] = {};
1476
+ }
1477
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1478
+ this.featureUsageEventMap[eventName][check.flag] = check;
1479
+ }
1480
+ this.debug(
1481
+ `Updated featureUsageEventMap for event: ${eventName}, flag: ${check.flag}`,
1482
+ check
1483
+ );
1484
+ };
1485
+ notifyFlagValueListeners = (flagKey, value) => {
1486
+ const listeners = this.flagValueListeners?.[flagKey] ?? [];
1487
+ if (listeners.size > 0) {
1488
+ this.debug(
1489
+ `Notifying ${listeners.size} flag value listeners for ${flagKey}`,
1490
+ { value }
1491
+ );
1492
+ }
1493
+ listeners.forEach((listener) => notifyFlagValueListener(listener, value));
1494
+ };
1495
+ };
1496
+ var notifyPendingListener = (listener, value) => {
1497
+ if (listener.length > 0) {
1498
+ listener(value);
1499
+ } else {
1500
+ listener();
1501
+ }
1502
+ };
1503
+ var notifyFlagCheckListener = (listener, value) => {
1504
+ if (listener.length > 0) {
1505
+ listener(value);
1506
+ } else {
1507
+ listener();
1508
+ }
1509
+ };
1510
+ var notifyFlagValueListener = (listener, value) => {
1511
+ if (listener.length > 0) {
1512
+ listener(value);
1513
+ } else {
1514
+ listener();
1515
+ }
1516
+ };
1517
+
1518
+ // src/context/schematic.ts
1519
+ import { inject, onScopeDispose } from "vue";
1520
+
1521
+ // src/version.ts
1522
+ var version2 = "0.1.0";
1523
+
1524
+ // src/context/schematic.ts
1525
+ var SchematicSymbol = Symbol("schematic");
1526
+ var SchematicPlugin = {
1527
+ install(app, options) {
1528
+ let client;
1529
+ if ("client" in options && options.client) {
1530
+ client = options.client;
1531
+ } else if ("publishableKey" in options && options.publishableKey) {
1532
+ const { publishableKey, ...clientOpts } = options;
1533
+ client = new Schematic(publishableKey, {
1534
+ useWebSocket: clientOpts.useWebSocket ?? true,
1535
+ additionalHeaders: {
1536
+ "X-Schematic-Client-Version": `schematic-vue@${version2}`
1537
+ },
1538
+ ...clientOpts
1539
+ });
1540
+ } else {
1541
+ throw new Error(
1542
+ "SchematicPlugin requires either 'publishableKey' or 'client' option"
1543
+ );
1544
+ }
1545
+ const contextValue = {
1546
+ client
1547
+ };
1548
+ app.provide(SchematicSymbol, contextValue);
1549
+ }
1550
+ };
1551
+ var useSchematic = () => {
1552
+ const context = inject(SchematicSymbol);
1553
+ if (!context) {
1554
+ throw new Error(
1555
+ "useSchematic must be used within a component where SchematicPlugin is installed"
1556
+ );
1557
+ }
1558
+ return context;
1559
+ };
1560
+
1561
+ // src/composables/schematic.ts
1562
+ import { computed, onMounted, onScopeDispose as onScopeDispose2, ref } from "vue";
1563
+ var useSchematicClient = (opts) => {
1564
+ const schematic = useSchematic();
1565
+ const { client } = opts ?? {};
1566
+ return client ?? schematic.client;
1567
+ };
1568
+ var useSchematicContext = (opts) => {
1569
+ const client = useSchematicClient(opts);
1570
+ return {
1571
+ setContext: (context) => client.setContext(context)
1572
+ };
1573
+ };
1574
+ var useSchematicEvents = (opts) => {
1575
+ const client = useSchematicClient(opts);
1576
+ const track = (body) => client.track(body);
1577
+ const identify = (body) => {
1578
+ client.identify(body);
1579
+ };
1580
+ return {
1581
+ track,
1582
+ identify
1583
+ };
1584
+ };
1585
+ var useSchematicFlag = (key, opts) => {
1586
+ const client = useSchematicClient(opts);
1587
+ const fallback = opts?.fallback ?? false;
1588
+ const flagValue = ref(client.getFlagValue(key) ?? fallback);
1589
+ let unsubscribe = null;
1590
+ onMounted(() => {
1591
+ unsubscribe = client.addFlagValueListener(key, (value) => {
1592
+ flagValue.value = value;
1593
+ });
1594
+ });
1595
+ onScopeDispose2(() => {
1596
+ unsubscribe?.();
1597
+ });
1598
+ return flagValue;
1599
+ };
1600
+ var useSchematicEntitlement = (key, opts) => {
1601
+ const client = useSchematicClient(opts);
1602
+ const fallback = opts?.fallback ?? false;
1603
+ const fallbackCheck = {
1604
+ flag: key,
1605
+ reason: "Fallback",
1606
+ value: fallback
1607
+ };
1608
+ const flagCheck = ref(
1609
+ client.getFlagCheck(key) ?? fallbackCheck
1610
+ );
1611
+ let unsubscribe = null;
1612
+ onMounted(() => {
1613
+ unsubscribe = client.addFlagCheckListener(key, (check) => {
1614
+ flagCheck.value = check;
1615
+ });
1616
+ });
1617
+ onScopeDispose2(() => {
1618
+ unsubscribe?.();
1619
+ });
1620
+ return {
1621
+ // Full check object
1622
+ check: computed(() => flagCheck.value),
1623
+ // Individual properties as computed refs
1624
+ value: computed(() => flagCheck.value.value),
1625
+ flag: computed(() => flagCheck.value.flag),
1626
+ reason: computed(() => flagCheck.value.reason),
1627
+ featureUsage: computed(() => flagCheck.value.featureUsage),
1628
+ featureAllocation: computed(() => flagCheck.value.featureAllocation),
1629
+ featureUsageExceeded: computed(() => flagCheck.value.featureUsageExceeded),
1630
+ featureUsageEvent: computed(() => flagCheck.value.featureUsageEvent),
1631
+ featureUsagePeriod: computed(() => flagCheck.value.featureUsagePeriod),
1632
+ flagId: computed(() => flagCheck.value.flagId),
1633
+ ruleId: computed(() => flagCheck.value.ruleId),
1634
+ companyId: computed(() => flagCheck.value.companyId),
1635
+ userId: computed(() => flagCheck.value.userId)
1636
+ };
1637
+ };
1638
+ var useSchematicIsPending = (opts) => {
1639
+ const client = useSchematicClient(opts);
1640
+ const isPending = ref(client.getIsPending());
1641
+ let unsubscribe = null;
1642
+ onMounted(() => {
1643
+ unsubscribe = client.addIsPendingListener((value) => {
1644
+ isPending.value = value;
1645
+ });
1646
+ });
1647
+ onScopeDispose2(() => {
1648
+ unsubscribe?.();
1649
+ });
1650
+ return isPending;
1651
+ };
1652
+ export {
1653
+ RuleType,
1654
+ Schematic,
1655
+ SchematicPlugin,
1656
+ UsagePeriod,
1657
+ useSchematic,
1658
+ useSchematicClient,
1659
+ useSchematicContext,
1660
+ useSchematicEntitlement,
1661
+ useSchematicEvents,
1662
+ useSchematicFlag,
1663
+ useSchematicIsPending
1664
+ };
1665
+ /*! Bundled license information:
1666
+
1667
+ @schematichq/schematic-js/dist/schematic.esm.js:
1668
+ (* @preserve *)
1669
+ */