@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.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
- insertId: triggerResult.record.id,
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
- rowId: triggerResult.record.id,
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
- const query = `
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
- const findRequesterDetailsRegex = /^--QUERY_METADATA\(\{.*\}\)/;
1943
- const match = payload.query.match(findRequesterDetailsRegex);
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
- triggers.push(this.createInsertTriggers(table.name));
1965
- triggers.push(this.createUpdateTrigger(table.name));
1966
- triggers.push(this.createDeleteTrigger(table.name));
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
- RETURNS TRIGGER AS $$
2402
+ RETURNS TRIGGER AS $$
2403
+ DECLARE
2404
+ query_metadata JSON;
2397
2405
  BEGIN
2398
- PERFORM pg_notify('update', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2399
- RETURN NEW;
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
- AFTER UPDATE ON "${tableName}"
2405
- FOR EACH ROW
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
- RETURNS TRIGGER AS $$
2507
+ RETURNS TRIGGER AS $$
2508
+ DECLARE
2509
+ query_metadata JSON;
2413
2510
  BEGIN
2414
- PERFORM pg_notify('delete', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2415
- RETURN NEW;
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
- AFTER DELETE ON "${tableName}"
2421
- FOR EACH ROW
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
- RETURNS TRIGGER AS $$
2576
+ RETURNS TRIGGER AS $$
2577
+ DECLARE
2578
+ query_metadata JSON;
2429
2579
  BEGIN
2430
- PERFORM pg_notify('insert', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2431
- RETURN NEW;
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
- AFTER INSERT ON "${tableName}"
2437
- FOR EACH ROW
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";