@statezero/core 0.2.56 → 0.2.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adaptors/vue/components/StateZeroDebugPanel.js +144 -129
- package/dist/cli/commands/syncModels.js +23 -1
- package/dist/config.js +6 -2
- package/dist/core/eventReceivers.d.ts +25 -2
- package/dist/core/eventReceivers.js +17 -4
- package/dist/flavours/django/errors.d.ts +3 -1
- package/dist/flavours/django/errors.js +5 -3
- package/dist/flavours/django/manager.d.ts +7 -0
- package/dist/flavours/django/manager.js +12 -0
- package/dist/flavours/django/model.d.ts +7 -0
- package/dist/flavours/django/model.js +9 -0
- package/dist/flavours/django/querySet.d.ts +69 -3
- package/dist/flavours/django/querySet.js +40 -1
- package/package.json +1 -1
|
@@ -2,11 +2,11 @@ import { ref as J, computed as I, onMounted as hs, onBeforeUnmount as fs, watch
|
|
|
2
2
|
import { v7 as B } from "uuid";
|
|
3
3
|
import { isNil as b, isEmpty as Te, trim as dt, isEqual as He } from "lodash-es";
|
|
4
4
|
import Oe from "mitt";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import Pt from "handlebars";
|
|
6
|
+
import Ft from "superjson";
|
|
7
7
|
import ps from "p-queue";
|
|
8
8
|
import ms from "axios";
|
|
9
|
-
import { z as
|
|
9
|
+
import { z as O } from "zod";
|
|
10
10
|
import ys from "pusher-js";
|
|
11
11
|
import Wt, { createEqualsOperation as ee } from "sift";
|
|
12
12
|
import { DateTime as _e } from "luxon";
|
|
@@ -47,9 +47,9 @@ function Je(n) {
|
|
|
47
47
|
const e = Object.fromEntries(se);
|
|
48
48
|
try {
|
|
49
49
|
if (typeof n == "string")
|
|
50
|
-
return
|
|
51
|
-
const t =
|
|
52
|
-
return
|
|
50
|
+
return Pt.compile(n, { noEscape: !0 })(e);
|
|
51
|
+
const t = Ft.stringify(n), r = Pt.compile(t, { noEscape: !0 })(e);
|
|
52
|
+
return Ft.parse(r);
|
|
53
53
|
} catch {
|
|
54
54
|
return n;
|
|
55
55
|
}
|
|
@@ -363,7 +363,7 @@ class Ss {
|
|
|
363
363
|
*/
|
|
364
364
|
_loadOperations(e) {
|
|
365
365
|
e.forEach((t) => {
|
|
366
|
-
const s =
|
|
366
|
+
const s = Pe.get(t.operationId);
|
|
367
367
|
s ? this.operationsMap.set(s.operationId, s) : this.operationsMap.set(t.operationId, new q(t, !0));
|
|
368
368
|
});
|
|
369
369
|
}
|
|
@@ -480,7 +480,7 @@ class Ss {
|
|
|
480
480
|
if (r.push(...Array.from(s.values())), this.groundTruthArray = r, i.length > 0) {
|
|
481
481
|
const l = /* @__PURE__ */ new Set();
|
|
482
482
|
for (const c of this.operations)
|
|
483
|
-
if ((c.type ===
|
|
483
|
+
if ((c.type === F.UPDATE || c.type === F.UPDATE_INSTANCE) && c.status !== C.CONFIRMED && c.status !== C.REJECTED)
|
|
484
484
|
for (const h of c.instances)
|
|
485
485
|
h && h[t] != null && l.add(h[t]);
|
|
486
486
|
const a = i.filter(
|
|
@@ -489,7 +489,7 @@ class Ss {
|
|
|
489
489
|
if (a.length > 0) {
|
|
490
490
|
const c = new q({
|
|
491
491
|
operationId: `checkpoint_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
492
|
-
type:
|
|
492
|
+
type: F.CHECKPOINT,
|
|
493
493
|
instances: a,
|
|
494
494
|
status: C.CONFIRMED,
|
|
495
495
|
timestamp: Date.now(),
|
|
@@ -553,21 +553,21 @@ class Ss {
|
|
|
553
553
|
}
|
|
554
554
|
let o = r[s];
|
|
555
555
|
switch (e.type) {
|
|
556
|
-
case
|
|
557
|
-
case
|
|
556
|
+
case F.CREATE:
|
|
557
|
+
case F.BULK_CREATE:
|
|
558
558
|
t.has(o) || t.set(o, r);
|
|
559
559
|
break;
|
|
560
|
-
case
|
|
561
|
-
case
|
|
562
|
-
case
|
|
560
|
+
case F.CHECKPOINT:
|
|
561
|
+
case F.UPDATE_INSTANCE:
|
|
562
|
+
case F.UPDATE: {
|
|
563
563
|
const i = t.get(o);
|
|
564
564
|
i ? t.set(o, { ...i, ...r }) : this.operations.some(
|
|
565
|
-
(a) => a.type ===
|
|
565
|
+
(a) => a.type === F.DELETE && a.status !== C.REJECTED && a.instances.some((c) => c && c[s] === o)
|
|
566
566
|
) || t.set(o, r);
|
|
567
567
|
break;
|
|
568
568
|
}
|
|
569
|
-
case
|
|
570
|
-
case
|
|
569
|
+
case F.DELETE_INSTANCE:
|
|
570
|
+
case F.DELETE:
|
|
571
571
|
t.delete(o);
|
|
572
572
|
break;
|
|
573
573
|
default:
|
|
@@ -726,7 +726,7 @@ const j = new Ve(), ie = Oe(), C = {
|
|
|
726
726
|
REJECTED: "operation:rejected",
|
|
727
727
|
CLEAR: "clear:all",
|
|
728
728
|
MUTATED: "operation:mutated"
|
|
729
|
-
},
|
|
729
|
+
}, F = {
|
|
730
730
|
CREATE: "create",
|
|
731
731
|
BULK_CREATE: "bulk_create",
|
|
732
732
|
UPDATE: "update",
|
|
@@ -763,7 +763,7 @@ class q {
|
|
|
763
763
|
throw new Error(`All operation instances must be objects with the '${o}' field`);
|
|
764
764
|
this.#e = r;
|
|
765
765
|
const i = r.map((a) => a[o]);
|
|
766
|
-
j.getStore(s).render(i, !0, !1), this.#t = r.map((a) => s.fromPk(a[o]).serialize()), this.timestamp = e.timestamp || Date.now(), !t && (
|
|
766
|
+
j.getStore(s).render(i, !0, !1), this.#t = r.map((a) => s.fromPk(a[o]).serialize()), this.timestamp = e.timestamp || Date.now(), !t && (Pe.register(this), ie.emit(C.CREATED, this));
|
|
767
767
|
}
|
|
768
768
|
/**
|
|
769
769
|
* Getter for instances that replaces any temporary PKs with real PKs
|
|
@@ -915,7 +915,7 @@ class Ts {
|
|
|
915
915
|
return t.length > 0 ? t[t.length - 1] : void 0;
|
|
916
916
|
}
|
|
917
917
|
}
|
|
918
|
-
const
|
|
918
|
+
const Pe = new Ts(), Ms = Oe();
|
|
919
919
|
function As(n) {
|
|
920
920
|
Ms.emit("error", n);
|
|
921
921
|
}
|
|
@@ -927,9 +927,10 @@ class fe extends Error {
|
|
|
927
927
|
* @param {string} code - The error code.
|
|
928
928
|
* @param {IErrorDetail|Object|string} detail - The error details.
|
|
929
929
|
* @param {number} status - The HTTP status code.
|
|
930
|
+
* @param {Object} [data={}] - Additional structured data from the server.
|
|
930
931
|
*/
|
|
931
|
-
constructor(e, t, s, r) {
|
|
932
|
-
super(e), this.name = "StateZeroError", this.code = t, this.detail = s, this.status = r, Object.setPrototypeOf(this, new.target.prototype), As(this);
|
|
932
|
+
constructor(e, t, s, r, o = {}) {
|
|
933
|
+
super(e), this.name = "StateZeroError", this.code = t, this.detail = s, this.status = r, this.data = o, Object.setPrototypeOf(this, new.target.prototype), As(this);
|
|
933
934
|
}
|
|
934
935
|
/**
|
|
935
936
|
* Returns a full error message including the detail.
|
|
@@ -1028,8 +1029,8 @@ class U extends fe {
|
|
|
1028
1029
|
super("Configuration error", "config_error", e, t), this.name = "ConfigError";
|
|
1029
1030
|
}
|
|
1030
1031
|
}
|
|
1031
|
-
function
|
|
1032
|
-
const { status: e, type: t, detail: s } = n;
|
|
1032
|
+
function Ps(n) {
|
|
1033
|
+
const { status: e, type: t, detail: s, data: r } = n;
|
|
1033
1034
|
if (t === void 0 && s === "Invalid token.")
|
|
1034
1035
|
return new lt(s, 403);
|
|
1035
1036
|
switch (t) {
|
|
@@ -1054,7 +1055,13 @@ function Fs(n) {
|
|
|
1054
1055
|
case "ValueError":
|
|
1055
1056
|
return new $e(s, e);
|
|
1056
1057
|
default:
|
|
1057
|
-
return e === 400 ? new $e(s, e) : e === 403 ? new lt(s, e) : e === 404 ? new It(s, e) : e === 409 ? new Nt(s, e) : new fe(
|
|
1058
|
+
return e === 400 ? new $e(s, e) : e === 403 ? new lt(s, e) : e === 404 ? new It(s, e) : e === 409 ? new Nt(s, e) : new fe(
|
|
1059
|
+
s || "Unknown error",
|
|
1060
|
+
t || "unknown",
|
|
1061
|
+
s,
|
|
1062
|
+
e,
|
|
1063
|
+
r || {}
|
|
1064
|
+
);
|
|
1058
1065
|
}
|
|
1059
1066
|
}
|
|
1060
1067
|
const xt = {
|
|
@@ -1065,7 +1072,7 @@ const xt = {
|
|
|
1065
1072
|
BULK_UPDATE: "bulk_update",
|
|
1066
1073
|
BULK_DELETE: "bulk_delete"
|
|
1067
1074
|
};
|
|
1068
|
-
class
|
|
1075
|
+
class Fs {
|
|
1069
1076
|
/**
|
|
1070
1077
|
* @param {PusherReceiverOptions} options
|
|
1071
1078
|
* @param {string} configKey - The backend configuration key
|
|
@@ -1075,12 +1082,13 @@ class Ps {
|
|
|
1075
1082
|
this.configKey = t, this.connectionTimeoutId = null, s.appKey && /^\d+$/.test(s.appKey) && s.appKey.length < 15 && console.warn(
|
|
1076
1083
|
`%c[Pusher Warning] The provided appKey ("${s.appKey}") looks like a numeric app_id. Pusher requires the alphanumeric key, not the ID. Please verify your configuration for backend: "${this.configKey}".`,
|
|
1077
1084
|
"color: orange; font-weight: bold; font-size: 14px;"
|
|
1078
|
-
)
|
|
1079
|
-
|
|
1085
|
+
);
|
|
1086
|
+
const l = {
|
|
1080
1087
|
forceTLS: s.forceTLS ?? !0,
|
|
1081
1088
|
authEndpoint: s.authEndpoint,
|
|
1082
1089
|
auth: { headers: s.getAuthHeaders?.() || {} }
|
|
1083
|
-
}
|
|
1090
|
+
};
|
|
1091
|
+
s.wsHost ? (l.wsHost = s.wsHost, l.wsPort = s.wsPort ?? 443, l.wssPort = s.wssPort ?? 443, l.enabledTransports = s.enabledTransports ?? ["ws", "wss"]) : l.cluster = s.cluster, this.pusherClient = new ys(s.appKey, l), this.pusherClient.connection.bind("connected", () => {
|
|
1084
1092
|
console.log(
|
|
1085
1093
|
`Pusher client connected successfully for backend: ${this.configKey}.`
|
|
1086
1094
|
), this.connectionTimeoutId && (clearTimeout(this.connectionTimeoutId), this.connectionTimeoutId = null);
|
|
@@ -1090,7 +1098,7 @@ class Ps {
|
|
|
1090
1098
|
this.pusherClient.connection.state !== "connected" && this._logConnectionError(
|
|
1091
1099
|
`Pusher connection timed out after ${i / 1e3} seconds.`
|
|
1092
1100
|
);
|
|
1093
|
-
}, i), this.formatChannelName = r ?? ((
|
|
1101
|
+
}, i), this.formatChannelName = r ?? ((a) => `private-${a}`), this.namespaceResolver = o ?? ((a) => a), this.channels = /* @__PURE__ */ new Map(), this.eventHandlers = /* @__PURE__ */ new Set();
|
|
1094
1102
|
}
|
|
1095
1103
|
/**
|
|
1096
1104
|
* @private
|
|
@@ -1226,53 +1234,60 @@ function zs() {
|
|
|
1226
1234
|
let Ut = {
|
|
1227
1235
|
backendConfigs: {}
|
|
1228
1236
|
};
|
|
1229
|
-
const Rs =
|
|
1230
|
-
clientOptions:
|
|
1231
|
-
appKey:
|
|
1232
|
-
cluster:
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1237
|
+
const Rs = O.object({
|
|
1238
|
+
clientOptions: O.object({
|
|
1239
|
+
appKey: O.string({ required_error: "Pusher appKey is required" }),
|
|
1240
|
+
cluster: O.string().optional(),
|
|
1241
|
+
wsHost: O.string().optional(),
|
|
1242
|
+
wsPort: O.number().optional(),
|
|
1243
|
+
wssPort: O.number().optional(),
|
|
1244
|
+
enabledTransports: O.array(O.string()).optional(),
|
|
1245
|
+
forceTLS: O.boolean().optional(),
|
|
1246
|
+
authEndpoint: O.string().url("Pusher authentication endpoint URL is required"),
|
|
1247
|
+
getAuthHeaders: O.function().optional().refine(
|
|
1236
1248
|
(n) => n === void 0 || typeof n == "function",
|
|
1237
1249
|
"getAuthHeaders must be a function if provided"
|
|
1238
1250
|
)
|
|
1239
|
-
})
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1251
|
+
}).refine(
|
|
1252
|
+
(n) => n.cluster || n.wsHost,
|
|
1253
|
+
"Either cluster or wsHost must be provided"
|
|
1254
|
+
)
|
|
1255
|
+
}), Ks = O.object({
|
|
1256
|
+
type: O.enum(["websocket", "pusher", "none"]),
|
|
1257
|
+
websocketUrl: O.string().url().optional(),
|
|
1243
1258
|
pusher: Rs.optional(),
|
|
1244
|
-
hotpaths:
|
|
1259
|
+
hotpaths: O.array(O.string()).default(["default"])
|
|
1245
1260
|
}).superRefine((n, e) => {
|
|
1246
1261
|
n.type === "websocket" && (n.websocketUrl || e.addIssue({
|
|
1247
|
-
code:
|
|
1262
|
+
code: O.ZodIssueCode.custom,
|
|
1248
1263
|
path: ["websocketUrl"],
|
|
1249
1264
|
message: "WebSocket URL is required for WebSocket event receiver"
|
|
1250
1265
|
})), n.type === "pusher" && (n.pusher || e.addIssue({
|
|
1251
|
-
code:
|
|
1266
|
+
code: O.ZodIssueCode.custom,
|
|
1252
1267
|
path: ["pusher"],
|
|
1253
1268
|
message: "Pusher configuration is required for Pusher event receiver"
|
|
1254
1269
|
}));
|
|
1255
|
-
}), Be =
|
|
1256
|
-
API_URL:
|
|
1257
|
-
GENERATED_TYPES_DIR:
|
|
1270
|
+
}), Be = O.object({
|
|
1271
|
+
API_URL: O.string().url("API_URL must be a valid URL"),
|
|
1272
|
+
GENERATED_TYPES_DIR: O.string({
|
|
1258
1273
|
required_error: "GENERATED_TYPES_DIR is required"
|
|
1259
1274
|
}),
|
|
1260
|
-
GENERATED_ACTIONS_DIR:
|
|
1261
|
-
BACKEND_TZ:
|
|
1262
|
-
SYNC_TOKEN:
|
|
1263
|
-
fileRootURL:
|
|
1264
|
-
fileUploadMode:
|
|
1265
|
-
getAuthHeaders:
|
|
1275
|
+
GENERATED_ACTIONS_DIR: O.string().optional(),
|
|
1276
|
+
BACKEND_TZ: O.string().optional(),
|
|
1277
|
+
SYNC_TOKEN: O.string().optional(),
|
|
1278
|
+
fileRootURL: O.string().url("fileRootURL must be a valid URL").optional(),
|
|
1279
|
+
fileUploadMode: O.enum(["server", "s3"]).default("server"),
|
|
1280
|
+
getAuthHeaders: O.function().optional().refine(
|
|
1266
1281
|
(n) => n === void 0 || typeof n == "function",
|
|
1267
1282
|
"getAuthHeaders must be a function if provided"
|
|
1268
1283
|
),
|
|
1269
|
-
eventInterceptor:
|
|
1284
|
+
eventInterceptor: O.function().optional().refine(
|
|
1270
1285
|
(n) => n === void 0 || typeof n == "function",
|
|
1271
1286
|
"eventInterceptor must be a function if provided"
|
|
1272
1287
|
),
|
|
1273
|
-
events:
|
|
1274
|
-
}), Is =
|
|
1275
|
-
backendConfigs:
|
|
1288
|
+
events: O.lazy(() => Ks.optional())
|
|
1289
|
+
}), Is = O.object({
|
|
1290
|
+
backendConfigs: O.record(O.string(), Be).refine(
|
|
1276
1291
|
(n) => {
|
|
1277
1292
|
for (const [e, t] of Object.entries(n))
|
|
1278
1293
|
if (!Be.safeParse(t).success)
|
|
@@ -1291,7 +1306,7 @@ const Rs = $.object({
|
|
|
1291
1306
|
return { message: e.join("; ") };
|
|
1292
1307
|
}
|
|
1293
1308
|
),
|
|
1294
|
-
periodicSyncIntervalSeconds:
|
|
1309
|
+
periodicSyncIntervalSeconds: O.number().min(5).nullable().optional().default(null)
|
|
1295
1310
|
});
|
|
1296
1311
|
let ht = null;
|
|
1297
1312
|
function Ns(n) {
|
|
@@ -1345,7 +1360,7 @@ function Yt(n = "default") {
|
|
|
1345
1360
|
...t.events.pusher.clientOptions,
|
|
1346
1361
|
getAuthHeaders: i
|
|
1347
1362
|
};
|
|
1348
|
-
s = new
|
|
1363
|
+
s = new Fs({ clientOptions: l }, n);
|
|
1349
1364
|
break;
|
|
1350
1365
|
case "none":
|
|
1351
1366
|
return null;
|
|
@@ -1549,8 +1564,8 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1549
1564
|
query: _,
|
|
1550
1565
|
serializerOptions: y
|
|
1551
1566
|
}
|
|
1552
|
-
}, v = w?.ast?.serializerOptions?.limit,
|
|
1553
|
-
v &&
|
|
1567
|
+
}, v = w?.ast?.serializerOptions?.limit, $ = w?.ast?.serializerOptions?.overfetch || 10;
|
|
1568
|
+
v && $ && (w.ast.serializerOptions.limit = v + $);
|
|
1554
1569
|
const k = [
|
|
1555
1570
|
"create",
|
|
1556
1571
|
"bulk_create",
|
|
@@ -1560,7 +1575,7 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1560
1575
|
"delete_instance",
|
|
1561
1576
|
"get_or_create",
|
|
1562
1577
|
"update_or_create"
|
|
1563
|
-
].includes(e), Q = `${p.API_URL.replace(/\/+$/, "")}/${c.modelName}/`, N = p.getAuthHeaders ? p.getAuthHeaders() : {},
|
|
1578
|
+
].includes(e), Q = `${p.API_URL.replace(/\/+$/, "")}/${c.modelName}/`, N = p.getAuthHeaders ? p.getAuthHeaders() : {}, P = n.semanticKey;
|
|
1564
1579
|
s && (N["X-Operation-ID"] = s), o && (N["X-Canonical-ID"] = o);
|
|
1565
1580
|
const re = async () => {
|
|
1566
1581
|
try {
|
|
@@ -1568,7 +1583,7 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1568
1583
|
type: "request",
|
|
1569
1584
|
modelName: c.modelName,
|
|
1570
1585
|
configKey: c.configKey,
|
|
1571
|
-
semanticKey:
|
|
1586
|
+
semanticKey: P,
|
|
1572
1587
|
operationType: e,
|
|
1573
1588
|
operationId: s,
|
|
1574
1589
|
canonicalId: o,
|
|
@@ -1594,7 +1609,7 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1594
1609
|
type: "response",
|
|
1595
1610
|
modelName: c.modelName,
|
|
1596
1611
|
configKey: c.configKey,
|
|
1597
|
-
semanticKey:
|
|
1612
|
+
semanticKey: P,
|
|
1598
1613
|
operationType: e,
|
|
1599
1614
|
operationId: s,
|
|
1600
1615
|
canonicalId: o,
|
|
@@ -1612,7 +1627,7 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1612
1627
|
type: "error",
|
|
1613
1628
|
modelName: c.modelName,
|
|
1614
1629
|
configKey: c.configKey,
|
|
1615
|
-
semanticKey:
|
|
1630
|
+
semanticKey: P,
|
|
1616
1631
|
operationType: e,
|
|
1617
1632
|
operationId: s,
|
|
1618
1633
|
canonicalId: o,
|
|
@@ -1624,7 +1639,7 @@ async function V(n, e, t = {}, s, r = null, o = null, i = {}) {
|
|
|
1624
1639
|
throw new Error(`${D} (${Q})`);
|
|
1625
1640
|
}
|
|
1626
1641
|
if (z.response && z.response.data) {
|
|
1627
|
-
const D =
|
|
1642
|
+
const D = Ps(z.response.data);
|
|
1628
1643
|
throw Error.captureStackTrace && Error.captureStackTrace(D, V), D;
|
|
1629
1644
|
}
|
|
1630
1645
|
throw new Error(`API call failed: ${z.message}`);
|
|
@@ -1959,11 +1974,11 @@ function ze(n, e, t, s = {}) {
|
|
|
1959
1974
|
E === "pk" && p && (E = p.primaryKeyField);
|
|
1960
1975
|
const Q = k === c.length - 1;
|
|
1961
1976
|
if (p && p.relationshipFields && p.relationshipFields instanceof Map && p.relationshipFields.has(E)) {
|
|
1962
|
-
const N = p.relationshipFields.get(E),
|
|
1977
|
+
const N = p.relationshipFields.get(E), P = N.ModelClass(), re = N.relationshipType;
|
|
1963
1978
|
if (!Q && re === "many-to-many") {
|
|
1964
1979
|
let ae = c.slice(k + 1).join("__");
|
|
1965
1980
|
a.length > 0 ? ae += "__" + a.join("__") : h && (ae += "__" + h);
|
|
1966
|
-
const z = ze(ae, e,
|
|
1981
|
+
const z = ze(ae, e, P, s), D = m.length > 0 ? m.join(".") + "." + E : E, K = z.requiredPath || z.field, me = `${D}.${K}`;
|
|
1967
1982
|
return {
|
|
1968
1983
|
field: D,
|
|
1969
1984
|
operator: { $elemMatch: { [z.field]: z.operator } },
|
|
@@ -1973,23 +1988,23 @@ function ze(n, e, t, s = {}) {
|
|
|
1973
1988
|
};
|
|
1974
1989
|
}
|
|
1975
1990
|
if (m.push(E), !Q)
|
|
1976
|
-
p =
|
|
1991
|
+
p = P;
|
|
1977
1992
|
else {
|
|
1978
1993
|
if (y = !0, re === "many-to-many")
|
|
1979
1994
|
_ = !0, w = E;
|
|
1980
1995
|
else {
|
|
1981
|
-
const pe =
|
|
1996
|
+
const pe = P.primaryKeyField || "id";
|
|
1982
1997
|
m.push(pe), w = pe;
|
|
1983
1998
|
}
|
|
1984
|
-
p =
|
|
1999
|
+
p = P;
|
|
1985
2000
|
}
|
|
1986
2001
|
} else if (p && p.fields && p.fields.includes(E)) {
|
|
1987
2002
|
if (m.push(E), w = E, Q)
|
|
1988
2003
|
break;
|
|
1989
2004
|
const N = p.schema?.properties?.[E];
|
|
1990
2005
|
if (N && N.format === "json") {
|
|
1991
|
-
const
|
|
1992
|
-
m.push(...
|
|
2006
|
+
const P = c.slice(k + 1);
|
|
2007
|
+
m.push(...P);
|
|
1993
2008
|
break;
|
|
1994
2009
|
}
|
|
1995
2010
|
throw new Error(`Field '${E}' in '${n}' is not a relationship field and cannot be traversed.`);
|
|
@@ -2186,17 +2201,17 @@ function tr(n = "UTC", e = null) {
|
|
|
2186
2201
|
if (!y || !(y instanceof Date) || isNaN(y.getTime()))
|
|
2187
2202
|
return !1;
|
|
2188
2203
|
const _ = _e.fromJSDate(y).setZone(n);
|
|
2189
|
-
let w, v,
|
|
2204
|
+
let w, v, $;
|
|
2190
2205
|
if (typeof a == "string") {
|
|
2191
2206
|
const T = a.split(":");
|
|
2192
|
-
w = parseInt(T[0], 10), v = parseInt(T[1], 10),
|
|
2207
|
+
w = parseInt(T[0], 10), v = parseInt(T[1], 10), $ = parseInt(T[2], 10);
|
|
2193
2208
|
} else {
|
|
2194
2209
|
const T = s(a, m);
|
|
2195
2210
|
if (!T) return !1;
|
|
2196
2211
|
const k = _e.fromJSDate(T).setZone(n);
|
|
2197
|
-
w = k.hour, v = k.minute,
|
|
2212
|
+
w = k.hour, v = k.minute, $ = k.second;
|
|
2198
2213
|
}
|
|
2199
|
-
return _.hour === w && _.minute === v && _.second ===
|
|
2214
|
+
return _.hour === w && _.minute === v && _.second === $;
|
|
2200
2215
|
},
|
|
2201
2216
|
c,
|
|
2202
2217
|
h
|
|
@@ -2223,7 +2238,7 @@ function tr(n = "UTC", e = null) {
|
|
|
2223
2238
|
const v = s(_, w);
|
|
2224
2239
|
if (!v || !(v instanceof Date) || isNaN(v.getTime()))
|
|
2225
2240
|
return !1;
|
|
2226
|
-
const
|
|
2241
|
+
const $ = _e.fromJSDate(v).setZone(n), T = c($), k = a === "date" ? p : typeof p == "string" ? Number(p) : p;
|
|
2227
2242
|
switch (h) {
|
|
2228
2243
|
case "gt":
|
|
2229
2244
|
return T > k;
|
|
@@ -2466,7 +2481,7 @@ class ar {
|
|
|
2466
2481
|
constructor(e, t, s, r = null, o = null, i = {}) {
|
|
2467
2482
|
if (this.modelClass = e, this.fetchFn = t, this.queryset = s, this.isSyncing = !1, this.lastSync = null, this.lastHydrated = null, this._createdAt = Date.now(), this.isTemp = i.isTemp || !1, this.pruneThreshold = i.pruneThreshold || 10, this.groundTruthPks = r || [], this.operationsMap = /* @__PURE__ */ new Map(), this.includedPks = /* @__PURE__ */ new Map(), Array.isArray(o))
|
|
2468
2483
|
for (const l of o) {
|
|
2469
|
-
const c =
|
|
2484
|
+
const c = Pe.get(l.operationId) || new q(l, !0);
|
|
2470
2485
|
this.operationsMap.set(c.operationId, c);
|
|
2471
2486
|
}
|
|
2472
2487
|
if (this.qsCache = new Ct("queryset-cache", {}, this.onHydrated.bind(this)), this._lastRenderedPks = null, this.renderCallbacks = /* @__PURE__ */ new Set(), !this.isTemp) {
|
|
@@ -2599,7 +2614,7 @@ class ar {
|
|
|
2599
2614
|
if (a == null) return null;
|
|
2600
2615
|
const c = this.pkField, h = new Set(e), p = new Set(e);
|
|
2601
2616
|
for (const m of s.operations)
|
|
2602
|
-
if (m.status !== C.REJECTED && !(!t && m.status !== C.CONFIRMED) && !(m.type !==
|
|
2617
|
+
if (m.status !== C.REJECTED && !(!t && m.status !== C.CONFIRMED) && !(m.type !== F.CREATE && m.type !== F.BULK_CREATE && m.type !== F.GET_OR_CREATE && m.type !== F.UPDATE_OR_CREATE))
|
|
2603
2618
|
for (const y of m.instances) {
|
|
2604
2619
|
if (!y || y[c] == null || h.has(y[c])) continue;
|
|
2605
2620
|
const _ = y[o];
|
|
@@ -3060,7 +3075,7 @@ class Ce {
|
|
|
3060
3075
|
});
|
|
3061
3076
|
return;
|
|
3062
3077
|
}
|
|
3063
|
-
const v = p.pks.map((k) => i.fromPk(k, e)),
|
|
3078
|
+
const v = p.pks.map((k) => i.fromPk(k, e)), $ = e.build(), T = ss(v, $, i, !1);
|
|
3064
3079
|
m.setGroundTruth(T), m.setOperations(m.getInflightOperations()), m.lastSync = Date.now(), G({
|
|
3065
3080
|
type: "groupSync",
|
|
3066
3081
|
phase: "filteredFromRoot",
|
|
@@ -3229,7 +3244,7 @@ class de {
|
|
|
3229
3244
|
const o = e.ModelClass.primaryKeyField, i = s || `${B()}`, l = zt(i);
|
|
3230
3245
|
return new q({
|
|
3231
3246
|
operationId: i,
|
|
3232
|
-
type:
|
|
3247
|
+
type: F.CREATE,
|
|
3233
3248
|
instances: [{ ...t, [o]: l }],
|
|
3234
3249
|
queryset: e,
|
|
3235
3250
|
args: { data: t },
|
|
@@ -3250,7 +3265,7 @@ class de {
|
|
|
3250
3265
|
});
|
|
3251
3266
|
return new q({
|
|
3252
3267
|
operationId: i,
|
|
3253
|
-
type:
|
|
3268
|
+
type: F.BULK_CREATE,
|
|
3254
3269
|
instances: l,
|
|
3255
3270
|
queryset: e,
|
|
3256
3271
|
args: { data: t },
|
|
@@ -3279,7 +3294,7 @@ class de {
|
|
|
3279
3294
|
});
|
|
3280
3295
|
return new q({
|
|
3281
3296
|
operationId: c,
|
|
3282
|
-
type:
|
|
3297
|
+
type: F.UPDATE,
|
|
3283
3298
|
instances: h,
|
|
3284
3299
|
queryset: e,
|
|
3285
3300
|
args: { filter: s, data: t },
|
|
@@ -3296,7 +3311,7 @@ class de {
|
|
|
3296
3311
|
const r = e.ModelClass.primaryKeyField, i = x.getStore(e).render(), l = t || `${B()}`, a = i.map((c) => ({ [r]: c }));
|
|
3297
3312
|
return new q({
|
|
3298
3313
|
operationId: l,
|
|
3299
|
-
type:
|
|
3314
|
+
type: F.DELETE,
|
|
3300
3315
|
instances: a,
|
|
3301
3316
|
queryset: e,
|
|
3302
3317
|
args: {},
|
|
@@ -3314,7 +3329,7 @@ class de {
|
|
|
3314
3329
|
const o = e.ModelClass.primaryKeyField, l = x.getStore(e).render(), a = s || `${B()}`, c = l.map((h) => ({ ...t, [o]: h }));
|
|
3315
3330
|
return new q({
|
|
3316
3331
|
operationId: a,
|
|
3317
|
-
type:
|
|
3332
|
+
type: F.UPDATE_INSTANCE,
|
|
3318
3333
|
instances: c,
|
|
3319
3334
|
queryset: e,
|
|
3320
3335
|
args: { data: t },
|
|
@@ -3332,7 +3347,7 @@ class de {
|
|
|
3332
3347
|
const r = s || `${B()}`;
|
|
3333
3348
|
return new q({
|
|
3334
3349
|
operationId: r,
|
|
3335
|
-
type:
|
|
3350
|
+
type: F.DELETE_INSTANCE,
|
|
3336
3351
|
instances: [t],
|
|
3337
3352
|
queryset: e,
|
|
3338
3353
|
args: t,
|
|
@@ -3352,7 +3367,7 @@ class de {
|
|
|
3352
3367
|
(E) => _t(y, o.fromPk(E[i], e))
|
|
3353
3368
|
), w = mt(_, m, o), v = c.filter(
|
|
3354
3369
|
(E) => w.includes(E[i])
|
|
3355
|
-
),
|
|
3370
|
+
), $ = v.length === 0, T = $ ? F.CREATE : F.UPDATE, k = $ ? { ...t, ...s, [i]: l } : v[0];
|
|
3356
3371
|
return new q({
|
|
3357
3372
|
operationId: l,
|
|
3358
3373
|
type: T,
|
|
@@ -3375,7 +3390,7 @@ class de {
|
|
|
3375
3390
|
(E) => _t(y, o.fromPk(E[i], e))
|
|
3376
3391
|
), w = mt(_, m, o), v = c.filter(
|
|
3377
3392
|
(E) => w.includes(E[i])
|
|
3378
|
-
),
|
|
3393
|
+
), $ = v.length === 0, T = $ ? F.CREATE : F.UPDATE, k = $ ? { ...t, ...s, [i]: l } : { ...v[0], ...s };
|
|
3379
3394
|
return new q({
|
|
3380
3395
|
operationId: l,
|
|
3381
3396
|
type: T,
|
|
@@ -3467,9 +3482,9 @@ class hr {
|
|
|
3467
3482
|
).then((m) => {
|
|
3468
3483
|
const { data: y, included: _, model_name: w } = m.data, v = m.metadata.created;
|
|
3469
3484
|
we(j, _, r, e);
|
|
3470
|
-
const
|
|
3471
|
-
a && (c.pk =
|
|
3472
|
-
const k = (_[w] || {})[
|
|
3485
|
+
const $ = Array.isArray(y) ? y[0] : y;
|
|
3486
|
+
a && (c.pk = $);
|
|
3487
|
+
const k = (_[w] || {})[$];
|
|
3473
3488
|
return k && l.mutate({
|
|
3474
3489
|
instances: [k],
|
|
3475
3490
|
status: C.CONFIRMED
|
|
@@ -3493,7 +3508,7 @@ class hr {
|
|
|
3493
3508
|
throw new Error(
|
|
3494
3509
|
`Field parameter is required for ${t} operation`
|
|
3495
3510
|
);
|
|
3496
|
-
const i =
|
|
3511
|
+
const i = Fe.getEntity(t, e, o), l = {};
|
|
3497
3512
|
t !== "exists" && (l.field = o);
|
|
3498
3513
|
const a = V(
|
|
3499
3514
|
e,
|
|
@@ -3501,7 +3516,7 @@ class hr {
|
|
|
3501
3516
|
l
|
|
3502
3517
|
).then((c) => {
|
|
3503
3518
|
const h = c.data, p = x.getEntity(e);
|
|
3504
|
-
return
|
|
3519
|
+
return Fe.setEntity(t, e, o, h, p), Z(i), h;
|
|
3505
3520
|
});
|
|
3506
3521
|
return te(i, a);
|
|
3507
3522
|
}
|
|
@@ -3545,7 +3560,7 @@ class hr {
|
|
|
3545
3560
|
i,
|
|
3546
3561
|
l.operationId
|
|
3547
3562
|
).then((p) => {
|
|
3548
|
-
const { data: m, included: y } = p.data || {}, _ = y[o] || {}, w = Array.isArray(m) ? m.map((
|
|
3563
|
+
const { data: m, included: y } = p.data || {}, _ = y[o] || {}, w = Array.isArray(m) ? m.map(($) => _[`${$}`]) : [];
|
|
3549
3564
|
l.updateStatus(C.CONFIRMED, w);
|
|
3550
3565
|
const v = p.metadata?.updated_count ?? 0;
|
|
3551
3566
|
return c = [v, { [o]: v }, w], Z(c), c;
|
|
@@ -3610,13 +3625,13 @@ class hr {
|
|
|
3610
3625
|
we(j, y, r, e);
|
|
3611
3626
|
const w = Array.isArray(m) ? m[0] : m;
|
|
3612
3627
|
c.pk = w;
|
|
3613
|
-
const
|
|
3614
|
-
if (
|
|
3628
|
+
const $ = (y[_] || {})[w];
|
|
3629
|
+
if (!$)
|
|
3615
3630
|
throw new Error(
|
|
3616
3631
|
`Entity data not found for ${_} with pk ${w}`
|
|
3617
3632
|
);
|
|
3618
3633
|
return l.mutate({
|
|
3619
|
-
instances: [
|
|
3634
|
+
instances: [$],
|
|
3620
3635
|
status: C.CONFIRMED
|
|
3621
3636
|
}), Z(c), c;
|
|
3622
3637
|
}).catch((p) => {
|
|
@@ -3663,9 +3678,9 @@ class hr {
|
|
|
3663
3678
|
w.forEach((T, k) => {
|
|
3664
3679
|
c[k] && (c[k].pk = T);
|
|
3665
3680
|
});
|
|
3666
|
-
const v = y[_] || {},
|
|
3681
|
+
const v = y[_] || {}, $ = w.map((T) => v[T]).filter(Boolean);
|
|
3667
3682
|
return a.mutate({
|
|
3668
|
-
instances:
|
|
3683
|
+
instances: $,
|
|
3669
3684
|
status: C.CONFIRMED
|
|
3670
3685
|
}), c.forEach((T) => Z(T)), Z(c), c;
|
|
3671
3686
|
}).catch((p) => {
|
|
@@ -3807,7 +3822,7 @@ class fr {
|
|
|
3807
3822
|
* Delegates to the underlying store's sync method
|
|
3808
3823
|
*/
|
|
3809
3824
|
refreshFromDb() {
|
|
3810
|
-
return
|
|
3825
|
+
return Fe.getStore(
|
|
3811
3826
|
this.metricType,
|
|
3812
3827
|
this.queryset,
|
|
3813
3828
|
this.field
|
|
@@ -3818,7 +3833,7 @@ class fr {
|
|
|
3818
3833
|
* Called implicitly by JS when coercing to a primitive (arithmetic, template literals, etc.)
|
|
3819
3834
|
*/
|
|
3820
3835
|
valueOf() {
|
|
3821
|
-
const e =
|
|
3836
|
+
const e = Fe.getStore(
|
|
3822
3837
|
this.metricType,
|
|
3823
3838
|
this.queryset,
|
|
3824
3839
|
this.field
|
|
@@ -3934,7 +3949,7 @@ class wt {
|
|
|
3934
3949
|
return this._stores.has(e) ? this._stores.get(e).queryset : null;
|
|
3935
3950
|
}
|
|
3936
3951
|
}
|
|
3937
|
-
const
|
|
3952
|
+
const Fe = new wt();
|
|
3938
3953
|
class pr {
|
|
3939
3954
|
constructor(e) {
|
|
3940
3955
|
this.event = e.event, this.model = e.model, this.operation_id = e.operation_id, this.pk_field_name = e.pk_field_name, this.configKey = e.configKey, this.canonical_id = e.canonical_id || null, this.server_ts_ms = e.server_ts_ms || null, this.instances = e.instances?.map((t) => t && this.pk_field_name && t[this.pk_field_name] != null ? {
|
|
@@ -4059,7 +4074,7 @@ class mr {
|
|
|
4059
4074
|
* Checks the `verify` flag on membership state to determine which querysets need syncing.
|
|
4060
4075
|
*/
|
|
4061
4076
|
syncQuerysetsNeedingVerification(e) {
|
|
4062
|
-
const t =
|
|
4077
|
+
const t = Pe.getQuerysetStates(e);
|
|
4063
4078
|
if (!t) return;
|
|
4064
4079
|
const s = this.registries.get(Ce);
|
|
4065
4080
|
if (!s) return;
|
|
@@ -4090,7 +4105,7 @@ class mr {
|
|
|
4090
4105
|
operationId: e.operation_id,
|
|
4091
4106
|
socketId: e.socket_id
|
|
4092
4107
|
});
|
|
4093
|
-
let t = new pr(e), s =
|
|
4108
|
+
let t = new pr(e), s = Pe.has(t.operation_id);
|
|
4094
4109
|
if (this.registries.has(wt) && this.processMetrics(t), s) {
|
|
4095
4110
|
this.syncQuerysetsNeedingVerification(t.operation_id);
|
|
4096
4111
|
return;
|
|
@@ -4190,7 +4205,7 @@ class mr {
|
|
|
4190
4205
|
const Ae = new mr();
|
|
4191
4206
|
Ae.manageRegistry(x);
|
|
4192
4207
|
Ae.manageRegistry(j);
|
|
4193
|
-
Ae.manageRegistry(
|
|
4208
|
+
Ae.manageRegistry(Fe);
|
|
4194
4209
|
const yr = /* @__PURE__ */ new Set();
|
|
4195
4210
|
function gr(n) {
|
|
4196
4211
|
typeof n == "function" && yr.add(n);
|
|
@@ -4217,7 +4232,7 @@ const _r = (n, e) => {
|
|
|
4217
4232
|
}, Mr = {
|
|
4218
4233
|
key: 1,
|
|
4219
4234
|
class: "szd-header__badge"
|
|
4220
|
-
}, Ar = { class: "szd-header__badge" }, Or = { class: "szd-tabs" }, $r = ["onClick"],
|
|
4235
|
+
}, Ar = { class: "szd-header__badge" }, Or = { class: "szd-tabs" }, $r = ["onClick"], Pr = { class: "szd-content" }, Fr = {
|
|
4221
4236
|
key: 0,
|
|
4222
4237
|
class: "szd-panel"
|
|
4223
4238
|
}, Dr = { class: "szd-panel__section" }, zr = { class: "szd-kv" }, Rr = { class: "szd-kv__row" }, Kr = { class: "szd-kv__value" }, Ir = { class: "szd-kv__row" }, Nr = { class: "szd-kv__value" }, xr = { class: "szd-kv__row" }, jr = { class: "szd-kv__value" }, Ur = { class: "szd-kv__row" }, Qr = { class: "szd-kv__value" }, Lr = { class: "szd-panel__section" }, Vr = { class: "szd-stats" }, Br = { class: "szd-stat" }, Gr = { class: "szd-stat__value" }, Hr = { class: "szd-stat" }, qr = { class: "szd-stat__value" }, Jr = { class: "szd-stat" }, Wr = { class: "szd-stat__value" }, Zr = { class: "szd-stat" }, Yr = { class: "szd-stat__value" }, Xr = {
|
|
@@ -4259,7 +4274,7 @@ const _r = (n, e) => {
|
|
|
4259
4274
|
}, $n = {
|
|
4260
4275
|
class: "szd-kv",
|
|
4261
4276
|
style: { "margin-bottom": "16px" }
|
|
4262
|
-
},
|
|
4277
|
+
}, Pn = { class: "szd-kv__row" }, Fn = { class: "szd-kv__value szd-kv__value--mono" }, Dn = { class: "szd-ast" }, zn = {
|
|
4263
4278
|
key: 0,
|
|
4264
4279
|
class: "szd-detail"
|
|
4265
4280
|
}, Rn = { class: "szd-detail__panel szd-detail__panel--sm" }, Kn = { class: "szd-detail__header" }, In = { class: "szd-detail__body" }, Nn = { class: "szd-settings-section" }, xn = ["value"], jn = {
|
|
@@ -4320,7 +4335,7 @@ const _r = (n, e) => {
|
|
|
4320
4335
|
queryset: d
|
|
4321
4336
|
});
|
|
4322
4337
|
}), u;
|
|
4323
|
-
}),
|
|
4338
|
+
}), $ = I(() => (a.value, Array.from(x._stores.entries()).map(
|
|
4324
4339
|
([u, d]) => ({
|
|
4325
4340
|
semanticKey: u,
|
|
4326
4341
|
modelName: d?.modelClass?.modelName,
|
|
@@ -4336,7 +4351,7 @@ const _r = (n, e) => {
|
|
|
4336
4351
|
const u = /* @__PURE__ */ new Map();
|
|
4337
4352
|
return v.value.forEach((d) => {
|
|
4338
4353
|
u.set(d.semanticKey, d);
|
|
4339
|
-
}),
|
|
4354
|
+
}), $.value.forEach((d) => {
|
|
4340
4355
|
u.has(d.semanticKey) || u.set(d.semanticKey, d);
|
|
4341
4356
|
}), Array.from(u.values());
|
|
4342
4357
|
}), E = I(() => w.value?.semanticKey ? w.value.semanticKey : r.value ? r.value : ""), Q = I(() => w.value ? w.value : r.value && T.value.get(r.value) || null), N = I(() => {
|
|
@@ -4347,7 +4362,7 @@ const _r = (n, e) => {
|
|
|
4347
4362
|
return null;
|
|
4348
4363
|
}
|
|
4349
4364
|
return E.value && x._stores.get(E.value) || null;
|
|
4350
|
-
}),
|
|
4365
|
+
}), P = I(() => {
|
|
4351
4366
|
a.value;
|
|
4352
4367
|
const u = N.value, d = Q.value, g = u?.modelClass?.modelName || d?.ModelClass?.modelName, R = u?.modelClass?.configKey || d?.ModelClass?.configKey, H = u?.groundTruthPks?.length ?? 0, oe = u?.operationsMap?.size ?? 0, le = u?.getInflightOperations?.() || [], ke = u?.isSyncing ?? !1, je = u?.lastSync ? new Date(u.lastSync).toLocaleString() : "—", nt = u && Array.isArray(u._lastRenderedPks) ? u._lastRenderedPks.length : null, cs = u?.groundTruthPks?.length ?? 0, ds = u ? u.lastSync === null ? "model store" : "ground truth" : "—", us = ke ? "Sync in progress — results may change." : oe > 0 ? "Optimistic operations are applied to results." : u?.lastSync === null ? "No ground truth yet — rendering from model store." : "Using ground truth + local filters.";
|
|
4353
4368
|
return {
|
|
@@ -4622,11 +4637,11 @@ const _r = (n, e) => {
|
|
|
4622
4637
|
f("div", vr, [
|
|
4623
4638
|
f("div", kr, [
|
|
4624
4639
|
d[9] || (d[9] = f("div", { class: "szd-header__title" }, "StateZero", -1)),
|
|
4625
|
-
E.value ? (A(), M("span", br, S(
|
|
4640
|
+
E.value ? (A(), M("span", br, S(P.value.modelName || "?"), 1)) : (A(), M("span", Er, "No queryset"))
|
|
4626
4641
|
]),
|
|
4627
4642
|
f("div", Sr, [
|
|
4628
|
-
|
|
4629
|
-
|
|
4643
|
+
P.value.isSyncing ? (A(), M("span", Tr, "Syncing")) : L("", !0),
|
|
4644
|
+
P.value.opsCount > 0 ? (A(), M("span", Mr, S(P.value.opsCount) + " ops", 1)) : L("", !0),
|
|
4630
4645
|
f("span", Ar, S(Ie.value) + " events", 1),
|
|
4631
4646
|
f("button", {
|
|
4632
4647
|
class: "szd-btn szd-btn--icon",
|
|
@@ -4659,8 +4674,8 @@ const _r = (n, e) => {
|
|
|
4659
4674
|
}, S(g.label), 11, $r)), 64))
|
|
4660
4675
|
])
|
|
4661
4676
|
]),
|
|
4662
|
-
f("main",
|
|
4663
|
-
t.value === "overview" ? (A(), M("div",
|
|
4677
|
+
f("main", Pr, [
|
|
4678
|
+
t.value === "overview" ? (A(), M("div", Fr, [
|
|
4664
4679
|
f("div", Dr, [
|
|
4665
4680
|
d[15] || (d[15] = f("h3", { class: "szd-panel__heading" }, "Why This View?", -1)),
|
|
4666
4681
|
f("div", zr, [
|
|
@@ -4678,7 +4693,7 @@ const _r = (n, e) => {
|
|
|
4678
4693
|
]),
|
|
4679
4694
|
f("div", Ur, [
|
|
4680
4695
|
d[14] || (d[14] = f("span", { class: "szd-kv__key" }, "Reason:", -1)),
|
|
4681
|
-
f("span", Qr, S(
|
|
4696
|
+
f("span", Qr, S(P.value.reason), 1)
|
|
4682
4697
|
])
|
|
4683
4698
|
])
|
|
4684
4699
|
]),
|
|
@@ -4686,26 +4701,26 @@ const _r = (n, e) => {
|
|
|
4686
4701
|
d[21] || (d[21] = f("h3", { class: "szd-panel__heading" }, "Current State", -1)),
|
|
4687
4702
|
f("div", Vr, [
|
|
4688
4703
|
f("div", Br, [
|
|
4689
|
-
f("div", Gr, S(
|
|
4704
|
+
f("div", Gr, S(P.value.optimisticCount ?? "—"), 1),
|
|
4690
4705
|
d[16] || (d[16] = f("div", { class: "szd-stat__label" }, "Optimistic", -1))
|
|
4691
4706
|
]),
|
|
4692
4707
|
f("div", Hr, [
|
|
4693
|
-
f("div", qr, S(
|
|
4708
|
+
f("div", qr, S(P.value.confirmedCount), 1),
|
|
4694
4709
|
d[17] || (d[17] = f("div", { class: "szd-stat__label" }, "Confirmed", -1))
|
|
4695
4710
|
]),
|
|
4696
4711
|
f("div", Jr, [
|
|
4697
|
-
f("div", Wr, S(
|
|
4712
|
+
f("div", Wr, S(P.value.groundTruthCount), 1),
|
|
4698
4713
|
d[18] || (d[18] = f("div", { class: "szd-stat__label" }, "Ground Truth", -1))
|
|
4699
4714
|
]),
|
|
4700
4715
|
f("div", Zr, [
|
|
4701
|
-
f("div", Yr, S(
|
|
4716
|
+
f("div", Yr, S(P.value.inFlightCount), 1),
|
|
4702
4717
|
d[19] || (d[19] = f("div", { class: "szd-stat__label" }, "In-Flight", -1))
|
|
4703
4718
|
])
|
|
4704
4719
|
]),
|
|
4705
4720
|
f("div", Xr, [
|
|
4706
4721
|
f("div", en, [
|
|
4707
4722
|
d[20] || (d[20] = f("span", { class: "szd-kv__key" }, "Last Sync:", -1)),
|
|
4708
|
-
f("span", tn, S(
|
|
4723
|
+
f("span", tn, S(P.value.lastSync), 1)
|
|
4709
4724
|
])
|
|
4710
4725
|
])
|
|
4711
4726
|
]),
|
|
@@ -4814,9 +4829,9 @@ const _r = (n, e) => {
|
|
|
4814
4829
|
t.value === "ast" ? (A(), M("div", On, [
|
|
4815
4830
|
d[27] || (d[27] = f("h3", { class: "szd-panel__heading" }, "Query AST", -1)),
|
|
4816
4831
|
f("div", $n, [
|
|
4817
|
-
f("div",
|
|
4832
|
+
f("div", Pn, [
|
|
4818
4833
|
d[26] || (d[26] = f("span", { class: "szd-kv__key" }, "Semantic Key:", -1)),
|
|
4819
|
-
f("code",
|
|
4834
|
+
f("code", Fn, S(E.value || "—"), 1)
|
|
4820
4835
|
])
|
|
4821
4836
|
]),
|
|
4822
4837
|
f("pre", Dn, S(re.value ? JSON.stringify(re.value, null, 2) : "Select a queryset to view AST"), 1)
|
|
@@ -4894,23 +4909,23 @@ const _r = (n, e) => {
|
|
|
4894
4909
|
f("div", Jn, [
|
|
4895
4910
|
f("div", Wn, [
|
|
4896
4911
|
d[35] || (d[35] = f("span", { class: "szd-kv__key" }, "Model:", -1)),
|
|
4897
|
-
f("span", Zn, S(
|
|
4912
|
+
f("span", Zn, S(P.value.modelName || "—"), 1)
|
|
4898
4913
|
]),
|
|
4899
4914
|
f("div", Yn, [
|
|
4900
4915
|
d[36] || (d[36] = f("span", { class: "szd-kv__key" }, "Source:", -1)),
|
|
4901
|
-
f("span", Xn, S(
|
|
4916
|
+
f("span", Xn, S(P.value.source), 1)
|
|
4902
4917
|
]),
|
|
4903
4918
|
f("div", eo, [
|
|
4904
4919
|
d[37] || (d[37] = f("span", { class: "szd-kv__key" }, "Syncing:", -1)),
|
|
4905
|
-
f("span", to, S(
|
|
4920
|
+
f("span", to, S(P.value.isSyncing ? "Yes" : "No"), 1)
|
|
4906
4921
|
]),
|
|
4907
4922
|
f("div", so, [
|
|
4908
4923
|
d[38] || (d[38] = f("span", { class: "szd-kv__key" }, "Operations:", -1)),
|
|
4909
|
-
f("span", ro, S(
|
|
4924
|
+
f("span", ro, S(P.value.opsCount), 1)
|
|
4910
4925
|
]),
|
|
4911
4926
|
f("div", no, [
|
|
4912
4927
|
d[39] || (d[39] = f("span", { class: "szd-kv__key" }, "Last Sync:", -1)),
|
|
4913
|
-
f("span", oo, S(
|
|
4928
|
+
f("span", oo, S(P.value.lastSync), 1)
|
|
4914
4929
|
])
|
|
4915
4930
|
])
|
|
4916
4931
|
])) : L("", !0)
|
|
@@ -248,7 +248,7 @@ const TS_DECLARATION_TEMPLATE = `/**
|
|
|
248
248
|
|
|
249
249
|
import { Model, Manager } from '{{modulePath}}';
|
|
250
250
|
import { StringOperators, NumberOperators, BooleanOperators, DateOperators } from '{{modulePath}}';
|
|
251
|
-
import { QuerySet, LiveQuerySet, LiveQuerySetOptions, MetricResult, ResultTuple, SerializerOptions, NestedPaths } from '{{modulePath}}';
|
|
251
|
+
import { QuerySet, LiveQuerySet, LiveQuerySetOptions, MetricResult, ResultTuple, SerializerOptions, NestedPaths, CompiledAST } from '{{modulePath}}';
|
|
252
252
|
|
|
253
253
|
// Re-export the real Manager for runtime use
|
|
254
254
|
import { Manager as RuntimeManager } from '{{modulePath}}';
|
|
@@ -387,6 +387,26 @@ export declare class {{className}}QuerySet extends QuerySet<any> {
|
|
|
387
387
|
delete(): Promise<[number, Record<string, number>]>;
|
|
388
388
|
exists(): Promise<boolean>;
|
|
389
389
|
fetch(serializerOptions?: SerializerOptions): Promise<{{className}}[]>;
|
|
390
|
+
|
|
391
|
+
// Compile
|
|
392
|
+
get compile(): {
|
|
393
|
+
fetch(args?: Record<string, any>): CompiledAST;
|
|
394
|
+
get(args?: Record<string, any>): CompiledAST;
|
|
395
|
+
first(args?: Record<string, any>): CompiledAST;
|
|
396
|
+
last(args?: Record<string, any>): CompiledAST;
|
|
397
|
+
count(args?: Record<string, any>): CompiledAST;
|
|
398
|
+
sum(args?: Record<string, any>): CompiledAST;
|
|
399
|
+
avg(args?: Record<string, any>): CompiledAST;
|
|
400
|
+
min(args?: Record<string, any>): CompiledAST;
|
|
401
|
+
max(args?: Record<string, any>): CompiledAST;
|
|
402
|
+
exists(args?: Record<string, any>): CompiledAST;
|
|
403
|
+
create(args?: Record<string, any>): CompiledAST;
|
|
404
|
+
bulkCreate(args?: Record<string, any>): CompiledAST;
|
|
405
|
+
update(args?: Record<string, any>): CompiledAST;
|
|
406
|
+
delete(args?: Record<string, any>): CompiledAST;
|
|
407
|
+
getOrCreate(args?: Record<string, any>): CompiledAST;
|
|
408
|
+
updateOrCreate(args?: Record<string, any>): CompiledAST;
|
|
409
|
+
};
|
|
390
410
|
}
|
|
391
411
|
|
|
392
412
|
/**
|
|
@@ -400,6 +420,7 @@ export declare class {{className}}Manager extends Manager {
|
|
|
400
420
|
get(filters?: {{className}}FilterData, serializerOptions?: SerializerOptions): Promise<{{className}}>;
|
|
401
421
|
create(data: {{className}}CreateData): Promise<{{className}}>;
|
|
402
422
|
delete(): Promise<[number, Record<string, number>]>;
|
|
423
|
+
execute(ast: CompiledAST): Promise<any>;
|
|
403
424
|
}
|
|
404
425
|
|
|
405
426
|
/**
|
|
@@ -471,6 +492,7 @@ export declare class {{className}} extends Model implements {{interfaceName}} {
|
|
|
471
492
|
|
|
472
493
|
constructor(data: Partial<{{interfaceName}}>);
|
|
473
494
|
serialize(): Partial<{{interfaceName}}>;
|
|
495
|
+
static execute(ast: CompiledAST): Promise<any>;
|
|
474
496
|
}
|
|
475
497
|
|
|
476
498
|
/**
|
package/dist/config.js
CHANGED
|
@@ -9,13 +9,17 @@ export let liveConfig = {
|
|
|
9
9
|
const pusherSchema = z.object({
|
|
10
10
|
clientOptions: z.object({
|
|
11
11
|
appKey: z.string({ required_error: 'Pusher appKey is required' }),
|
|
12
|
-
cluster: z.string(
|
|
12
|
+
cluster: z.string().optional(),
|
|
13
|
+
wsHost: z.string().optional(),
|
|
14
|
+
wsPort: z.number().optional(),
|
|
15
|
+
wssPort: z.number().optional(),
|
|
16
|
+
enabledTransports: z.array(z.string()).optional(),
|
|
13
17
|
forceTLS: z.boolean().optional(),
|
|
14
18
|
authEndpoint: z.string()
|
|
15
19
|
.url('Pusher authentication endpoint URL is required'),
|
|
16
20
|
getAuthHeaders: z.function().optional()
|
|
17
21
|
.refine((fn) => fn === undefined || typeof fn === 'function', 'getAuthHeaders must be a function if provided')
|
|
18
|
-
})
|
|
22
|
+
}).refine((opts) => opts.cluster || opts.wsHost, 'Either cluster or wsHost must be provided')
|
|
19
23
|
});
|
|
20
24
|
const eventConfigSchema = z.object({
|
|
21
25
|
type: z.enum(['websocket', 'pusher', 'none']),
|
|
@@ -48,7 +48,11 @@ export namespace EventType {
|
|
|
48
48
|
* Options for instantiating a Pusher client.
|
|
49
49
|
* @typedef {Object} PusherClientOptions
|
|
50
50
|
* @property {string} appKey
|
|
51
|
-
* @property {string} cluster
|
|
51
|
+
* @property {string} [cluster] - Pusher cluster (use this OR wsHost)
|
|
52
|
+
* @property {string} [wsHost] - Custom WebSocket host (e.g. for Soketi)
|
|
53
|
+
* @property {number} [wsPort] - Custom WebSocket port (default 443)
|
|
54
|
+
* @property {number} [wssPort] - Custom secure WebSocket port (default 443)
|
|
55
|
+
* @property {string[]} [enabledTransports] - Transports to use (default ['ws', 'wss'])
|
|
52
56
|
* @property {boolean} [forceTLS]
|
|
53
57
|
* @property {string} authEndpoint
|
|
54
58
|
* @property {function(): Object<string, string>} [getAuthHeaders]
|
|
@@ -162,7 +166,26 @@ export type NamespaceResolver = (modelName: string) => string;
|
|
|
162
166
|
*/
|
|
163
167
|
export type PusherClientOptions = {
|
|
164
168
|
appKey: string;
|
|
165
|
-
|
|
169
|
+
/**
|
|
170
|
+
* - Pusher cluster (use this OR wsHost)
|
|
171
|
+
*/
|
|
172
|
+
cluster?: string | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* - Custom WebSocket host (e.g. for Soketi)
|
|
175
|
+
*/
|
|
176
|
+
wsHost?: string | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* - Custom WebSocket port (default 443)
|
|
179
|
+
*/
|
|
180
|
+
wsPort?: number | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* - Custom secure WebSocket port (default 443)
|
|
183
|
+
*/
|
|
184
|
+
wssPort?: number | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* - Transports to use (default ['ws', 'wss'])
|
|
187
|
+
*/
|
|
188
|
+
enabledTransports?: string[] | undefined;
|
|
166
189
|
forceTLS?: boolean | undefined;
|
|
167
190
|
authEndpoint: string;
|
|
168
191
|
getAuthHeaders?: (() => {
|
|
@@ -41,7 +41,11 @@ export const EventType = {
|
|
|
41
41
|
* Options for instantiating a Pusher client.
|
|
42
42
|
* @typedef {Object} PusherClientOptions
|
|
43
43
|
* @property {string} appKey
|
|
44
|
-
* @property {string} cluster
|
|
44
|
+
* @property {string} [cluster] - Pusher cluster (use this OR wsHost)
|
|
45
|
+
* @property {string} [wsHost] - Custom WebSocket host (e.g. for Soketi)
|
|
46
|
+
* @property {number} [wsPort] - Custom WebSocket port (default 443)
|
|
47
|
+
* @property {number} [wssPort] - Custom secure WebSocket port (default 443)
|
|
48
|
+
* @property {string[]} [enabledTransports] - Transports to use (default ['ws', 'wss'])
|
|
45
49
|
* @property {boolean} [forceTLS]
|
|
46
50
|
* @property {string} authEndpoint
|
|
47
51
|
* @property {function(): Object<string, string>} [getAuthHeaders]
|
|
@@ -71,12 +75,21 @@ export class PusherEventReceiver {
|
|
|
71
75
|
clientOptions.appKey.length < 15) {
|
|
72
76
|
console.warn(`%c[Pusher Warning] The provided appKey ("${clientOptions.appKey}") looks like a numeric app_id. Pusher requires the alphanumeric key, not the ID. Please verify your configuration for backend: "${this.configKey}".`, "color: orange; font-weight: bold; font-size: 14px;");
|
|
73
77
|
}
|
|
74
|
-
|
|
75
|
-
cluster: clientOptions.cluster,
|
|
78
|
+
const pusherOpts = {
|
|
76
79
|
forceTLS: clientOptions.forceTLS ?? true,
|
|
77
80
|
authEndpoint: clientOptions.authEndpoint,
|
|
78
81
|
auth: { headers: clientOptions.getAuthHeaders?.() || {} },
|
|
79
|
-
}
|
|
82
|
+
};
|
|
83
|
+
if (clientOptions.wsHost) {
|
|
84
|
+
pusherOpts.wsHost = clientOptions.wsHost;
|
|
85
|
+
pusherOpts.wsPort = clientOptions.wsPort ?? 443;
|
|
86
|
+
pusherOpts.wssPort = clientOptions.wssPort ?? 443;
|
|
87
|
+
pusherOpts.enabledTransports = clientOptions.enabledTransports ?? ['ws', 'wss'];
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
pusherOpts.cluster = clientOptions.cluster;
|
|
91
|
+
}
|
|
92
|
+
this.pusherClient = new Pusher(clientOptions.appKey, pusherOpts);
|
|
80
93
|
this.pusherClient.connection.bind("connected", () => {
|
|
81
94
|
console.log(`Pusher client connected successfully for backend: ${this.configKey}.`);
|
|
82
95
|
if (this.connectionTimeoutId) {
|
|
@@ -28,11 +28,13 @@ export class StateZeroError extends Error {
|
|
|
28
28
|
* @param {string} code - The error code.
|
|
29
29
|
* @param {IErrorDetail|Object|string} detail - The error details.
|
|
30
30
|
* @param {number} status - The HTTP status code.
|
|
31
|
+
* @param {Object} [data={}] - Additional structured data from the server.
|
|
31
32
|
*/
|
|
32
|
-
constructor(message: string, code: string, detail: IErrorDetail | Object | string, status: number);
|
|
33
|
+
constructor(message: string, code: string, detail: IErrorDetail | Object | string, status: number, data?: Object);
|
|
33
34
|
code: string;
|
|
34
35
|
detail: string | Object | IErrorDetail;
|
|
35
36
|
status: number;
|
|
37
|
+
data: Object;
|
|
36
38
|
/**
|
|
37
39
|
* Returns a full error message including the detail.
|
|
38
40
|
*
|
|
@@ -21,13 +21,15 @@ export class StateZeroError extends Error {
|
|
|
21
21
|
* @param {string} code - The error code.
|
|
22
22
|
* @param {IErrorDetail|Object|string} detail - The error details.
|
|
23
23
|
* @param {number} status - The HTTP status code.
|
|
24
|
+
* @param {Object} [data={}] - Additional structured data from the server.
|
|
24
25
|
*/
|
|
25
|
-
constructor(message, code, detail, status) {
|
|
26
|
+
constructor(message, code, detail, status, data = {}) {
|
|
26
27
|
super(message);
|
|
27
28
|
this.name = "StateZeroError";
|
|
28
29
|
this.code = code;
|
|
29
30
|
this.detail = detail;
|
|
30
31
|
this.status = status;
|
|
32
|
+
this.data = data;
|
|
31
33
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
32
34
|
emitError(this);
|
|
33
35
|
}
|
|
@@ -169,7 +171,7 @@ export class ConfigError extends StateZeroError {
|
|
|
169
171
|
* @returns {StateZeroError} An instance of a StateZeroError subclass.
|
|
170
172
|
*/
|
|
171
173
|
export function parseStateZeroError(errorResponse) {
|
|
172
|
-
const { status, type, detail } = errorResponse;
|
|
174
|
+
const { status, type, detail, data } = errorResponse;
|
|
173
175
|
// Handle undefined type/status case (like in permission denied)
|
|
174
176
|
if (type === undefined && detail === 'Invalid token.') {
|
|
175
177
|
return new PermissionDenied(detail, 403);
|
|
@@ -209,6 +211,6 @@ export function parseStateZeroError(errorResponse) {
|
|
|
209
211
|
else if (status === 409) {
|
|
210
212
|
return new ConflictError(detail, status);
|
|
211
213
|
}
|
|
212
|
-
return new StateZeroError("Unknown error", "unknown", detail, status);
|
|
214
|
+
return new StateZeroError(detail || "Unknown error", type || "unknown", detail, status, data || {});
|
|
213
215
|
}
|
|
214
216
|
}
|
|
@@ -157,6 +157,13 @@ export class Manager {
|
|
|
157
157
|
* and a boolean indicating whether it was created.
|
|
158
158
|
*/
|
|
159
159
|
updateOrCreate(lookupFields: any, defaults?: Object): Promise<ResultTuple>;
|
|
160
|
+
/**
|
|
161
|
+
* Executes a pre-compiled AST through the standard QueryExecutor path.
|
|
162
|
+
*
|
|
163
|
+
* @param {import('./querySet.js').CompiledAST} ast - A compiled AST from QuerySet.compile()
|
|
164
|
+
* @returns {Promise<any>} The query result.
|
|
165
|
+
*/
|
|
166
|
+
execute(ast: import("./querySet.js").CompiledAST): Promise<any>;
|
|
160
167
|
/**
|
|
161
168
|
* Applies a search to the QuerySet using the specified search query and fields.
|
|
162
169
|
*
|
|
@@ -200,6 +200,18 @@ export class Manager {
|
|
|
200
200
|
async updateOrCreate(lookupFields, defaults = {}) {
|
|
201
201
|
return this.newQuerySet().updateOrCreate(lookupFields, defaults);
|
|
202
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Executes a pre-compiled AST through the standard QueryExecutor path.
|
|
205
|
+
*
|
|
206
|
+
* @param {import('./querySet.js').CompiledAST} ast - A compiled AST from QuerySet.compile()
|
|
207
|
+
* @returns {Promise<any>} The query result.
|
|
208
|
+
*/
|
|
209
|
+
execute(ast) {
|
|
210
|
+
const { op, args, ...buildOutput } = ast;
|
|
211
|
+
const qs = new this.QuerySetClass(this.ModelClass, { serializerOptions: buildOutput.serializerOptions || {} });
|
|
212
|
+
qs._prebuiltAST = { ...buildOutput, serializerOptions: buildOutput.serializerOptions || {} };
|
|
213
|
+
return QueryExecutor.execute(qs, op, args || {});
|
|
214
|
+
}
|
|
203
215
|
/**
|
|
204
216
|
* Applies a search to the QuerySet using the specified search query and fields.
|
|
205
217
|
*
|
|
@@ -47,6 +47,13 @@ export class Model {
|
|
|
47
47
|
* @returns {Promise<boolean>} Promise that resolves to true if valid, throws error if invalid
|
|
48
48
|
*/
|
|
49
49
|
static validate(data: Object, validateType?: string, partial?: boolean): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Executes a pre-compiled AST through the standard QueryExecutor path.
|
|
52
|
+
*
|
|
53
|
+
* @param {import('./querySet.js').CompiledAST} ast - A compiled AST from QuerySet.compile()
|
|
54
|
+
* @returns {Promise<any>} The query result.
|
|
55
|
+
*/
|
|
56
|
+
static execute(ast: import("./querySet.js").CompiledAST): Promise<any>;
|
|
50
57
|
/**
|
|
51
58
|
* Get field permissions for the current user (cached on the class)
|
|
52
59
|
* @param {boolean} refresh - Force refresh the cached permissions
|
|
@@ -313,6 +313,15 @@ export class Model {
|
|
|
313
313
|
throw new Error(`Validation failed: ${error.message}`);
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Executes a pre-compiled AST through the standard QueryExecutor path.
|
|
318
|
+
*
|
|
319
|
+
* @param {import('./querySet.js').CompiledAST} ast - A compiled AST from QuerySet.compile()
|
|
320
|
+
* @returns {Promise<any>} The query result.
|
|
321
|
+
*/
|
|
322
|
+
static execute(ast) {
|
|
323
|
+
return this.objects.execute(ast);
|
|
324
|
+
}
|
|
316
325
|
/**
|
|
317
326
|
* Get field permissions for the current user (cached on the class)
|
|
318
327
|
* @param {boolean} refresh - Force refresh the cached permissions
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compiled AST that can be serialized and later executed via Model.execute().
|
|
3
|
+
*
|
|
4
|
+
* @typedef {Object} CompiledAST
|
|
5
|
+
* @property {string} op - The operation type (e.g. 'list', 'get', 'create').
|
|
6
|
+
* @property {Object} args - Operation-specific arguments.
|
|
7
|
+
* @property {Object|null} filter - The filter AST node.
|
|
8
|
+
* @property {Object|null} search - The search configuration.
|
|
9
|
+
* @property {Array} aggregations - Aggregation operations.
|
|
10
|
+
* @property {Array<string>} [orderBy] - Ordering fields.
|
|
11
|
+
* @property {Object} serializerOptions - Serializer options.
|
|
12
|
+
*/
|
|
1
13
|
/**
|
|
2
14
|
* A QuerySet provides a fluent API for constructing and executing queries.
|
|
3
15
|
*
|
|
@@ -273,9 +285,30 @@ export class QuerySet<T> {
|
|
|
273
285
|
/**
|
|
274
286
|
* Builds the final query object to be sent to the backend (simple jsonable object format).
|
|
275
287
|
*
|
|
276
|
-
* @
|
|
277
|
-
|
|
278
|
-
|
|
288
|
+
* @param {string} op - The operation type.
|
|
289
|
+
* @param {Object} [args={}] - Operation-specific arguments.
|
|
290
|
+
* @returns {CompiledAST} The compiled AST.
|
|
291
|
+
*/
|
|
292
|
+
_compile(op: string, args?: Object): CompiledAST;
|
|
293
|
+
get compile(): {
|
|
294
|
+
fetch: (args: any) => CompiledAST;
|
|
295
|
+
get: (args: any) => CompiledAST;
|
|
296
|
+
first: (args: any) => CompiledAST;
|
|
297
|
+
last: (args: any) => CompiledAST;
|
|
298
|
+
count: (args: any) => CompiledAST;
|
|
299
|
+
sum: (args: any) => CompiledAST;
|
|
300
|
+
avg: (args: any) => CompiledAST;
|
|
301
|
+
min: (args: any) => CompiledAST;
|
|
302
|
+
max: (args: any) => CompiledAST;
|
|
303
|
+
exists: (args: any) => CompiledAST;
|
|
304
|
+
create: (args: any) => CompiledAST;
|
|
305
|
+
bulkCreate: (args: any) => CompiledAST;
|
|
306
|
+
update: (args: any) => CompiledAST;
|
|
307
|
+
delete: (args: any) => CompiledAST;
|
|
308
|
+
getOrCreate: (args: any) => CompiledAST;
|
|
309
|
+
updateOrCreate: (args: any) => CompiledAST;
|
|
310
|
+
};
|
|
311
|
+
build(): any;
|
|
279
312
|
/**
|
|
280
313
|
* Returns the current configuration of the QuerySet.
|
|
281
314
|
*
|
|
@@ -297,5 +330,38 @@ export class QuerySet<T> {
|
|
|
297
330
|
*/
|
|
298
331
|
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
299
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* A compiled AST that can be serialized and later executed via Model.execute().
|
|
335
|
+
*/
|
|
336
|
+
export type CompiledAST = {
|
|
337
|
+
/**
|
|
338
|
+
* - The operation type (e.g. 'list', 'get', 'create').
|
|
339
|
+
*/
|
|
340
|
+
op: string;
|
|
341
|
+
/**
|
|
342
|
+
* - Operation-specific arguments.
|
|
343
|
+
*/
|
|
344
|
+
args: Object;
|
|
345
|
+
/**
|
|
346
|
+
* - The filter AST node.
|
|
347
|
+
*/
|
|
348
|
+
filter: Object | null;
|
|
349
|
+
/**
|
|
350
|
+
* - The search configuration.
|
|
351
|
+
*/
|
|
352
|
+
search: Object | null;
|
|
353
|
+
/**
|
|
354
|
+
* - Aggregation operations.
|
|
355
|
+
*/
|
|
356
|
+
aggregations: any[];
|
|
357
|
+
/**
|
|
358
|
+
* - Ordering fields.
|
|
359
|
+
*/
|
|
360
|
+
orderBy?: string[] | undefined;
|
|
361
|
+
/**
|
|
362
|
+
* - Serializer options.
|
|
363
|
+
*/
|
|
364
|
+
serializerOptions: Object;
|
|
365
|
+
};
|
|
300
366
|
import { ModelSerializer } from "./serializers.js";
|
|
301
367
|
import { Model } from "./model.js";
|
|
@@ -7,6 +7,18 @@ import { v7 } from "uuid";
|
|
|
7
7
|
import hash from "object-hash";
|
|
8
8
|
import rfdc from "rfdc";
|
|
9
9
|
const clone = rfdc();
|
|
10
|
+
/**
|
|
11
|
+
* A compiled AST that can be serialized and later executed via Model.execute().
|
|
12
|
+
*
|
|
13
|
+
* @typedef {Object} CompiledAST
|
|
14
|
+
* @property {string} op - The operation type (e.g. 'list', 'get', 'create').
|
|
15
|
+
* @property {Object} args - Operation-specific arguments.
|
|
16
|
+
* @property {Object|null} filter - The filter AST node.
|
|
17
|
+
* @property {Object|null} search - The search configuration.
|
|
18
|
+
* @property {Array} aggregations - Aggregation operations.
|
|
19
|
+
* @property {Array<string>} [orderBy] - Ordering fields.
|
|
20
|
+
* @property {Object} serializerOptions - Serializer options.
|
|
21
|
+
*/
|
|
10
22
|
/**
|
|
11
23
|
* A QuerySet provides a fluent API for constructing and executing queries.
|
|
12
24
|
*
|
|
@@ -649,9 +661,36 @@ export class QuerySet {
|
|
|
649
661
|
/**
|
|
650
662
|
* Builds the final query object to be sent to the backend (simple jsonable object format).
|
|
651
663
|
*
|
|
652
|
-
* @
|
|
664
|
+
* @param {string} op - The operation type.
|
|
665
|
+
* @param {Object} [args={}] - Operation-specific arguments.
|
|
666
|
+
* @returns {CompiledAST} The compiled AST.
|
|
653
667
|
*/
|
|
668
|
+
_compile(op, args = {}) {
|
|
669
|
+
return { op, args, ...this.build() };
|
|
670
|
+
}
|
|
671
|
+
get compile() {
|
|
672
|
+
return {
|
|
673
|
+
fetch: (args) => this._compile('list', args),
|
|
674
|
+
get: (args) => this._compile('get', args),
|
|
675
|
+
first: (args) => this._compile('first', args),
|
|
676
|
+
last: (args) => this._compile('last', args),
|
|
677
|
+
count: (args) => this._compile('count', args),
|
|
678
|
+
sum: (args) => this._compile('sum', args),
|
|
679
|
+
avg: (args) => this._compile('avg', args),
|
|
680
|
+
min: (args) => this._compile('min', args),
|
|
681
|
+
max: (args) => this._compile('max', args),
|
|
682
|
+
exists: (args) => this._compile('exists', args),
|
|
683
|
+
create: (args) => this._compile('create', args),
|
|
684
|
+
bulkCreate: (args) => this._compile('bulk_create', args),
|
|
685
|
+
update: (args) => this._compile('update', args),
|
|
686
|
+
delete: (args) => this._compile('delete', args),
|
|
687
|
+
getOrCreate: (args) => this._compile('get_or_create', args),
|
|
688
|
+
updateOrCreate: (args) => this._compile('update_or_create', args),
|
|
689
|
+
};
|
|
690
|
+
}
|
|
654
691
|
build() {
|
|
692
|
+
if (this._prebuiltAST)
|
|
693
|
+
return clone(this._prebuiltAST);
|
|
655
694
|
let searchData = null;
|
|
656
695
|
const nonSearchNodes = [];
|
|
657
696
|
for (const node of this.nodes) {
|
package/package.json
CHANGED