@restura/core 0.1.0-alpha.34 → 0.1.0-alpha.36

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(),
@@ -1939,16 +1948,8 @@ var PsqlEngine = class extends SqlEngine {
1939
1948
  });
1940
1949
  }
1941
1950
  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);
1951
+ if (payload.queryMetadata && payload.queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId) {
1952
+ await eventManager_default.fireActionFromDbTrigger({ queryMetadata: payload.queryMetadata, mutationType }, payload);
1952
1953
  }
1953
1954
  }
1954
1955
  async createDatabaseFromSchema(schema, connection) {
@@ -1961,9 +1962,11 @@ var PsqlEngine = class extends SqlEngine {
1961
1962
  const indexes = [];
1962
1963
  const triggers = [];
1963
1964
  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));
1965
+ if (table.notify) {
1966
+ triggers.push(this.createInsertTriggers(table.name, table.notify));
1967
+ triggers.push(this.createUpdateTrigger(table.name, table.notify));
1968
+ triggers.push(this.createDeleteTrigger(table.name, table.notify));
1969
+ }
1967
1970
  let sql = `CREATE TABLE "${table.name}"
1968
1971
  ( `;
1969
1972
  const tableColumns = [];
@@ -2390,53 +2393,216 @@ DELETE FROM "${routeData.table}" ${joinStatement} ${whereClause}`;
2390
2393
  }
2391
2394
  return whereClause;
2392
2395
  }
2393
- createUpdateTrigger(tableName) {
2394
- return `
2396
+ createUpdateTrigger(tableName, notify) {
2397
+ if (!notify) return "";
2398
+ if (notify === "ALL") {
2399
+ return `
2395
2400
  CREATE OR REPLACE FUNCTION notify_${tableName}_update()
2396
- RETURNS TRIGGER AS $$
2401
+ RETURNS TRIGGER AS $$
2402
+ DECLARE
2403
+ query_metadata JSON;
2397
2404
  BEGIN
2398
- PERFORM pg_notify('update', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2399
- RETURN NEW;
2405
+ SELECT INTO query_metadata
2406
+ (regexp_match(
2407
+ current_query(),
2408
+ '^--QUERY_METADATA\\(({.*})', 'n'
2409
+ ))[1]::json;
2410
+
2411
+ PERFORM pg_notify(
2412
+ 'update',
2413
+ json_build_object(
2414
+ 'table', '${tableName}',
2415
+ 'queryMetadata', query_metadata,
2416
+ 'changedId', NEW.id,
2417
+ 'record', NEW,
2418
+ 'previousRecord', OLD
2419
+ )::text
2420
+ );
2421
+ RETURN NEW;
2400
2422
  END;
2401
2423
  $$ LANGUAGE plpgsql;
2402
2424
 
2403
2425
  CREATE OR REPLACE TRIGGER ${tableName}_update
2404
- AFTER UPDATE ON "${tableName}"
2405
- FOR EACH ROW
2426
+ AFTER UPDATE ON "${tableName}"
2427
+ FOR EACH ROW
2428
+ EXECUTE FUNCTION notify_${tableName}_update();
2429
+ `;
2430
+ }
2431
+ const notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW."${column}"`).join(",\n");
2432
+ const notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD."${column}"`).join(",\n");
2433
+ return `
2434
+ CREATE OR REPLACE FUNCTION notify_${tableName}_update()
2435
+ RETURNS TRIGGER AS $$
2436
+ DECLARE
2437
+ query_metadata JSON;
2438
+ BEGIN
2439
+ SELECT INTO query_metadata
2440
+ (regexp_match(
2441
+ current_query(),
2442
+ '^--QUERY_METADATA\\(({.*})', 'n'
2443
+ ))[1]::json;
2444
+
2445
+ PERFORM pg_notify(
2446
+ 'update',
2447
+ json_build_object(
2448
+ 'table', '${tableName}',
2449
+ 'queryMetadata', query_metadata,
2450
+ 'changedId', NEW.id,
2451
+ 'record', json_build_object(
2452
+ ${notifyColumnNewBuildString}
2453
+ ),
2454
+ 'previousRecord', json_build_object(
2455
+ ${notifyColumnOldBuildString}
2456
+ )
2457
+ )::text
2458
+ );
2459
+ RETURN NEW;
2460
+ END;
2461
+ $$ LANGUAGE plpgsql;
2462
+
2463
+ CREATE OR REPLACE TRIGGER ${tableName}_update
2464
+ AFTER UPDATE ON "${tableName}"
2465
+ FOR EACH ROW
2406
2466
  EXECUTE FUNCTION notify_${tableName}_update();
2407
2467
  `;
