@objectstack/objectql 2.0.0 → 2.0.1
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +10 -0
- package/dist/index.d.mts +97 -9
- package/dist/index.d.ts +97 -9
- package/dist/index.js +275 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +275 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/engine.ts +16 -4
- package/src/protocol.ts +300 -28
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/objectql@2.0.
|
|
2
|
+
> @objectstack/objectql@2.0.1 build /home/runner/work/spec/spec/packages/objectql
|
|
3
3
|
> tsup --config ../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m53.23 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m109.67 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 79ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m54.65 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m110.38 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 79ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 11177ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m71.29 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m71.29 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @objectstack/objectql
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Patch release for maintenance and stability improvements
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @objectstack/spec@2.0.1
|
|
10
|
+
- @objectstack/core@2.0.1
|
|
11
|
+
- @objectstack/types@2.0.1
|
|
12
|
+
|
|
3
13
|
## 2.0.0
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1203,7 +1203,6 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1203
1203
|
websockets: boolean;
|
|
1204
1204
|
files: boolean;
|
|
1205
1205
|
analytics: boolean;
|
|
1206
|
-
hub: boolean;
|
|
1207
1206
|
ai: boolean;
|
|
1208
1207
|
workflow: boolean;
|
|
1209
1208
|
notifications: boolean;
|
|
@@ -1212,7 +1211,98 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1212
1211
|
endpoints: {
|
|
1213
1212
|
data: string;
|
|
1214
1213
|
metadata: string;
|
|
1215
|
-
|
|
1214
|
+
analytics: string;
|
|
1215
|
+
};
|
|
1216
|
+
services: {
|
|
1217
|
+
metadata: {
|
|
1218
|
+
enabled: boolean;
|
|
1219
|
+
status: "degraded";
|
|
1220
|
+
route: string;
|
|
1221
|
+
provider: string;
|
|
1222
|
+
message: string;
|
|
1223
|
+
};
|
|
1224
|
+
data: {
|
|
1225
|
+
enabled: boolean;
|
|
1226
|
+
status: "available";
|
|
1227
|
+
route: string;
|
|
1228
|
+
provider: string;
|
|
1229
|
+
};
|
|
1230
|
+
analytics: {
|
|
1231
|
+
enabled: boolean;
|
|
1232
|
+
status: "available";
|
|
1233
|
+
route: string;
|
|
1234
|
+
provider: string;
|
|
1235
|
+
};
|
|
1236
|
+
auth: {
|
|
1237
|
+
enabled: boolean;
|
|
1238
|
+
status: "unavailable";
|
|
1239
|
+
message: string;
|
|
1240
|
+
};
|
|
1241
|
+
automation: {
|
|
1242
|
+
enabled: boolean;
|
|
1243
|
+
status: "unavailable";
|
|
1244
|
+
message: string;
|
|
1245
|
+
};
|
|
1246
|
+
cache: {
|
|
1247
|
+
enabled: boolean;
|
|
1248
|
+
status: "unavailable";
|
|
1249
|
+
message: string;
|
|
1250
|
+
};
|
|
1251
|
+
queue: {
|
|
1252
|
+
enabled: boolean;
|
|
1253
|
+
status: "unavailable";
|
|
1254
|
+
message: string;
|
|
1255
|
+
};
|
|
1256
|
+
job: {
|
|
1257
|
+
enabled: boolean;
|
|
1258
|
+
status: "unavailable";
|
|
1259
|
+
message: string;
|
|
1260
|
+
};
|
|
1261
|
+
ui: {
|
|
1262
|
+
enabled: boolean;
|
|
1263
|
+
status: "unavailable";
|
|
1264
|
+
message: string;
|
|
1265
|
+
};
|
|
1266
|
+
workflow: {
|
|
1267
|
+
enabled: boolean;
|
|
1268
|
+
status: "unavailable";
|
|
1269
|
+
message: string;
|
|
1270
|
+
};
|
|
1271
|
+
realtime: {
|
|
1272
|
+
enabled: boolean;
|
|
1273
|
+
status: "unavailable";
|
|
1274
|
+
message: string;
|
|
1275
|
+
};
|
|
1276
|
+
notification: {
|
|
1277
|
+
enabled: boolean;
|
|
1278
|
+
status: "unavailable";
|
|
1279
|
+
message: string;
|
|
1280
|
+
};
|
|
1281
|
+
ai: {
|
|
1282
|
+
enabled: boolean;
|
|
1283
|
+
status: "unavailable";
|
|
1284
|
+
message: string;
|
|
1285
|
+
};
|
|
1286
|
+
i18n: {
|
|
1287
|
+
enabled: boolean;
|
|
1288
|
+
status: "unavailable";
|
|
1289
|
+
message: string;
|
|
1290
|
+
};
|
|
1291
|
+
graphql: {
|
|
1292
|
+
enabled: boolean;
|
|
1293
|
+
status: "unavailable";
|
|
1294
|
+
message: string;
|
|
1295
|
+
};
|
|
1296
|
+
'file-storage': {
|
|
1297
|
+
enabled: boolean;
|
|
1298
|
+
status: "unavailable";
|
|
1299
|
+
message: string;
|
|
1300
|
+
};
|
|
1301
|
+
search: {
|
|
1302
|
+
enabled: boolean;
|
|
1303
|
+
status: "unavailable";
|
|
1304
|
+
message: string;
|
|
1305
|
+
};
|
|
1216
1306
|
};
|
|
1217
1307
|
}>;
|
|
1218
1308
|
getMetaTypes(): Promise<{
|
|
@@ -1319,7 +1409,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1319
1409
|
name: string;
|
|
1320
1410
|
cacheRequest?: MetadataCacheRequest;
|
|
1321
1411
|
}): Promise<MetadataCacheResponse>;
|
|
1322
|
-
batchData(
|
|
1412
|
+
batchData(request: {
|
|
1323
1413
|
object: string;
|
|
1324
1414
|
request: BatchUpdateRequest;
|
|
1325
1415
|
}): Promise<BatchUpdateResponse>;
|
|
@@ -1327,13 +1417,11 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1327
1417
|
object: string;
|
|
1328
1418
|
records: any[];
|
|
1329
1419
|
}): Promise<any>;
|
|
1330
|
-
updateManyData(
|
|
1331
|
-
analyticsQuery(
|
|
1332
|
-
getAnalyticsMeta(
|
|
1420
|
+
updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse>;
|
|
1421
|
+
analyticsQuery(request: any): Promise<any>;
|
|
1422
|
+
getAnalyticsMeta(request: any): Promise<any>;
|
|
1423
|
+
private mapAnalyticsOperator;
|
|
1333
1424
|
triggerAutomation(_request: any): Promise<any>;
|
|
1334
|
-
listSpaces(_request: any): Promise<any>;
|
|
1335
|
-
createSpace(_request: any): Promise<any>;
|
|
1336
|
-
installPlugin(_request: any): Promise<any>;
|
|
1337
1425
|
deleteManyData(request: DeleteManyDataRequest): Promise<any>;
|
|
1338
1426
|
saveMetaItem(request: {
|
|
1339
1427
|
type: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1203,7 +1203,6 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1203
1203
|
websockets: boolean;
|
|
1204
1204
|
files: boolean;
|
|
1205
1205
|
analytics: boolean;
|
|
1206
|
-
hub: boolean;
|
|
1207
1206
|
ai: boolean;
|
|
1208
1207
|
workflow: boolean;
|
|
1209
1208
|
notifications: boolean;
|
|
@@ -1212,7 +1211,98 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1212
1211
|
endpoints: {
|
|
1213
1212
|
data: string;
|
|
1214
1213
|
metadata: string;
|
|
1215
|
-
|
|
1214
|
+
analytics: string;
|
|
1215
|
+
};
|
|
1216
|
+
services: {
|
|
1217
|
+
metadata: {
|
|
1218
|
+
enabled: boolean;
|
|
1219
|
+
status: "degraded";
|
|
1220
|
+
route: string;
|
|
1221
|
+
provider: string;
|
|
1222
|
+
message: string;
|
|
1223
|
+
};
|
|
1224
|
+
data: {
|
|
1225
|
+
enabled: boolean;
|
|
1226
|
+
status: "available";
|
|
1227
|
+
route: string;
|
|
1228
|
+
provider: string;
|
|
1229
|
+
};
|
|
1230
|
+
analytics: {
|
|
1231
|
+
enabled: boolean;
|
|
1232
|
+
status: "available";
|
|
1233
|
+
route: string;
|
|
1234
|
+
provider: string;
|
|
1235
|
+
};
|
|
1236
|
+
auth: {
|
|
1237
|
+
enabled: boolean;
|
|
1238
|
+
status: "unavailable";
|
|
1239
|
+
message: string;
|
|
1240
|
+
};
|
|
1241
|
+
automation: {
|
|
1242
|
+
enabled: boolean;
|
|
1243
|
+
status: "unavailable";
|
|
1244
|
+
message: string;
|
|
1245
|
+
};
|
|
1246
|
+
cache: {
|
|
1247
|
+
enabled: boolean;
|
|
1248
|
+
status: "unavailable";
|
|
1249
|
+
message: string;
|
|
1250
|
+
};
|
|
1251
|
+
queue: {
|
|
1252
|
+
enabled: boolean;
|
|
1253
|
+
status: "unavailable";
|
|
1254
|
+
message: string;
|
|
1255
|
+
};
|
|
1256
|
+
job: {
|
|
1257
|
+
enabled: boolean;
|
|
1258
|
+
status: "unavailable";
|
|
1259
|
+
message: string;
|
|
1260
|
+
};
|
|
1261
|
+
ui: {
|
|
1262
|
+
enabled: boolean;
|
|
1263
|
+
status: "unavailable";
|
|
1264
|
+
message: string;
|
|
1265
|
+
};
|
|
1266
|
+
workflow: {
|
|
1267
|
+
enabled: boolean;
|
|
1268
|
+
status: "unavailable";
|
|
1269
|
+
message: string;
|
|
1270
|
+
};
|
|
1271
|
+
realtime: {
|
|
1272
|
+
enabled: boolean;
|
|
1273
|
+
status: "unavailable";
|
|
1274
|
+
message: string;
|
|
1275
|
+
};
|
|
1276
|
+
notification: {
|
|
1277
|
+
enabled: boolean;
|
|
1278
|
+
status: "unavailable";
|
|
1279
|
+
message: string;
|
|
1280
|
+
};
|
|
1281
|
+
ai: {
|
|
1282
|
+
enabled: boolean;
|
|
1283
|
+
status: "unavailable";
|
|
1284
|
+
message: string;
|
|
1285
|
+
};
|
|
1286
|
+
i18n: {
|
|
1287
|
+
enabled: boolean;
|
|
1288
|
+
status: "unavailable";
|
|
1289
|
+
message: string;
|
|
1290
|
+
};
|
|
1291
|
+
graphql: {
|
|
1292
|
+
enabled: boolean;
|
|
1293
|
+
status: "unavailable";
|
|
1294
|
+
message: string;
|
|
1295
|
+
};
|
|
1296
|
+
'file-storage': {
|
|
1297
|
+
enabled: boolean;
|
|
1298
|
+
status: "unavailable";
|
|
1299
|
+
message: string;
|
|
1300
|
+
};
|
|
1301
|
+
search: {
|
|
1302
|
+
enabled: boolean;
|
|
1303
|
+
status: "unavailable";
|
|
1304
|
+
message: string;
|
|
1305
|
+
};
|
|
1216
1306
|
};
|
|
1217
1307
|
}>;
|
|
1218
1308
|
getMetaTypes(): Promise<{
|
|
@@ -1319,7 +1409,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1319
1409
|
name: string;
|
|
1320
1410
|
cacheRequest?: MetadataCacheRequest;
|
|
1321
1411
|
}): Promise<MetadataCacheResponse>;
|
|
1322
|
-
batchData(
|
|
1412
|
+
batchData(request: {
|
|
1323
1413
|
object: string;
|
|
1324
1414
|
request: BatchUpdateRequest;
|
|
1325
1415
|
}): Promise<BatchUpdateResponse>;
|
|
@@ -1327,13 +1417,11 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
|
|
|
1327
1417
|
object: string;
|
|
1328
1418
|
records: any[];
|
|
1329
1419
|
}): Promise<any>;
|
|
1330
|
-
updateManyData(
|
|
1331
|
-
analyticsQuery(
|
|
1332
|
-
getAnalyticsMeta(
|
|
1420
|
+
updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse>;
|
|
1421
|
+
analyticsQuery(request: any): Promise<any>;
|
|
1422
|
+
getAnalyticsMeta(request: any): Promise<any>;
|
|
1423
|
+
private mapAnalyticsOperator;
|
|
1333
1424
|
triggerAutomation(_request: any): Promise<any>;
|
|
1334
|
-
listSpaces(_request: any): Promise<any>;
|
|
1335
|
-
createSpace(_request: any): Promise<any>;
|
|
1336
|
-
installPlugin(_request: any): Promise<any>;
|
|
1337
1425
|
deleteManyData(request: DeleteManyDataRequest): Promise<any>;
|
|
1338
1426
|
saveMetaItem(request: {
|
|
1339
1427
|
type: string;
|
package/dist/index.js
CHANGED
|
@@ -546,9 +546,8 @@ var ObjectStackProtocolImplementation = class {
|
|
|
546
546
|
graphql: false,
|
|
547
547
|
search: false,
|
|
548
548
|
websockets: false,
|
|
549
|
-
files:
|
|
550
|
-
analytics:
|
|
551
|
-
hub: false,
|
|
549
|
+
files: false,
|
|
550
|
+
analytics: true,
|
|
552
551
|
ai: false,
|
|
553
552
|
workflow: false,
|
|
554
553
|
notifications: false,
|
|
@@ -557,7 +556,30 @@ var ObjectStackProtocolImplementation = class {
|
|
|
557
556
|
endpoints: {
|
|
558
557
|
data: "/api/data",
|
|
559
558
|
metadata: "/api/meta",
|
|
560
|
-
|
|
559
|
+
analytics: "/api/analytics"
|
|
560
|
+
},
|
|
561
|
+
services: {
|
|
562
|
+
// --- Kernel-provided (objectql is an example kernel implementation) ---
|
|
563
|
+
metadata: { enabled: true, status: "degraded", route: "/api/meta", provider: "objectql", message: "In-memory registry only; DB persistence not yet implemented" },
|
|
564
|
+
data: { enabled: true, status: "available", route: "/api/data", provider: "objectql" },
|
|
565
|
+
analytics: { enabled: true, status: "available", route: "/api/analytics", provider: "objectql" },
|
|
566
|
+
// --- Plugin-provided (kernel does NOT handle these) ---
|
|
567
|
+
auth: { enabled: false, status: "unavailable", message: "Install an auth plugin (e.g. plugin-auth) to enable" },
|
|
568
|
+
automation: { enabled: false, status: "unavailable", message: "Install an automation plugin (e.g. plugin-automation) to enable" },
|
|
569
|
+
// --- Core infrastructure (plugin-provided) ---
|
|
570
|
+
cache: { enabled: false, status: "unavailable", message: "Install a cache plugin (e.g. plugin-redis) to enable" },
|
|
571
|
+
queue: { enabled: false, status: "unavailable", message: "Install a queue plugin (e.g. plugin-bullmq) to enable" },
|
|
572
|
+
job: { enabled: false, status: "unavailable", message: "Install a job scheduler plugin to enable" },
|
|
573
|
+
// --- Optional services (all plugin-provided) ---
|
|
574
|
+
ui: { enabled: false, status: "unavailable", message: "Install a UI plugin to enable" },
|
|
575
|
+
workflow: { enabled: false, status: "unavailable", message: "Install a workflow plugin to enable" },
|
|
576
|
+
realtime: { enabled: false, status: "unavailable", message: "Install a realtime plugin to enable" },
|
|
577
|
+
notification: { enabled: false, status: "unavailable", message: "Install a notification plugin to enable" },
|
|
578
|
+
ai: { enabled: false, status: "unavailable", message: "Install an AI plugin to enable" },
|
|
579
|
+
i18n: { enabled: false, status: "unavailable", message: "Install an i18n plugin to enable" },
|
|
580
|
+
graphql: { enabled: false, status: "unavailable", message: "Install a GraphQL plugin to enable" },
|
|
581
|
+
"file-storage": { enabled: false, status: "unavailable", message: "Install a file-storage plugin to enable" },
|
|
582
|
+
search: { enabled: false, status: "unavailable", message: "Install a search plugin to enable" }
|
|
561
583
|
}
|
|
562
584
|
};
|
|
563
585
|
}
|
|
@@ -736,8 +758,80 @@ var ObjectStackProtocolImplementation = class {
|
|
|
736
758
|
// ==========================================
|
|
737
759
|
// Batch Operations
|
|
738
760
|
// ==========================================
|
|
739
|
-
async batchData(
|
|
740
|
-
|
|
761
|
+
async batchData(request) {
|
|
762
|
+
const { object, request: batchReq } = request;
|
|
763
|
+
const { operation, records, options } = batchReq;
|
|
764
|
+
const results = [];
|
|
765
|
+
let succeeded = 0;
|
|
766
|
+
let failed = 0;
|
|
767
|
+
for (const record of records) {
|
|
768
|
+
try {
|
|
769
|
+
switch (operation) {
|
|
770
|
+
case "create": {
|
|
771
|
+
const created = await this.engine.insert(object, record.data || record);
|
|
772
|
+
results.push({ id: created._id || created.id, success: true, record: created });
|
|
773
|
+
succeeded++;
|
|
774
|
+
break;
|
|
775
|
+
}
|
|
776
|
+
case "update": {
|
|
777
|
+
if (!record.id) throw new Error("Record id is required for update");
|
|
778
|
+
const updated = await this.engine.update(object, record.data || {}, { filter: { _id: record.id } });
|
|
779
|
+
results.push({ id: record.id, success: true, record: updated });
|
|
780
|
+
succeeded++;
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
case "upsert": {
|
|
784
|
+
if (record.id) {
|
|
785
|
+
try {
|
|
786
|
+
const existing = await this.engine.findOne(object, { filter: { _id: record.id } });
|
|
787
|
+
if (existing) {
|
|
788
|
+
const updated = await this.engine.update(object, record.data || {}, { filter: { _id: record.id } });
|
|
789
|
+
results.push({ id: record.id, success: true, record: updated });
|
|
790
|
+
} else {
|
|
791
|
+
const created = await this.engine.insert(object, { _id: record.id, ...record.data || {} });
|
|
792
|
+
results.push({ id: created._id || created.id, success: true, record: created });
|
|
793
|
+
}
|
|
794
|
+
} catch {
|
|
795
|
+
const created = await this.engine.insert(object, { _id: record.id, ...record.data || {} });
|
|
796
|
+
results.push({ id: created._id || created.id, success: true, record: created });
|
|
797
|
+
}
|
|
798
|
+
} else {
|
|
799
|
+
const created = await this.engine.insert(object, record.data || record);
|
|
800
|
+
results.push({ id: created._id || created.id, success: true, record: created });
|
|
801
|
+
}
|
|
802
|
+
succeeded++;
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
805
|
+
case "delete": {
|
|
806
|
+
if (!record.id) throw new Error("Record id is required for delete");
|
|
807
|
+
await this.engine.delete(object, { filter: { _id: record.id } });
|
|
808
|
+
results.push({ id: record.id, success: true });
|
|
809
|
+
succeeded++;
|
|
810
|
+
break;
|
|
811
|
+
}
|
|
812
|
+
default:
|
|
813
|
+
results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });
|
|
814
|
+
failed++;
|
|
815
|
+
}
|
|
816
|
+
} catch (err) {
|
|
817
|
+
results.push({ id: record.id, success: false, error: err.message });
|
|
818
|
+
failed++;
|
|
819
|
+
if (options?.atomic) {
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
822
|
+
if (!options?.continueOnError) {
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
success: failed === 0,
|
|
829
|
+
operation,
|
|
830
|
+
total: records.length,
|
|
831
|
+
succeeded,
|
|
832
|
+
failed,
|
|
833
|
+
results: options?.returnRecords !== false ? results : results.map((r) => ({ id: r.id, success: r.success, error: r.error }))
|
|
834
|
+
};
|
|
741
835
|
}
|
|
742
836
|
async createManyData(request) {
|
|
743
837
|
const records = await this.engine.insert(request.object, request.records);
|
|
@@ -747,26 +841,174 @@ var ObjectStackProtocolImplementation = class {
|
|
|
747
841
|
count: records.length
|
|
748
842
|
};
|
|
749
843
|
}
|
|
750
|
-
async updateManyData(
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
844
|
+
async updateManyData(request) {
|
|
845
|
+
const { object, records, options } = request;
|
|
846
|
+
const results = [];
|
|
847
|
+
let succeeded = 0;
|
|
848
|
+
let failed = 0;
|
|
849
|
+
for (const record of records) {
|
|
850
|
+
try {
|
|
851
|
+
const updated = await this.engine.update(object, record.data, { filter: { _id: record.id } });
|
|
852
|
+
results.push({ id: record.id, success: true, record: updated });
|
|
853
|
+
succeeded++;
|
|
854
|
+
} catch (err) {
|
|
855
|
+
results.push({ id: record.id, success: false, error: err.message });
|
|
856
|
+
failed++;
|
|
857
|
+
if (!options?.continueOnError) {
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return {
|
|
863
|
+
success: failed === 0,
|
|
864
|
+
operation: "update",
|
|
865
|
+
total: records.length,
|
|
866
|
+
succeeded,
|
|
867
|
+
failed,
|
|
868
|
+
results
|
|
869
|
+
};
|
|
758
870
|
}
|
|
759
|
-
async
|
|
760
|
-
|
|
871
|
+
async analyticsQuery(request) {
|
|
872
|
+
const { query, cube } = request;
|
|
873
|
+
const object = cube;
|
|
874
|
+
const groupBy = query.dimensions || [];
|
|
875
|
+
const aggregations = [];
|
|
876
|
+
if (query.measures) {
|
|
877
|
+
for (const measure of query.measures) {
|
|
878
|
+
if (measure === "count" || measure === "count_all") {
|
|
879
|
+
aggregations.push({ field: "*", method: "count", alias: "count" });
|
|
880
|
+
} else if (measure.includes(".")) {
|
|
881
|
+
const [field, method] = measure.split(".");
|
|
882
|
+
aggregations.push({ field, method, alias: `${field}_${method}` });
|
|
883
|
+
} else {
|
|
884
|
+
aggregations.push({ field: measure, method: "sum", alias: measure });
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
let filter = void 0;
|
|
889
|
+
if (query.filters && query.filters.length > 0) {
|
|
890
|
+
const conditions = query.filters.map((f) => {
|
|
891
|
+
const op = this.mapAnalyticsOperator(f.operator);
|
|
892
|
+
if (f.values && f.values.length === 1) {
|
|
893
|
+
return { [f.member]: { [op]: f.values[0] } };
|
|
894
|
+
} else if (f.values && f.values.length > 1) {
|
|
895
|
+
return { [f.member]: { $in: f.values } };
|
|
896
|
+
}
|
|
897
|
+
return { [f.member]: { [op]: true } };
|
|
898
|
+
});
|
|
899
|
+
filter = conditions.length === 1 ? conditions[0] : { $and: conditions };
|
|
900
|
+
}
|
|
901
|
+
const rows = await this.engine.aggregate(object, {
|
|
902
|
+
filter,
|
|
903
|
+
groupBy: groupBy.length > 0 ? groupBy : void 0,
|
|
904
|
+
aggregations: aggregations.length > 0 ? aggregations.map((a) => ({ field: a.field, method: a.method, alias: a.alias })) : [{ field: "*", method: "count", alias: "count" }]
|
|
905
|
+
});
|
|
906
|
+
const fields = [
|
|
907
|
+
...groupBy.map((d) => ({ name: d, type: "string" })),
|
|
908
|
+
...aggregations.map((a) => ({ name: a.alias, type: "number" }))
|
|
909
|
+
];
|
|
910
|
+
return {
|
|
911
|
+
success: true,
|
|
912
|
+
data: {
|
|
913
|
+
rows,
|
|
914
|
+
fields
|
|
915
|
+
}
|
|
916
|
+
};
|
|
761
917
|
}
|
|
762
|
-
async
|
|
763
|
-
|
|
918
|
+
async getAnalyticsMeta(request) {
|
|
919
|
+
const objects = SchemaRegistry.listItems("object");
|
|
920
|
+
const cubeFilter = request?.cube;
|
|
921
|
+
const cubes = [];
|
|
922
|
+
for (const obj of objects) {
|
|
923
|
+
const schema = obj;
|
|
924
|
+
if (cubeFilter && schema.name !== cubeFilter) continue;
|
|
925
|
+
const measures = {};
|
|
926
|
+
const dimensions = {};
|
|
927
|
+
const fields = schema.fields || {};
|
|
928
|
+
measures["count"] = {
|
|
929
|
+
name: "count",
|
|
930
|
+
label: "Count",
|
|
931
|
+
type: "count",
|
|
932
|
+
sql: "*"
|
|
933
|
+
};
|
|
934
|
+
for (const [fieldName, fieldDef] of Object.entries(fields)) {
|
|
935
|
+
const fd = fieldDef;
|
|
936
|
+
const fieldType = fd.type || "text";
|
|
937
|
+
if (["number", "currency", "percent"].includes(fieldType)) {
|
|
938
|
+
measures[`${fieldName}_sum`] = {
|
|
939
|
+
name: `${fieldName}_sum`,
|
|
940
|
+
label: `${fd.label || fieldName} (Sum)`,
|
|
941
|
+
type: "sum",
|
|
942
|
+
sql: fieldName
|
|
943
|
+
};
|
|
944
|
+
measures[`${fieldName}_avg`] = {
|
|
945
|
+
name: `${fieldName}_avg`,
|
|
946
|
+
label: `${fd.label || fieldName} (Avg)`,
|
|
947
|
+
type: "avg",
|
|
948
|
+
sql: fieldName
|
|
949
|
+
};
|
|
950
|
+
dimensions[fieldName] = {
|
|
951
|
+
name: fieldName,
|
|
952
|
+
label: fd.label || fieldName,
|
|
953
|
+
type: "number",
|
|
954
|
+
sql: fieldName
|
|
955
|
+
};
|
|
956
|
+
} else if (["date", "datetime"].includes(fieldType)) {
|
|
957
|
+
dimensions[fieldName] = {
|
|
958
|
+
name: fieldName,
|
|
959
|
+
label: fd.label || fieldName,
|
|
960
|
+
type: "time",
|
|
961
|
+
sql: fieldName,
|
|
962
|
+
granularities: ["day", "week", "month", "quarter", "year"]
|
|
963
|
+
};
|
|
964
|
+
} else if (["boolean"].includes(fieldType)) {
|
|
965
|
+
dimensions[fieldName] = {
|
|
966
|
+
name: fieldName,
|
|
967
|
+
label: fd.label || fieldName,
|
|
968
|
+
type: "boolean",
|
|
969
|
+
sql: fieldName
|
|
970
|
+
};
|
|
971
|
+
} else {
|
|
972
|
+
dimensions[fieldName] = {
|
|
973
|
+
name: fieldName,
|
|
974
|
+
label: fd.label || fieldName,
|
|
975
|
+
type: "string",
|
|
976
|
+
sql: fieldName
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
cubes.push({
|
|
981
|
+
name: schema.name,
|
|
982
|
+
title: schema.label || schema.name,
|
|
983
|
+
description: schema.description,
|
|
984
|
+
sql: schema.name,
|
|
985
|
+
measures,
|
|
986
|
+
dimensions,
|
|
987
|
+
public: true
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
return {
|
|
991
|
+
success: true,
|
|
992
|
+
data: { cubes }
|
|
993
|
+
};
|
|
764
994
|
}
|
|
765
|
-
|
|
766
|
-
|
|
995
|
+
mapAnalyticsOperator(op) {
|
|
996
|
+
const map = {
|
|
997
|
+
equals: "$eq",
|
|
998
|
+
notEquals: "$ne",
|
|
999
|
+
contains: "$contains",
|
|
1000
|
+
notContains: "$notContains",
|
|
1001
|
+
gt: "$gt",
|
|
1002
|
+
gte: "$gte",
|
|
1003
|
+
lt: "$lt",
|
|
1004
|
+
lte: "$lte",
|
|
1005
|
+
set: "$ne",
|
|
1006
|
+
notSet: "$eq"
|
|
1007
|
+
};
|
|
1008
|
+
return map[op] || "$eq";
|
|
767
1009
|
}
|
|
768
|
-
async
|
|
769
|
-
throw new Error(
|
|
1010
|
+
async triggerAutomation(_request) {
|
|
1011
|
+
throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the "automation" service.');
|
|
770
1012
|
}
|
|
771
1013
|
async deleteManyData(request) {
|
|
772
1014
|
return this.engine.delete(request.object, {
|
|
@@ -1277,7 +1519,17 @@ var ObjectQL = class {
|
|
|
1277
1519
|
object = this.resolveObjectName(object);
|
|
1278
1520
|
const driver = this.getDriver(object);
|
|
1279
1521
|
this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);
|
|
1280
|
-
|
|
1522
|
+
const ast = {
|
|
1523
|
+
object,
|
|
1524
|
+
where: query.filter,
|
|
1525
|
+
groupBy: query.groupBy,
|
|
1526
|
+
aggregations: query.aggregations?.map((agg) => ({
|
|
1527
|
+
function: agg.method,
|
|
1528
|
+
field: agg.field,
|
|
1529
|
+
alias: agg.alias || `${agg.method}_${agg.field || "all"}`
|
|
1530
|
+
}))
|
|
1531
|
+
};
|
|
1532
|
+
return driver.find(object, ast);
|
|
1281
1533
|
}
|
|
1282
1534
|
async execute(command, options) {
|
|
1283
1535
|
if (options?.object) {
|