@cadenza.io/service 2.3.17 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +512 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +512 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -282,10 +282,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
282
282
|
} = serviceInstance;
|
|
283
283
|
if (uuid4 === this.serviceInstanceId) return;
|
|
284
284
|
if (deleted) {
|
|
285
|
-
this.instances.get(serviceName)?.
|
|
286
|
-
|
|
287
|
-
1
|
|
288
|
-
|
|
285
|
+
const indexToDelete = this.instances.get(serviceName)?.findIndex((i) => i.uuid === uuid4) ?? -1;
|
|
286
|
+
if (indexToDelete >= 0) {
|
|
287
|
+
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
288
|
+
}
|
|
289
289
|
if (this.instances.get(serviceName)?.length === 0) {
|
|
290
290
|
this.instances.delete(serviceName);
|
|
291
291
|
} else if (this.instances.get(serviceName)?.filter((i) => i.address === address && i.port === port).length === 0) {
|
|
@@ -328,7 +328,7 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
328
328
|
communicationTypes
|
|
329
329
|
});
|
|
330
330
|
instances?.filter(
|
|
331
|
-
(i) => i.address === address && i.port === port && i.
|
|
331
|
+
(i) => i.address === address && i.port === port && i.isActive
|
|
332
332
|
).forEach((i) => {
|
|
333
333
|
i.clientCreated = true;
|
|
334
334
|
});
|
|
@@ -432,7 +432,12 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
432
432
|
return true;
|
|
433
433
|
},
|
|
434
434
|
"Handles service not responding"
|
|
435
|
-
).doOn(
|
|
435
|
+
).doOn(
|
|
436
|
+
"meta.fetch.handshake_failed",
|
|
437
|
+
"meta.fetch.handshake_failed.*",
|
|
438
|
+
"meta.socket_client.disconnected",
|
|
439
|
+
"meta.socket_client.disconnected.*"
|
|
440
|
+
).attachSignal("global.meta.service_registry.service_not_responding");
|
|
436
441
|
this.handleServiceHandshakeTask = CadenzaService.createMetaTask(
|
|
437
442
|
"Handle service handshake",
|
|
438
443
|
(ctx, emit) => {
|
|
@@ -459,7 +464,10 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
459
464
|
(i) => i.uuid !== serviceInstanceId && i.address === serviceAddress && i.port === servicePort
|
|
460
465
|
);
|
|
461
466
|
for (const i of instancesToDelete ?? []) {
|
|
462
|
-
this.instances.get(serviceName)?.
|
|
467
|
+
const indexToDelete = this.instances.get(serviceName)?.indexOf(i) ?? -1;
|
|
468
|
+
if (indexToDelete >= 0) {
|
|
469
|
+
this.instances.get(serviceName)?.splice(indexToDelete, 1);
|
|
470
|
+
}
|
|
463
471
|
emit("global.meta.service_registry.deleted", {
|
|
464
472
|
data: {
|
|
465
473
|
isActive: false,
|
|
@@ -619,8 +627,9 @@ var ServiceRegistry = class _ServiceRegistry {
|
|
|
619
627
|
}
|
|
620
628
|
if (__broadcast || instances[0].isFrontend) {
|
|
621
629
|
for (const instance of instances) {
|
|
630
|
+
const socketKey = instance.isFrontend ? instance.address : `${instance.address}_${instance.port}`;
|
|
622
631
|
emit(
|
|
623
|
-
`meta.service_registry.selected_instance_for_socket:${
|
|
632
|
+
`meta.service_registry.selected_instance_for_socket:${socketKey}`,
|
|
624
633
|
context
|
|
625
634
|
);
|
|
626
635
|
}
|
|
@@ -1611,6 +1620,46 @@ var RestController = class _RestController {
|
|
|
1611
1620
|
import { Server } from "socket.io";
|
|
1612
1621
|
import { RateLimiterMemory as RateLimiterMemory2 } from "rate-limiter-flexible";
|
|
1613
1622
|
import { io } from "socket.io-client";
|
|
1623
|
+
|
|
1624
|
+
// src/network/socketClientUtils.ts
|
|
1625
|
+
var waitForSocketConnection = async (socket, timeoutMs, createError) => {
|
|
1626
|
+
if (!socket) {
|
|
1627
|
+
return { ok: false, error: createError("disconnected") };
|
|
1628
|
+
}
|
|
1629
|
+
if (socket.connected) {
|
|
1630
|
+
return { ok: true };
|
|
1631
|
+
}
|
|
1632
|
+
return new Promise((resolve) => {
|
|
1633
|
+
let timer = null;
|
|
1634
|
+
let settled = false;
|
|
1635
|
+
const cleanup = () => {
|
|
1636
|
+
if (timer) {
|
|
1637
|
+
clearTimeout(timer);
|
|
1638
|
+
timer = null;
|
|
1639
|
+
}
|
|
1640
|
+
socket.off("connect", onConnect);
|
|
1641
|
+
socket.off("connect_error", onConnectError);
|
|
1642
|
+
socket.off("disconnect", onDisconnect);
|
|
1643
|
+
};
|
|
1644
|
+
const settle = (outcome) => {
|
|
1645
|
+
if (settled) return;
|
|
1646
|
+
settled = true;
|
|
1647
|
+
cleanup();
|
|
1648
|
+
resolve(outcome);
|
|
1649
|
+
};
|
|
1650
|
+
const onConnect = () => settle({ ok: true });
|
|
1651
|
+
const onConnectError = (error) => settle({ ok: false, error: createError("connect_error", error) });
|
|
1652
|
+
const onDisconnect = () => settle({ ok: false, error: createError("disconnected") });
|
|
1653
|
+
socket.once("connect", onConnect);
|
|
1654
|
+
socket.once("connect_error", onConnectError);
|
|
1655
|
+
socket.once("disconnect", onDisconnect);
|
|
1656
|
+
timer = setTimeout(() => {
|
|
1657
|
+
settle({ ok: false, error: createError("connect_timeout") });
|
|
1658
|
+
}, timeoutMs);
|
|
1659
|
+
});
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
// src/network/SocketController.ts
|
|
1614
1663
|
var SocketController = class _SocketController {
|
|
1615
1664
|
static get instance() {
|
|
1616
1665
|
if (!this._instance) this._instance = new _SocketController();
|
|
@@ -1886,35 +1935,71 @@ var SocketController = class _SocketController {
|
|
|
1886
1935
|
});
|
|
1887
1936
|
emitWhenReady = (event, data, timeoutMs = 6e4, ack) => {
|
|
1888
1937
|
return new Promise((resolve) => {
|
|
1889
|
-
const
|
|
1890
|
-
|
|
1891
|
-
|
|
1938
|
+
const resolveWithError = (errorMessage, fallbackError) => {
|
|
1939
|
+
resolve({
|
|
1940
|
+
...data,
|
|
1941
|
+
errored: true,
|
|
1942
|
+
__error: errorMessage,
|
|
1943
|
+
error: fallbackError instanceof Error ? fallbackError.message : errorMessage,
|
|
1944
|
+
socketId: socket?.id,
|
|
1945
|
+
serviceName,
|
|
1946
|
+
URL
|
|
1947
|
+
});
|
|
1948
|
+
};
|
|
1949
|
+
const tryEmit = async () => {
|
|
1950
|
+
const waitTimeoutMs = timeoutMs > 0 ? timeoutMs + 10 : 1e4;
|
|
1951
|
+
const waitResult = await waitForSocketConnection(
|
|
1952
|
+
socket,
|
|
1953
|
+
waitTimeoutMs,
|
|
1954
|
+
(reason, error) => {
|
|
1955
|
+
if (reason === "connect_timeout") {
|
|
1956
|
+
return `Socket connect timed out before '${event}'`;
|
|
1957
|
+
}
|
|
1958
|
+
if (reason === "connect_error") {
|
|
1959
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
1960
|
+
return `Socket connect error before '${event}': ${errMessage}`;
|
|
1961
|
+
}
|
|
1962
|
+
return `Socket disconnected before '${event}'`;
|
|
1963
|
+
}
|
|
1964
|
+
);
|
|
1965
|
+
if (!waitResult.ok) {
|
|
1966
|
+
CadenzaService.log(
|
|
1967
|
+
waitResult.error,
|
|
1968
|
+
{ socketId: socket?.id, serviceName, URL, event },
|
|
1969
|
+
"error"
|
|
1970
|
+
);
|
|
1971
|
+
resolveWithError(waitResult.error);
|
|
1892
1972
|
return;
|
|
1893
1973
|
}
|
|
1894
|
-
let timer;
|
|
1974
|
+
let timer = null;
|
|
1895
1975
|
if (timeoutMs !== 0) {
|
|
1896
1976
|
timer = setTimeout(() => {
|
|
1977
|
+
if (timer) {
|
|
1978
|
+
pendingTimers.delete(timer);
|
|
1979
|
+
timer = null;
|
|
1980
|
+
}
|
|
1897
1981
|
CadenzaService.log(
|
|
1898
1982
|
`Socket event '${event}' timed out`,
|
|
1899
1983
|
{ socketId: socket?.id, serviceName, URL },
|
|
1900
1984
|
"error"
|
|
1901
1985
|
);
|
|
1902
|
-
|
|
1903
|
-
...data,
|
|
1904
|
-
errored: true,
|
|
1905
|
-
__error: `Socket event '${event}' timed out`,
|
|
1906
|
-
error: `Socket event '${event}' timed out`,
|
|
1907
|
-
socketId: socket?.id,
|
|
1908
|
-
serviceName,
|
|
1909
|
-
URL
|
|
1910
|
-
});
|
|
1986
|
+
resolveWithError(`Socket event '${event}' timed out`);
|
|
1911
1987
|
}, timeoutMs + 10);
|
|
1912
1988
|
pendingTimers.add(timer);
|
|
1913
1989
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1990
|
+
const connectedSocket = socket;
|
|
1991
|
+
if (!connectedSocket) {
|
|
1992
|
+
resolveWithError(
|
|
1993
|
+
`Socket unavailable before emitting '${event}'`
|
|
1994
|
+
);
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
connectedSocket.timeout(timeoutMs).emit(event, data, (err, response) => {
|
|
1998
|
+
if (timer) {
|
|
1999
|
+
clearTimeout(timer);
|
|
2000
|
+
pendingTimers.delete(timer);
|
|
2001
|
+
timer = null;
|
|
2002
|
+
}
|
|
1918
2003
|
if (err) {
|
|
1919
2004
|
CadenzaService.log(
|
|
1920
2005
|
"Socket timeout.",
|
|
@@ -1937,11 +2022,7 @@ var SocketController = class _SocketController {
|
|
|
1937
2022
|
resolve(response);
|
|
1938
2023
|
});
|
|
1939
2024
|
};
|
|
1940
|
-
|
|
1941
|
-
tryEmit();
|
|
1942
|
-
} else {
|
|
1943
|
-
socket?.once("connect", tryEmit);
|
|
1944
|
-
}
|
|
2025
|
+
void tryEmit();
|
|
1945
2026
|
});
|
|
1946
2027
|
};
|
|
1947
2028
|
socket.on("connect", () => {
|
|
@@ -2258,14 +2339,25 @@ var GraphMetadataController = class _GraphMetadataController {
|
|
|
2258
2339
|
return {
|
|
2259
2340
|
data: {
|
|
2260
2341
|
...ctx.data,
|
|
2261
|
-
serviceName: CadenzaService.serviceRegistry.serviceName
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2342
|
+
serviceName: CadenzaService.serviceRegistry.serviceName,
|
|
2343
|
+
inputContextSchemaId: ctx.data.inputContextSchemaId ? {
|
|
2344
|
+
subOperation: "insert",
|
|
2345
|
+
table: "context_schema",
|
|
2346
|
+
data: {
|
|
2347
|
+
...ctx.data.inputContextSchemaId
|
|
2348
|
+
},
|
|
2349
|
+
return: "uuid"
|
|
2350
|
+
} : null,
|
|
2351
|
+
outputContextSchemaId: ctx.data.outputContextSchemaId ? {
|
|
2352
|
+
subOperation: "insert",
|
|
2353
|
+
table: "context_schema",
|
|
2354
|
+
data: {
|
|
2355
|
+
...ctx.data.outputContextSchemaId
|
|
2356
|
+
},
|
|
2357
|
+
return: "uuid"
|
|
2358
|
+
} : null
|
|
2359
|
+
},
|
|
2360
|
+
transaction: true
|
|
2269
2361
|
};
|
|
2270
2362
|
}).doOn("meta.task.created").emits("global.meta.graph_metadata.task_created");
|
|
2271
2363
|
CadenzaService.createMetaTask("Handle task update", (ctx) => {
|
|
@@ -3573,9 +3665,9 @@ var DatabaseController = class _DatabaseController {
|
|
|
3573
3665
|
createDatabaseTask(op, tableName, table, queryFunction, options) {
|
|
3574
3666
|
const opAction = op === "query" ? "queried" : op === "insert" ? "inserted" : op === "update" ? "updated" : op === "delete" ? "deleted" : "";
|
|
3575
3667
|
const defaultSignal = `global.${options.isMeta ? "meta." : ""}${tableName}.${opAction}`;
|
|
3576
|
-
const
|
|
3577
|
-
const
|
|
3578
|
-
CadenzaService.createThrottledTask(
|
|
3668
|
+
const taskName = `${op.charAt(0).toUpperCase() + op.slice(1)} ${tableName}`;
|
|
3669
|
+
const schema = this.getInputSchema(op, tableName, table);
|
|
3670
|
+
const task = CadenzaService.createThrottledTask(
|
|
3579
3671
|
taskName,
|
|
3580
3672
|
async (context, emit) => {
|
|
3581
3673
|
for (const action of Object.keys(table.customSignals?.triggers ?? {})) {
|
|
@@ -3670,17 +3762,8 @@ var DatabaseController = class _DatabaseController {
|
|
|
3670
3762
|
{
|
|
3671
3763
|
isMeta: options.isMeta,
|
|
3672
3764
|
isSubMeta: options.isMeta,
|
|
3673
|
-
validateInputContext:
|
|
3674
|
-
|
|
3675
|
-
inputSchema: {
|
|
3676
|
-
// TODO
|
|
3677
|
-
type: "object",
|
|
3678
|
-
properties: {
|
|
3679
|
-
filter: {
|
|
3680
|
-
type: "object"
|
|
3681
|
-
}
|
|
3682
|
-
}
|
|
3683
|
-
}
|
|
3765
|
+
validateInputContext: options.securityProfile !== "low",
|
|
3766
|
+
inputSchema: schema
|
|
3684
3767
|
}
|
|
3685
3768
|
).doOn(
|
|
3686
3769
|
...table.customSignals?.triggers?.[op]?.map((signal) => {
|
|
@@ -3691,8 +3774,382 @@ var DatabaseController = class _DatabaseController {
|
|
|
3691
3774
|
return typeof signal === "string" ? signal : signal.signal;
|
|
3692
3775
|
}) ?? []
|
|
3693
3776
|
);
|
|
3777
|
+
if (op === "query") {
|
|
3778
|
+
const intentName = `query-${CadenzaService.serviceRegistry.serviceName}-${tableName}`;
|
|
3779
|
+
CadenzaService.defineIntent({
|
|
3780
|
+
name: intentName,
|
|
3781
|
+
description: `Perform a query operation on the ${tableName} table`,
|
|
3782
|
+
input: schema
|
|
3783
|
+
});
|
|
3784
|
+
task.respondsTo(intentName);
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
getInputSchema(op, tableName, table) {
|
|
3788
|
+
const inputSchema = {
|
|
3789
|
+
type: "object",
|
|
3790
|
+
properties: {
|
|
3791
|
+
queryData: {
|
|
3792
|
+
type: "object",
|
|
3793
|
+
properties: {},
|
|
3794
|
+
strict: true
|
|
3795
|
+
}
|
|
3796
|
+
},
|
|
3797
|
+
strict: true
|
|
3798
|
+
};
|
|
3799
|
+
if (!inputSchema.properties) {
|
|
3800
|
+
return inputSchema;
|
|
3801
|
+
}
|
|
3802
|
+
inputSchema.properties.transaction = getTransactionSchema();
|
|
3803
|
+
inputSchema.properties.queryData.properties.transaction = inputSchema.properties.transaction;
|
|
3804
|
+
switch (op) {
|
|
3805
|
+
case "insert":
|
|
3806
|
+
inputSchema.properties.data = getInsertDataSchemaFromTable(
|
|
3807
|
+
table,
|
|
3808
|
+
tableName
|
|
3809
|
+
);
|
|
3810
|
+
inputSchema.properties.queryData.properties.data = inputSchema.properties.data;
|
|
3811
|
+
inputSchema.properties.batch = getQueryBatchSchemaFromTable();
|
|
3812
|
+
inputSchema.properties.queryData.properties.batch = inputSchema.properties.batch;
|
|
3813
|
+
inputSchema.properties.onConflict = getQueryOnConflictSchemaFromTable(
|
|
3814
|
+
table,
|
|
3815
|
+
tableName
|
|
3816
|
+
);
|
|
3817
|
+
inputSchema.properties.queryData.properties.onConflict = inputSchema.properties.onConflict;
|
|
3818
|
+
break;
|
|
3819
|
+
case "query":
|
|
3820
|
+
inputSchema.properties.filter = getQueryFilterSchemaFromTable(
|
|
3821
|
+
table,
|
|
3822
|
+
tableName
|
|
3823
|
+
);
|
|
3824
|
+
inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
|
|
3825
|
+
inputSchema.properties.fields = getQueryFieldsSchemaFromTable(
|
|
3826
|
+
table,
|
|
3827
|
+
tableName
|
|
3828
|
+
);
|
|
3829
|
+
inputSchema.properties.queryData.properties.fields = inputSchema.properties.fields;
|
|
3830
|
+
inputSchema.properties.joins = getQueryJoinsSchemaFromTable(
|
|
3831
|
+
table,
|
|
3832
|
+
tableName
|
|
3833
|
+
);
|
|
3834
|
+
inputSchema.properties.queryData.properties.joins = inputSchema.properties.joins;
|
|
3835
|
+
inputSchema.properties.sort = getQuerySortSchemaFromTable(
|
|
3836
|
+
table,
|
|
3837
|
+
tableName
|
|
3838
|
+
);
|
|
3839
|
+
inputSchema.properties.queryData.properties.sort = inputSchema.properties.sort;
|
|
3840
|
+
inputSchema.properties.limit = getQueryLimitSchemaFromTable();
|
|
3841
|
+
inputSchema.properties.queryData.properties.limit = inputSchema.properties.limit;
|
|
3842
|
+
inputSchema.properties.offset = getQueryOffsetSchemaFromTable();
|
|
3843
|
+
inputSchema.properties.queryData.properties.offset = inputSchema.properties.offset;
|
|
3844
|
+
break;
|
|
3845
|
+
case "update":
|
|
3846
|
+
inputSchema.properties.filter = getQueryFilterSchemaFromTable(
|
|
3847
|
+
table,
|
|
3848
|
+
tableName
|
|
3849
|
+
);
|
|
3850
|
+
inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
|
|
3851
|
+
inputSchema.properties.fields = getQueryFieldsSchemaFromTable(
|
|
3852
|
+
table,
|
|
3853
|
+
tableName
|
|
3854
|
+
);
|
|
3855
|
+
inputSchema.properties.queryData.properties.fields = inputSchema.properties.fields;
|
|
3856
|
+
break;
|
|
3857
|
+
case "delete":
|
|
3858
|
+
inputSchema.properties.filter = getQueryFilterSchemaFromTable(
|
|
3859
|
+
table,
|
|
3860
|
+
tableName
|
|
3861
|
+
);
|
|
3862
|
+
inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
|
|
3863
|
+
break;
|
|
3864
|
+
}
|
|
3865
|
+
return inputSchema;
|
|
3694
3866
|
}
|
|
3695
3867
|
};
|
|
3868
|
+
function getInsertDataSchemaFromTable(table, tableName) {
|
|
3869
|
+
const dataSchema = {
|
|
3870
|
+
type: "object",
|
|
3871
|
+
properties: {
|
|
3872
|
+
...Object.fromEntries(
|
|
3873
|
+
Object.entries(table.fields).map((field) => {
|
|
3874
|
+
return [
|
|
3875
|
+
field[0],
|
|
3876
|
+
[
|
|
3877
|
+
{
|
|
3878
|
+
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3879
|
+
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3880
|
+
},
|
|
3881
|
+
{
|
|
3882
|
+
type: "string",
|
|
3883
|
+
constraints: {
|
|
3884
|
+
oneOf: ["increment", "decrement", "set"]
|
|
3885
|
+
}
|
|
3886
|
+
},
|
|
3887
|
+
{
|
|
3888
|
+
type: "object",
|
|
3889
|
+
properties: {
|
|
3890
|
+
subOperation: {
|
|
3891
|
+
type: "string",
|
|
3892
|
+
enum: ["insert", "query"]
|
|
3893
|
+
},
|
|
3894
|
+
table: {
|
|
3895
|
+
type: "string"
|
|
3896
|
+
},
|
|
3897
|
+
data: [
|
|
3898
|
+
{
|
|
3899
|
+
type: "object"
|
|
3900
|
+
},
|
|
3901
|
+
{
|
|
3902
|
+
type: "array",
|
|
3903
|
+
items: {
|
|
3904
|
+
type: "object"
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
],
|
|
3908
|
+
filter: {
|
|
3909
|
+
type: "object"
|
|
3910
|
+
},
|
|
3911
|
+
fields: {
|
|
3912
|
+
type: "array",
|
|
3913
|
+
items: {
|
|
3914
|
+
type: "string"
|
|
3915
|
+
}
|
|
3916
|
+
},
|
|
3917
|
+
return: {
|
|
3918
|
+
type: "string"
|
|
3919
|
+
}
|
|
3920
|
+
},
|
|
3921
|
+
required: ["subOperation", "table"]
|
|
3922
|
+
}
|
|
3923
|
+
]
|
|
3924
|
+
];
|
|
3925
|
+
})
|
|
3926
|
+
)
|
|
3927
|
+
},
|
|
3928
|
+
required: Object.entries(table.fields).filter((field) => field[1].required || field[1].primary).map((field) => field[0]),
|
|
3929
|
+
strict: true
|
|
3930
|
+
};
|
|
3931
|
+
return [
|
|
3932
|
+
dataSchema,
|
|
3933
|
+
{
|
|
3934
|
+
type: "array",
|
|
3935
|
+
items: dataSchema
|
|
3936
|
+
}
|
|
3937
|
+
];
|
|
3938
|
+
}
|
|
3939
|
+
function getQueryFilterSchemaFromTable(table, tableName) {
|
|
3940
|
+
return {
|
|
3941
|
+
type: "object",
|
|
3942
|
+
properties: {
|
|
3943
|
+
...Object.fromEntries(
|
|
3944
|
+
Object.entries(table.fields).map((field) => {
|
|
3945
|
+
return [
|
|
3946
|
+
field[0],
|
|
3947
|
+
[
|
|
3948
|
+
{
|
|
3949
|
+
type: tableFieldTypeToSchemaType(field[1].type),
|
|
3950
|
+
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
3951
|
+
},
|
|
3952
|
+
{
|
|
3953
|
+
type: "array",
|
|
3954
|
+
items: {
|
|
3955
|
+
type: tableFieldTypeToSchemaType(field[1].type)
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
]
|
|
3959
|
+
];
|
|
3960
|
+
})
|
|
3961
|
+
)
|
|
3962
|
+
},
|
|
3963
|
+
strict: true,
|
|
3964
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
function getQueryFieldsSchemaFromTable(table, tableName) {
|
|
3968
|
+
return {
|
|
3969
|
+
type: "array",
|
|
3970
|
+
items: {
|
|
3971
|
+
type: "string",
|
|
3972
|
+
constraints: {
|
|
3973
|
+
oneOf: Object.keys(table.fields)
|
|
3974
|
+
}
|
|
3975
|
+
},
|
|
3976
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
|
|
3977
|
+
};
|
|
3978
|
+
}
|
|
3979
|
+
function getQueryJoinsSchemaFromTable(table, tableName) {
|
|
3980
|
+
return {
|
|
3981
|
+
type: "object",
|
|
3982
|
+
properties: {
|
|
3983
|
+
...Object.fromEntries(
|
|
3984
|
+
Object.entries(table.fields).map((field) => {
|
|
3985
|
+
return [
|
|
3986
|
+
field[0],
|
|
3987
|
+
{
|
|
3988
|
+
type: "object",
|
|
3989
|
+
properties: {
|
|
3990
|
+
on: {
|
|
3991
|
+
type: "string"
|
|
3992
|
+
},
|
|
3993
|
+
fields: {
|
|
3994
|
+
type: "array",
|
|
3995
|
+
items: {
|
|
3996
|
+
type: "string"
|
|
3997
|
+
}
|
|
3998
|
+
},
|
|
3999
|
+
filter: {
|
|
4000
|
+
type: "object"
|
|
4001
|
+
},
|
|
4002
|
+
returnAs: {
|
|
4003
|
+
type: "string",
|
|
4004
|
+
constraints: {
|
|
4005
|
+
oneOf: ["array", "object"]
|
|
4006
|
+
}
|
|
4007
|
+
},
|
|
4008
|
+
alias: {
|
|
4009
|
+
type: "string"
|
|
4010
|
+
},
|
|
4011
|
+
joins: {
|
|
4012
|
+
type: "object"
|
|
4013
|
+
}
|
|
4014
|
+
},
|
|
4015
|
+
required: ["on", "fields"],
|
|
4016
|
+
strict: true
|
|
4017
|
+
}
|
|
4018
|
+
];
|
|
4019
|
+
})
|
|
4020
|
+
)
|
|
4021
|
+
},
|
|
4022
|
+
strict: true,
|
|
4023
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
|
|
4024
|
+
};
|
|
4025
|
+
}
|
|
4026
|
+
function getQuerySortSchemaFromTable(table, tableName) {
|
|
4027
|
+
return {
|
|
4028
|
+
type: "object",
|
|
4029
|
+
properties: {
|
|
4030
|
+
...Object.fromEntries(
|
|
4031
|
+
Object.entries(table.fields).map((field) => {
|
|
4032
|
+
return [
|
|
4033
|
+
field[0],
|
|
4034
|
+
{
|
|
4035
|
+
type: "string",
|
|
4036
|
+
constraints: {
|
|
4037
|
+
oneOf: ["asc", "desc"]
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
];
|
|
4041
|
+
})
|
|
4042
|
+
)
|
|
4043
|
+
},
|
|
4044
|
+
strict: true,
|
|
4045
|
+
description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
|
|
4046
|
+
};
|
|
4047
|
+
}
|
|
4048
|
+
function getQueryLimitSchemaFromTable() {
|
|
4049
|
+
return {
|
|
4050
|
+
type: "number",
|
|
4051
|
+
constraints: {
|
|
4052
|
+
min: 1
|
|
4053
|
+
},
|
|
4054
|
+
description: "Limit for query results"
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
function getQueryOffsetSchemaFromTable() {
|
|
4058
|
+
return {
|
|
4059
|
+
type: "number",
|
|
4060
|
+
constraints: {
|
|
4061
|
+
min: 0
|
|
4062
|
+
},
|
|
4063
|
+
description: "Offset for query results"
|
|
4064
|
+
};
|
|
4065
|
+
}
|
|
4066
|
+
function getTransactionSchema() {
|
|
4067
|
+
return {
|
|
4068
|
+
type: "boolean",
|
|
4069
|
+
description: "Whether to run the query in a transaction"
|
|
4070
|
+
};
|
|
4071
|
+
}
|
|
4072
|
+
function getQueryBatchSchemaFromTable() {
|
|
4073
|
+
return {
|
|
4074
|
+
type: "boolean",
|
|
4075
|
+
description: "Whether to run the query in batch mode"
|
|
4076
|
+
};
|
|
4077
|
+
}
|
|
4078
|
+
function getQueryOnConflictSchemaFromTable(table, tableName) {
|
|
4079
|
+
return {
|
|
4080
|
+
type: "object",
|
|
4081
|
+
properties: {
|
|
4082
|
+
target: {
|
|
4083
|
+
type: "array",
|
|
4084
|
+
items: {
|
|
4085
|
+
type: "string",
|
|
4086
|
+
constraints: {
|
|
4087
|
+
oneOf: Object.keys(table.fields)
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
},
|
|
4091
|
+
action: {
|
|
4092
|
+
type: "object",
|
|
4093
|
+
properties: {
|
|
4094
|
+
do: {
|
|
4095
|
+
type: "string",
|
|
4096
|
+
constraints: {
|
|
4097
|
+
oneOf: ["nothing", "update"]
|
|
4098
|
+
}
|
|
4099
|
+
},
|
|
4100
|
+
set: {
|
|
4101
|
+
type: "object",
|
|
4102
|
+
properties: {
|
|
4103
|
+
...Object.fromEntries(
|
|
4104
|
+
Object.entries(table.fields).map((field) => {
|
|
4105
|
+
return [
|
|
4106
|
+
field[0],
|
|
4107
|
+
[
|
|
4108
|
+
{
|
|
4109
|
+
type: tableFieldTypeToSchemaType(field[1].type),
|
|
4110
|
+
description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
|
|
4111
|
+
}
|
|
4112
|
+
]
|
|
4113
|
+
];
|
|
4114
|
+
})
|
|
4115
|
+
)
|
|
4116
|
+
}
|
|
4117
|
+
},
|
|
4118
|
+
where: {
|
|
4119
|
+
type: "string"
|
|
4120
|
+
}
|
|
4121
|
+
},
|
|
4122
|
+
required: ["do"]
|
|
4123
|
+
}
|
|
4124
|
+
},
|
|
4125
|
+
required: ["target", "action"],
|
|
4126
|
+
strict: true
|
|
4127
|
+
};
|
|
4128
|
+
}
|
|
4129
|
+
function tableFieldTypeToSchemaType(type) {
|
|
4130
|
+
switch (type) {
|
|
4131
|
+
case "varchar":
|
|
4132
|
+
case "text":
|
|
4133
|
+
case "jsonb":
|
|
4134
|
+
case "uuid":
|
|
4135
|
+
case "date":
|
|
4136
|
+
case "geo_point":
|
|
4137
|
+
case "bytea":
|
|
4138
|
+
return "string";
|
|
4139
|
+
case "int":
|
|
4140
|
+
case "bigint":
|
|
4141
|
+
case "decimal":
|
|
4142
|
+
case "timestamp":
|
|
4143
|
+
return "number";
|
|
4144
|
+
case "boolean":
|
|
4145
|
+
return "boolean";
|
|
4146
|
+
case "array":
|
|
4147
|
+
return "array";
|
|
4148
|
+
case "object":
|
|
4149
|
+
return "object";
|
|
4150
|
+
}
|
|
4151
|
+
return "any";
|
|
4152
|
+
}
|
|
3696
4153
|
|
|
3697
4154
|
// src/Cadenza.ts
|
|
3698
4155
|
import { v4 as uuid3 } from "uuid";
|
|
@@ -4566,10 +5023,9 @@ var CadenzaService = class {
|
|
|
4566
5023
|
this.bootstrap();
|
|
4567
5024
|
this.validateName(tableName);
|
|
4568
5025
|
this.validateName(operation);
|
|
4569
|
-
const tableNameFormatted = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
4570
5026
|
const name = `${operation.charAt(0).toUpperCase() + operation.slice(1)} ${tableName} in ${databaseServiceName ?? "default database service"}`;
|
|
4571
5027
|
const description = `Executes a ${operation} on table ${tableName} in ${databaseServiceName ?? "default database service"}`;
|
|
4572
|
-
const taskName =
|
|
5028
|
+
const taskName = `${operation.charAt(0).toUpperCase() + operation.slice(1)} ${tableName}`;
|
|
4573
5029
|
options = {
|
|
4574
5030
|
concurrency: 100,
|
|
4575
5031
|
timeout: 0,
|
|
@@ -4831,7 +5287,7 @@ var CadenzaService = class {
|
|
|
4831
5287
|
* This method is not supported in a browser environment and will log a warning if called in such an environment.
|
|
4832
5288
|
*
|
|
4833
5289
|
* @param {string} name - The name of the database service to be created.
|
|
4834
|
-
* @param {
|
|
5290
|
+
* @param {DatabaseSchemaDefinition} schema - The schema definition for the database service.
|
|
4835
5291
|
* @param {string} [description=""] - An optional description of the database service.
|
|
4836
5292
|
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional configuration settings for the database and server.
|
|
4837
5293
|
* @return {void} This method does not return a value.
|
|
@@ -4895,7 +5351,7 @@ var CadenzaService = class {
|
|
|
4895
5351
|
* Creates a meta database service with the specified configuration.
|
|
4896
5352
|
*
|
|
4897
5353
|
* @param {string} name - The name of the database service to be created.
|
|
4898
|
-
* @param {
|
|
5354
|
+
* @param {DatabaseSchemaDefinition} schema - The schema definition for the database.
|
|
4899
5355
|
* @param {string} [description=""] - An optional description of the database service.
|
|
4900
5356
|
* @param {ServerOptions & DatabaseOptions} [options={}] - Optional server and database configuration options. The `isMeta` flag will be automatically set to true.
|
|
4901
5357
|
* @return {void} - This method does not return a value.
|