@restura/core 0.1.0-alpha.35 → 0.1.0-alpha.37
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 +15 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +211 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -129,7 +129,7 @@ var EventManager = class {
|
|
|
129
129
|
if (!this.hasHandlersForEventType("DATABASE_ROW_INSERT", filter, triggerResult)) return;
|
|
130
130
|
const insertData = {
|
|
131
131
|
tableName: triggerResult.table,
|
|
132
|
-
|
|
132
|
+
insertedId: triggerResult.insertedId || 0,
|
|
133
133
|
insertObject: triggerResult.record,
|
|
134
134
|
queryMetadata: data.queryMetadata
|
|
135
135
|
};
|
|
@@ -145,6 +145,7 @@ var EventManager = class {
|
|
|
145
145
|
if (!this.hasHandlersForEventType("DATABASE_ROW_DELETE", filter, triggerResult)) return;
|
|
146
146
|
const deleteData = {
|
|
147
147
|
tableName: triggerResult.table,
|
|
148
|
+
deletedId: triggerResult.deletedId || 0,
|
|
148
149
|
deletedRow: triggerResult.previousRecord,
|
|
149
150
|
queryMetadata: data.queryMetadata
|
|
150
151
|
};
|
|
@@ -160,7 +161,7 @@ var EventManager = class {
|
|
|
160
161
|
if (!this.hasHandlersForEventType("DATABASE_COLUMN_UPDATE", filter, triggerResult)) return;
|
|
161
162
|
const columnChangeData = {
|
|
162
163
|
tableName: triggerResult.table,
|
|
163
|
-
|
|
164
|
+
changedId: triggerResult.changedId || 0,
|
|
164
165
|
newData: triggerResult.record,
|
|
165
166
|
oldData: triggerResult.previousRecord,
|
|
166
167
|
queryMetadata: data.queryMetadata
|
|
@@ -504,7 +505,7 @@ var SqlUtils = class _SqlUtils {
|
|
|
504
505
|
static convertDatabaseTypeToTypescript(type, value) {
|
|
505
506
|
type = type.toLocaleLowerCase();
|
|
506
507
|
if (type.startsWith("tinyint") || type.startsWith("boolean")) return "boolean";
|
|
507
|
-
if (type.indexOf("int") > -1 || type.startsWith("decimal") || type.startsWith("double") || type.startsWith("float"))
|
|
508
|
+
if (type.indexOf("int") > -1 || type.startsWith("decimal") || type.startsWith("double") || type.startsWith("float") || type.indexOf("serial") > -1 || type.startsWith("decimal") || type.startsWith("real") || type.startsWith("double precision") || type.startsWith("numeric"))
|
|
508
509
|
return "number";
|
|
509
510
|
if (type === "json") {
|
|
510
511
|
if (!value) return "object";
|
|
@@ -786,21 +787,28 @@ var ApiTree = class _ApiTree {
|
|
|
786
787
|
return `export type Res = CustomTypes.${route.responseType}[]`;
|
|
787
788
|
else return `export type Res = CustomTypes.${route.responseType}`;
|
|
788
789
|
}
|
|
789
|
-
return `export interface Res ${this.getFields(route.response)}`;
|
|
790
|
+
return `export interface Res ${this.getFields(route.response, route.table, route.joins)}`;
|
|
790
791
|
}
|
|
791
|
-
getFields(fields) {
|
|
792
|
-
const nameFields = fields.map((f) => this.getNameAndType(f));
|
|
792
|
+
getFields(fields, routeBaseTable, joins) {
|
|
793
|
+
const nameFields = fields.map((f) => this.getNameAndType(f, routeBaseTable, joins));
|
|
793
794
|
const nested = `{
|
|
794
795
|
${nameFields.join(";\n ")}${ObjectUtils.isArrayWithData(nameFields) ? ";" : ""}
|
|
795
796
|
}`;
|
|
796
797
|
return nested;
|
|
797
798
|
}
|
|
798
|
-
getNameAndType(p) {
|
|
799
|
+
getNameAndType(p, routeBaseTable, joins) {
|
|
799
800
|
let responseType = "any", isNullable = false, array = false;
|
|
800
801
|
if (p.selector) {
|
|
801
802
|
({ responseType, isNullable } = this.getTypeFromTable(p.selector, p.name));
|
|
803
|
+
const selectorKey = p.selector.split(".")[0];
|
|
804
|
+
if (selectorKey !== routeBaseTable) {
|
|
805
|
+
const join = joins.find((j) => j.alias === selectorKey);
|
|
806
|
+
if (join && join.type !== "INNER") {
|
|
807
|
+
isNullable = true;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
802
810
|
} else if (p.subquery) {
|
|
803
|
-
responseType = this.getFields(p.subquery.properties);
|
|
811
|
+
responseType = this.getFields(p.subquery.properties, p.subquery.table, p.subquery.joins);
|
|
804
812
|
array = true;
|
|
805
813
|
}
|
|
806
814
|
return `${p.name}:${responseType}${array ? "[]" : ""}${isNullable ? " | null" : ""}`;
|
|
@@ -1266,7 +1274,8 @@ var tableDataSchema = z3.object({
|
|
|
1266
1274
|
indexes: z3.array(indexDataSchema),
|
|
1267
1275
|
foreignKeys: z3.array(foreignKeyDataSchema),
|
|
1268
1276
|
checkConstraints: z3.array(checkConstraintDataSchema),
|
|
1269
|
-
roles: z3.array(z3.string())
|
|
1277
|
+
roles: z3.array(z3.string()),
|
|
1278
|
+
notify: z3.union([z3.literal("ALL"), z3.array(z3.string())]).optional()
|
|
1270
1279
|
}).strict();
|
|
1271
1280
|
var endpointDataSchema = z3.object({
|
|
1272
1281
|
name: z3.string(),
|
|
@@ -1560,10 +1569,11 @@ function insertObjectQuery(table, obj) {
|
|
|
1560
1569
|
const params = Object.values(obj);
|
|
1561
1570
|
const columns = keys.map((column) => escapeColumnName(column)).join(", ");
|
|
1562
1571
|
const values = params.map((value) => SQL`${value}`).join(", ");
|
|
1563
|
-
|
|
1572
|
+
let query = `
|
|
1564
1573
|
INSERT INTO "${table}" (${columns})
|
|
1565
1574
|
VALUES (${values})
|
|
1566
1575
|
RETURNING *`;
|
|
1576
|
+
query = query.replace(/'(\?)'/, "?");
|
|
1567
1577
|
return query;
|
|
1568
1578
|
}
|
|
1569
1579
|
function updateObjectQuery(table, obj, whereStatement) {
|
|
@@ -1939,16 +1949,8 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1939
1949
|
});
|
|
1940
1950
|
}
|
|
1941
1951
|
async handleTrigger(payload, mutationType) {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
if (match) {
|
|
1945
|
-
const jsonString = match[0].slice(match[0].indexOf("{"), match[0].lastIndexOf("}") + 1);
|
|
1946
|
-
const queryMetadata = ObjectUtils4.safeParse(jsonString);
|
|
1947
|
-
const triggerFromThisInstance = queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId;
|
|
1948
|
-
if (!triggerFromThisInstance) {
|
|
1949
|
-
return;
|
|
1950
|
-
}
|
|
1951
|
-
await eventManager_default.fireActionFromDbTrigger({ queryMetadata, mutationType }, payload);
|
|
1952
|
+
if (payload.queryMetadata && payload.queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId) {
|
|
1953
|
+
await eventManager_default.fireActionFromDbTrigger({ queryMetadata: payload.queryMetadata, mutationType }, payload);
|
|
1952
1954
|
}
|
|
1953
1955
|
}
|
|
1954
1956
|
async createDatabaseFromSchema(schema, connection) {
|
|
@@ -1961,9 +1963,11 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1961
1963
|
const indexes = [];
|
|
1962
1964
|
const triggers = [];
|
|
1963
1965
|
for (const table of schema.database) {
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1966
|
+
if (table.notify) {
|
|
1967
|
+
triggers.push(this.createInsertTriggers(table.name, table.notify));
|
|
1968
|
+
triggers.push(this.createUpdateTrigger(table.name, table.notify));
|
|
1969
|
+
triggers.push(this.createDeleteTrigger(table.name, table.notify));
|
|
1970
|
+
}
|
|
1967
1971
|
let sql = `CREATE TABLE "${table.name}"
|
|
1968
1972
|
( `;
|
|
1969
1973
|
const tableColumns = [];
|
|
@@ -2390,53 +2394,216 @@ DELETE FROM "${routeData.table}" ${joinStatement} ${whereClause}`;
|
|
|
2390
2394
|
}
|
|
2391
2395
|
return whereClause;
|
|
2392
2396
|
}
|
|
2393
|
-
createUpdateTrigger(tableName) {
|
|
2394
|
-
return
|
|
2397
|
+
createUpdateTrigger(tableName, notify) {
|
|
2398
|
+
if (!notify) return "";
|
|
2399
|
+
if (notify === "ALL") {
|
|
2400
|
+
return `
|
|
2395
2401
|
CREATE OR REPLACE FUNCTION notify_${tableName}_update()
|
|
2396
|
-
|
|
2402
|
+
RETURNS TRIGGER AS $$
|
|
2403
|
+
DECLARE
|
|
2404
|
+
query_metadata JSON;
|
|
2397
2405
|
BEGIN
|
|
2398
|
-
|
|
2399
|
-
|
|
2406
|
+
SELECT INTO query_metadata
|
|
2407
|
+
(regexp_match(
|
|
2408
|
+
current_query(),
|
|
2409
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2410
|
+
))[1]::json;
|
|
2411
|
+
|
|
2412
|
+
PERFORM pg_notify(
|
|
2413
|
+
'update',
|
|
2414
|
+
json_build_object(
|
|
2415
|
+
'table', '${tableName}',
|
|
2416
|
+
'queryMetadata', query_metadata,
|
|
2417
|
+
'changedId', NEW.id,
|
|
2418
|
+
'record', NEW,
|
|
2419
|
+
'previousRecord', OLD
|
|
2420
|
+
)::text
|
|
2421
|
+
);
|
|
2422
|
+
RETURN NEW;
|
|
2400
2423
|
END;
|
|
2401
2424
|
$$ LANGUAGE plpgsql;
|
|
2402
2425
|
|
|
2403
2426
|
CREATE OR REPLACE TRIGGER ${tableName}_update
|
|
2404
|
-
|
|
2405
|
-
|
|
2427
|
+
AFTER UPDATE ON "${tableName}"
|
|
2428
|
+
FOR EACH ROW
|
|
2429
|
+
EXECUTE FUNCTION notify_${tableName}_update();
|
|
2430
|
+
`;
|
|
2431
|
+
}
|
|
2432
|
+
const notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW."${column}"`).join(",\n");
|
|
2433
|
+
const notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD."${column}"`).join(",\n");
|
|
2434
|
+
return `
|
|
2435
|
+
CREATE OR REPLACE FUNCTION notify_${tableName}_update()
|
|
2436
|
+
RETURNS TRIGGER AS $$
|
|
2437
|
+
DECLARE
|
|
2438
|
+
query_metadata JSON;
|
|
2439
|
+
BEGIN
|
|
2440
|
+
SELECT INTO query_metadata
|
|
2441
|
+
(regexp_match(
|
|
2442
|
+
current_query(),
|
|
2443
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2444
|
+
))[1]::json;
|
|
2445
|
+
|
|
2446
|
+
PERFORM pg_notify(
|
|
2447
|
+
'update',
|
|
2448
|
+
json_build_object(
|
|
2449
|
+
'table', '${tableName}',
|
|
2450
|
+
'queryMetadata', query_metadata,
|
|
2451
|
+
'changedId', NEW.id,
|
|
2452
|
+
'record', json_build_object(
|
|
2453
|
+
${notifyColumnNewBuildString}
|
|
2454
|
+
),
|
|
2455
|
+
'previousRecord', json_build_object(
|
|
2456
|
+
${notifyColumnOldBuildString}
|
|
2457
|
+
)
|
|
2458
|
+
)::text
|
|
2459
|
+
);
|
|
2460
|
+
RETURN NEW;
|
|
2461
|
+
END;
|
|
2462
|
+
$$ LANGUAGE plpgsql;
|
|
2463
|
+
|
|
2464
|
+
CREATE OR REPLACE TRIGGER ${tableName}_update
|
|
2465
|
+
AFTER UPDATE ON "${tableName}"
|
|
2466
|
+
FOR EACH ROW
|
|
2406
2467
|
EXECUTE FUNCTION notify_${tableName}_update();
|
|
2407
2468
|
`;
|
|
2408
2469
|
}
|
|
2409
|
-
createDeleteTrigger(tableName) {
|
|
2470
|
+
createDeleteTrigger(tableName, notify) {
|
|
2471
|
+
if (!notify) return "";
|
|
2472
|
+
if (notify === "ALL") {
|
|
2473
|
+
return `
|
|
2474
|
+
CREATE OR REPLACE FUNCTION notify_${tableName}_delete()
|
|
2475
|
+
RETURNS TRIGGER AS $$
|
|
2476
|
+
DECLARE
|
|
2477
|
+
query_metadata JSON;
|
|
2478
|
+
BEGIN
|
|
2479
|
+
SELECT INTO query_metadata
|
|
2480
|
+
(regexp_match(
|
|
2481
|
+
current_query(),
|
|
2482
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2483
|
+
))[1]::json;
|
|
2484
|
+
|
|
2485
|
+
PERFORM pg_notify(
|
|
2486
|
+
'delete',
|
|
2487
|
+
json_build_object(
|
|
2488
|
+
'table', '${tableName}',
|
|
2489
|
+
'queryMetadata', query_metadata,
|
|
2490
|
+
'deletedId', OLD.id,
|
|
2491
|
+
'previousRecord', OLD
|
|
2492
|
+
)::text
|
|
2493
|
+
);
|
|
2494
|
+
RETURN NEW;
|
|
2495
|
+
END;
|
|
2496
|
+
$$ LANGUAGE plpgsql;
|
|
2497
|
+
|
|
2498
|
+
CREATE OR REPLACE TRIGGER "${tableName}_delete"
|
|
2499
|
+
AFTER DELETE ON "${tableName}"
|
|
2500
|
+
FOR EACH ROW
|
|
2501
|
+
EXECUTE FUNCTION notify_${tableName}_delete();
|
|
2502
|
+
`;
|
|
2503
|
+
}
|
|
2504
|
+
const notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD."${column}"`).join(",\n");
|
|
2410
2505
|
return `
|
|
2411
2506
|
CREATE OR REPLACE FUNCTION notify_${tableName}_delete()
|
|
2412
|
-
|
|
2507
|
+
RETURNS TRIGGER AS $$
|
|
2508
|
+
DECLARE
|
|
2509
|
+
query_metadata JSON;
|
|
2413
2510
|
BEGIN
|
|
2414
|
-
|
|
2415
|
-
|
|
2511
|
+
SELECT INTO query_metadata
|
|
2512
|
+
(regexp_match(
|
|
2513
|
+
current_query(),
|
|
2514
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2515
|
+
))[1]::json;
|
|
2516
|
+
|
|
2517
|
+
PERFORM pg_notify(
|
|
2518
|
+
'delete',
|
|
2519
|
+
json_build_object(
|
|
2520
|
+
'table', '${tableName}',
|
|
2521
|
+
'queryMetadata', query_metadata,
|
|
2522
|
+
'deletedId', OLD.id,
|
|
2523
|
+
'previousRecord', json_build_object(
|
|
2524
|
+
${notifyColumnOldBuildString}
|
|
2525
|
+
)
|
|
2526
|
+
)::text
|
|
2527
|
+
);
|
|
2528
|
+
RETURN NEW;
|
|
2416
2529
|
END;
|
|
2417
2530
|
$$ LANGUAGE plpgsql;
|
|
2418
2531
|
|
|
2419
2532
|
CREATE OR REPLACE TRIGGER "${tableName}_delete"
|
|
2420
|
-
|
|
2421
|
-
|
|
2533
|
+
AFTER DELETE ON "${tableName}"
|
|
2534
|
+
FOR EACH ROW
|
|
2422
2535
|
EXECUTE FUNCTION notify_${tableName}_delete();
|
|
2423
2536
|
`;
|
|
2424
2537
|
}
|
|
2425
|
-
createInsertTriggers(tableName) {
|
|
2538
|
+
createInsertTriggers(tableName, notify) {
|
|
2539
|
+
if (!notify) return "";
|
|
2540
|
+
if (notify === "ALL") {
|
|
2541
|
+
return `
|
|
2542
|
+
CREATE OR REPLACE FUNCTION notify_${tableName}_insert()
|
|
2543
|
+
RETURNS TRIGGER AS $$
|
|
2544
|
+
DECLARE
|
|
2545
|
+
query_metadata JSON;
|
|
2546
|
+
BEGIN
|
|
2547
|
+
SELECT INTO query_metadata
|
|
2548
|
+
(regexp_match(
|
|
2549
|
+
current_query(),
|
|
2550
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2551
|
+
))[1]::json;
|
|
2552
|
+
|
|
2553
|
+
PERFORM pg_notify(
|
|
2554
|
+
'insert',
|
|
2555
|
+
json_build_object(
|
|
2556
|
+
'table', '${tableName}',
|
|
2557
|
+
'queryMetadata', query_metadata,
|
|
2558
|
+
'insertedId', NEW.id,
|
|
2559
|
+
'record', NEW
|
|
2560
|
+
)::text
|
|
2561
|
+
);
|
|
2562
|
+
|
|
2563
|
+
RETURN NEW;
|
|
2564
|
+
END;
|
|
2565
|
+
$$ LANGUAGE plpgsql;
|
|
2566
|
+
|
|
2567
|
+
CREATE OR REPLACE TRIGGER "${tableName}_insert"
|
|
2568
|
+
AFTER INSERT ON "${tableName}"
|
|
2569
|
+
FOR EACH ROW
|
|
2570
|
+
EXECUTE FUNCTION notify_${tableName}_insert();
|
|
2571
|
+
`;
|
|
2572
|
+
}
|
|
2573
|
+
const notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW."${column}"`).join(",\n");
|
|
2426
2574
|
return `
|
|
2427
2575
|
CREATE OR REPLACE FUNCTION notify_${tableName}_insert()
|
|
2428
|
-
|
|
2576
|
+
RETURNS TRIGGER AS $$
|
|
2577
|
+
DECLARE
|
|
2578
|
+
query_metadata JSON;
|
|
2429
2579
|
BEGIN
|
|
2430
|
-
|
|
2431
|
-
|
|
2580
|
+
SELECT INTO query_metadata
|
|
2581
|
+
(regexp_match(
|
|
2582
|
+
current_query(),
|
|
2583
|
+
'^--QUERY_METADATA\\(({.*})', 'n'
|
|
2584
|
+
))[1]::json;
|
|
2585
|
+
|
|
2586
|
+
PERFORM pg_notify(
|
|
2587
|
+
'insert',
|
|
2588
|
+
json_build_object(
|
|
2589
|
+
'table', '${tableName}',
|
|
2590
|
+
'queryMetadata', query_metadata,
|
|
2591
|
+
'insertedId', NEW.id,
|
|
2592
|
+
'record', json_build_object(
|
|
2593
|
+
${notifyColumnNewBuildString}
|
|
2594
|
+
)
|
|
2595
|
+
)::text
|
|
2596
|
+
);
|
|
2597
|
+
|
|
2598
|
+
RETURN NEW;
|
|
2432
2599
|
END;
|
|
2433
2600
|
$$ LANGUAGE plpgsql;
|
|
2434
2601
|
|
|
2435
|
-
CREATE TRIGGER "${tableName}_insert"
|
|
2436
|
-
|
|
2437
|
-
|
|
2602
|
+
CREATE OR REPLACE TRIGGER "${tableName}_insert"
|
|
2603
|
+
AFTER INSERT ON "${tableName}"
|
|
2604
|
+
FOR EACH ROW
|
|
2438
2605
|
EXECUTE FUNCTION notify_${tableName}_insert();
|
|
2439
|
-
|
|
2606
|
+
`;
|
|
2440
2607
|
}
|
|
2441
2608
|
schemaToPsqlType(column) {
|
|
2442
2609
|
if (column.hasAutoIncrement) return "BIGSERIAL";
|
|
@@ -2446,15 +2613,6 @@ EXECUTE FUNCTION notify_${tableName}_insert();
|
|
|
2446
2613
|
return column.type;
|
|
2447
2614
|
}
|
|
2448
2615
|
};
|
|
2449
|
-
__decorateClass([
|
|
2450
|
-
boundMethod
|
|
2451
|
-
], PsqlEngine.prototype, "createUpdateTrigger", 1);
|
|
2452
|
-
__decorateClass([
|
|
2453
|
-
boundMethod
|
|
2454
|
-
], PsqlEngine.prototype, "createDeleteTrigger", 1);
|
|
2455
|
-
__decorateClass([
|
|
2456
|
-
boundMethod
|
|
2457
|
-
], PsqlEngine.prototype, "createInsertTriggers", 1);
|
|
2458
2616
|
|
|
2459
2617
|
// src/restura/utils/TempCache.ts
|
|
2460
2618
|
import fs3 from "fs";
|