2408
2468
  }
2409
- createDeleteTrigger(tableName) {
2469
+ createDeleteTrigger(tableName, notify) {
2470
+ if (!notify) return "";
2471
+ if (notify === "ALL") {
2472
+ return `
2473
+ CREATE OR REPLACE FUNCTION notify_${tableName}_delete()
2474
+ RETURNS TRIGGER AS $$
2475
+ DECLARE
2476
+ query_metadata JSON;
2477
+ BEGIN
2478
+ SELECT INTO query_metadata
2479
+ (regexp_match(
2480
+ current_query(),
2481
+ '^--QUERY_METADATA\\(({.*})', 'n'
2482
+ ))[1]::json;
2483
+
2484
+ PERFORM pg_notify(
2485
+ 'delete',
2486
+ json_build_object(
2487
+ 'table', '${tableName}',
2488
+ 'queryMetadata', query_metadata,
2489
+ 'deletedId', OLD.id,
2490
+ 'previousRecord', OLD
2491
+ )::text
2492
+ );
2493
+ RETURN NEW;
2494
+ END;
2495
+ $$ LANGUAGE plpgsql;
2496
+
2497
+ CREATE OR REPLACE TRIGGER "${tableName}_delete"
2498
+ AFTER DELETE ON "${tableName}"
2499
+ FOR EACH ROW
2500
+ EXECUTE FUNCTION notify_${tableName}_delete();
2501
+ `;
2502
+ }
2503
+ const notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD."${column}"`).join(",\n");
2410
2504
  return `
2411
2505
  CREATE OR REPLACE FUNCTION notify_${tableName}_delete()
2412
- RETURNS TRIGGER AS $$
2506
+ RETURNS TRIGGER AS $$
2507
+ DECLARE
2508
+ query_metadata JSON;
2413
2509
  BEGIN
2414
- PERFORM pg_notify('delete', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2415
- RETURN NEW;
2510
+ SELECT INTO query_metadata
2511
+ (regexp_match(
2512
+ current_query(),
2513
+ '^--QUERY_METADATA\\(({.*})', 'n'
2514
+ ))[1]::json;
2515
+
2516
+ PERFORM pg_notify(
2517
+ 'delete',
2518
+ json_build_object(
2519
+ 'table', '${tableName}',
2520
+ 'queryMetadata', query_metadata,
2521
+ 'deletedId', OLD.id,
2522
+ 'previousRecord', json_build_object(
2523
+ ${notifyColumnOldBuildString}
2524
+ )
2525
+ )::text
2526
+ );
2527
+ RETURN NEW;
2416
2528
  END;
2417
2529
  $$ LANGUAGE plpgsql;
2418
2530
 
2419
2531
  CREATE OR REPLACE TRIGGER "${tableName}_delete"
2420
- AFTER DELETE ON "${tableName}"
2421
- FOR EACH ROW
2532
+ AFTER DELETE ON "${tableName}"
2533
+ FOR EACH ROW
2422
2534
  EXECUTE FUNCTION notify_${tableName}_delete();
2423
2535
  `;
2424
2536
  }
2425
- createInsertTriggers(tableName) {
2537
+ createInsertTriggers(tableName, notify) {
2538
+ if (!notify) return "";
2539
+ if (notify === "ALL") {
2540
+ return `
2541
+ CREATE OR REPLACE FUNCTION notify_${tableName}_insert()
2542
+ RETURNS TRIGGER AS $$
2543
+ DECLARE
2544
+ query_metadata JSON;
2545
+ BEGIN
2546
+ SELECT INTO query_metadata
2547
+ (regexp_match(
2548
+ current_query(),
2549
+ '^--QUERY_METADATA\\(({.*})', 'n'
2550
+ ))[1]::json;
2551
+
2552
+ PERFORM pg_notify(
2553
+ 'insert',
2554
+ json_build_object(
2555
+ 'table', '${tableName}',
2556
+ 'queryMetadata', query_metadata,
2557
+ 'insertedId', NEW.id,
2558
+ 'record', NEW
2559
+ )::text
2560
+ );
2561
+
2562
+ RETURN NEW;
2563
+ END;
2564
+ $$ LANGUAGE plpgsql;
2565
+
2566
+ CREATE OR REPLACE TRIGGER "${tableName}_insert"
2567
+ AFTER INSERT ON "${tableName}"
2568
+ FOR EACH ROW
2569
+ EXECUTE FUNCTION notify_${tableName}_insert();
2570
+ `;
2571
+ }
2572
+ const notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW."${column}"`).join(",\n");
2426
2573
  return `
2427
2574
  CREATE OR REPLACE FUNCTION notify_${tableName}_insert()
2428
- RETURNS TRIGGER AS $$
2575
+ RETURNS TRIGGER AS $$
2576
+ DECLARE
2577
+ query_metadata JSON;
2429
2578
  BEGIN
2430
- PERFORM pg_notify('insert', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2431
- RETURN NEW;
2579
+ SELECT INTO query_metadata
2580
+ (regexp_match(
2581
+ current_query(),
2582
+ '^--QUERY_METADATA\\(({.*})', 'n'
2583
+ ))[1]::json;
2584
+
2585
+ PERFORM pg_notify(
2586
+ 'insert',
2587
+ json_build_object(
2588
+ 'table', '${tableName}',
2589
+ 'queryMetadata', query_metadata,
2590
+ 'insertedId', NEW.id,
2591
+ 'record', json_build_object(
2592
+ ${notifyColumnNewBuildString}
2593
+ )
2594
+ )::text
2595
+ );
2596
+
2597
+ RETURN NEW;
2432
2598
  END;
2433
2599
  $$ LANGUAGE plpgsql;
2434
2600
 
2435
- CREATE TRIGGER "${tableName}_insert"
2436
- AFTER INSERT ON "${tableName}"
2437
- FOR EACH ROW
2601
+ CREATE OR REPLACE TRIGGER "${tableName}_insert"
2602
+ AFTER INSERT ON "${tableName}"
2603
+ FOR EACH ROW
2438
2604
  EXECUTE FUNCTION notify_${tableName}_insert();
2439
- `;
2605
+ `;
2440
2606
  }
2441
2607
  schemaToPsqlType(column) {
2442
2608
  if (column.hasAutoIncrement) return "BIGSERIAL";
@@ -2446,15 +2612,6 @@ EXECUTE FUNCTION notify_${tableName}_insert();
2446
2612
  return column.type;
2447
2613
  }
2448
2614
  };
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
2615
 
2459
2616
  // src/restura/utils/TempCache.ts
2460
2617
  import fs3 from "fs";
@@ -2870,6 +3027,7 @@ export {
2870
3027
  SQL,
2871
3028
  escapeColumnName,
2872
3029
  eventManager_default as eventManager,
3030
+ filterPsqlParser_default as filterPsqlParser,
2873
3031
  insertObjectQuery,
2874
3032
  isValueNumber2 as isValueNumber,
2875
3033
  logger,