@carbonorm/carbonnode 6.0.4 → 6.0.6

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.
Files changed (57) hide show
  1. package/dist/handlers/ExpressHandler.d.ts +3 -2
  2. package/dist/index.cjs.js +51 -3
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +51 -3
  5. package/dist/index.esm.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/__tests__/sakila-db/C6.js +1 -1
  8. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  9. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  10. package/src/__tests__/sakila-db/C6.ts +1 -1
  11. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +3 -3
  12. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  13. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  14. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  15. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +5 -5
  16. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  17. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  18. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  19. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +2 -2
  20. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  21. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  22. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  23. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +2 -2
  24. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  25. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  26. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  27. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +2 -2
  28. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  29. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  30. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  31. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +5 -5
  32. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  33. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  34. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  35. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +2 -2
  36. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  37. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  38. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  39. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +1 -1
  40. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  41. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  42. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  43. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +2 -2
  44. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  45. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  46. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  47. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +2 -2
  48. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  49. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  50. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +3 -3
  51. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  52. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  53. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  54. package/src/api/restRequest.ts +10 -0
  55. package/src/executors/HttpExecutor.ts +2 -1
  56. package/src/executors/SqlExecutor.ts +56 -16
  57. package/src/handlers/ExpressHandler.ts +4 -1
@@ -529,7 +529,8 @@ export class HttpExecutor<
529
529
 
530
530
  if (C6.GET === requestMethod && this.isRestResponse(response)) {
531
531
 
532
- const responseData = response.data;
532
+ const responseData =
533
+ response.data as DetermineResponseDataType<'GET', G['RestTableInterface']>;
533
534
 
534
535
  const pageLimit = query?.[C6.PAGINATION]?.[C6.LIMIT];
535
536
 
@@ -1,26 +1,26 @@
1
- import {DeleteQueryBuilder} from "../orm/queries/DeleteQueryBuilder";
2
- import {PostQueryBuilder} from "../orm/queries/PostQueryBuilder";
3
- import {SelectQueryBuilder} from "../orm/queries/SelectQueryBuilder";
4
- import {UpdateQueryBuilder} from "../orm/queries/UpdateQueryBuilder";
5
- import {OrmGenerics} from "../types/ormGenerics";
6
- import {C6Constants as C6C} from "../constants/C6Constants";
1
+ import { DeleteQueryBuilder } from "../orm/queries/DeleteQueryBuilder";
2
+ import { PostQueryBuilder } from "../orm/queries/PostQueryBuilder";
3
+ import { SelectQueryBuilder } from "../orm/queries/SelectQueryBuilder";
4
+ import { UpdateQueryBuilder } from "../orm/queries/UpdateQueryBuilder";
5
+ import { OrmGenerics } from "../types/ormGenerics";
6
+ import { C6Constants as C6C } from "../constants/C6Constants";
7
7
  import {
8
8
  DetermineResponseDataType,
9
9
  iRestWebsocketPayload,
10
10
  } from "../types/ormInterfaces";
11
11
  import namedPlaceholders from 'named-placeholders';
12
- import type {PoolConnection} from 'mysql2/promise';
13
- import {Buffer} from 'buffer';
14
- import {Executor} from "./Executor";
12
+ import type { PoolConnection } from 'mysql2/promise';
13
+ import { Buffer } from 'buffer';
14
+ import { Executor } from "./Executor";
15
15
  import { normalizeSingularRequest } from "../utils/normalizeSingularRequest";
16
- import {loadSqlAllowList, normalizeSql} from "../utils/sqlAllowList";
16
+ import { loadSqlAllowList, normalizeSql } from "../utils/sqlAllowList";
17
17
 
18
18
  export class SqlExecutor<
19
19
  G extends OrmGenerics
20
20
  > extends Executor<G> {
21
21
 
22
22
  async execute(): Promise<DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>> {
23
- const {TABLE_NAME} = this.config.restModel;
23
+ const { TABLE_NAME } = this.config.restModel;
24
24
  const method = this.config.requestMethod;
25
25
 
26
26
  // Normalize singular T-shaped requests into complex ORM shape (GET/PUT/DELETE)
@@ -42,6 +42,13 @@ export class SqlExecutor<
42
42
  switch (method) {
43
43
  case 'GET': {
44
44
  const rest = await this.runQuery();
45
+ if (this.config.reactBootstrap) {
46
+ this.config.reactBootstrap.updateRestfulObjectArrays({
47
+ dataOrCallback: (rest as any).rest,
48
+ stateKey: this.config.restModel.TABLE_NAME,
49
+ uniqueObjectId: this.config.restModel.PRIMARY_SHORT as any,
50
+ });
51
+ }
45
52
  return rest as DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>;
46
53
  }
47
54
 
@@ -260,7 +267,16 @@ export class SqlExecutor<
260
267
  response?: DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>
261
268
  ): Promise<void> {
262
269
  const broadcast = this.config.websocketBroadcast;
263
- if (!broadcast || this.config.requestMethod === C6C.GET) return;
270
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 broadcastWebsocketIfConfigured start", {
271
+ method: this.config.requestMethod,
272
+ hasBroadcast: Boolean(broadcast),
273
+ });
274
+ if (!broadcast || this.config.requestMethod === C6C.GET) {
275
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket broadcast skipped", {
276
+ reason: !broadcast ? "no broadcast configured" : "GET request",
277
+ });
278
+ return;
279
+ }
264
280
 
265
281
  const normalizedRequest = this.normalizeRequestPayload(this.extractRequestBody());
266
282
  const pkShorts = this.config.restModel.PRIMARY_SHORT ?? [];
@@ -269,11 +285,27 @@ export class SqlExecutor<
269
285
  let responseRest = response?.rest;
270
286
  let responsePrimaryKey = this.extractPrimaryKeyValuesFromData(responseRest);
271
287
 
288
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket request payload", {
289
+ normalizedRequest,
290
+ requestPrimaryKey: this.extractPrimaryKeyValues(),
291
+ pkShorts,
292
+ });
293
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket response payload", {
294
+ responseRest,
295
+ responsePrimaryKey,
296
+ });
297
+
272
298
  if (
273
299
  (responseRest === null || (Array.isArray(responseRest) && responseRest.length === 0))
274
300
  && this.config.requestMethod === C6C.POST
275
301
  ) {
302
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 response rest empty, attempting synthesize", {
303
+ responseRest,
304
+ });
276
305
  const insertId = (response as DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']> & { insertId?: number | string | null })?.insertId;
306
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 POST insertId lookup", {
307
+ insertId,
308
+ });
277
309
  if (insertId !== undefined && pkShorts.length === 1) {
278
310
  const synthesizedRequest = {
279
311
  ...normalizedRequest,
@@ -298,6 +330,10 @@ export class SqlExecutor<
298
330
  responsePrimaryKey = {
299
331
  [pkShorts[0]]: insertId,
300
332
  };
333
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 synthesized response payload", {
334
+ synthesized,
335
+ responsePrimaryKey,
336
+ });
301
337
  }
302
338
  }
303
339
 
@@ -313,8 +349,12 @@ export class SqlExecutor<
313
349
  },
314
350
  };
315
351
 
352
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket payload ready", payload);
353
+
316
354
  try {
355
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket broadcast dispatch start");
317
356
  await broadcast(payload);
357
+ this.config.verbose && console.log("[SQL EXECUTOR] 📣 websocket broadcast dispatch complete");
318
358
  } catch (error) {
319
359
  if (this.config.verbose) {
320
360
  console.error("[SQL EXECUTOR] websocketBroadcast failed", error);
@@ -322,7 +362,7 @@ export class SqlExecutor<
322
362
  }
323
363
  }
324
364
  async runQuery(): Promise<DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>> {
325
- const {TABLE_NAME} = this.config.restModel;
365
+ const { TABLE_NAME } = this.config.restModel;
326
366
  const method = this.config.requestMethod;
327
367
  let builder: SelectQueryBuilder<G> | UpdateQueryBuilder<G> | DeleteQueryBuilder<G> | PostQueryBuilder<G>;
328
368
 
@@ -361,15 +401,15 @@ export class SqlExecutor<
361
401
  if (method === 'GET') {
362
402
  return {
363
403
  rest: result.map(this.serialize),
364
- sql: {sql, values}
404
+ sql: { sql, values }
365
405
  } as DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>;
366
406
  } else {
367
- this.config.verbose && console.log(`[SQL EXECUTOR] ✏️ Rows affected:`, result.affectedRows);
407
+ this.config.verbose && console.log(`[SQL EXECUTOR] ✏️ Rows affected:`, result.affectedRows);
368
408
  return {
369
409
  affected: result.affectedRows as number,
370
410
  insertId: result.insertId as number,
371
411
  rest: [], // TODO - remove rest empty array from non-GET responses?
372
- sql: {sql, values}
412
+ sql: { sql, values }
373
413
  } as DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>;
374
414
  }
375
415
  });
@@ -2,7 +2,7 @@ import type {Request, Response, NextFunction} from "express";
2
2
  import type {Pool} from "mysql2/promise";
3
3
  import {C6C} from "../constants/C6Constants";
4
4
  import restRequest from "../api/restRequest";
5
- import type {iC6Object, iRestMethods} from "../types/ormInterfaces";
5
+ import type {iC6Object, iRestMethods, tWebsocketBroadcast} from "../types/ormInterfaces";
6
6
 
7
7
 
8
8
  // TODO - WE MUST make this a generic - optional, but helpful
@@ -11,10 +11,12 @@ export function ExpressHandler({
11
11
  C6,
12
12
  mysqlPool,
13
13
  sqlAllowListPath,
14
+ websocketBroadcast,
14
15
  }: {
15
16
  C6: iC6Object;
16
17
  mysqlPool: Pool;
17
18
  sqlAllowListPath?: string;
19
+ websocketBroadcast?: tWebsocketBroadcast;
18
20
  }) {
19
21
 
20
22
  return async (req: Request, res: Response, next: NextFunction) => {
@@ -101,6 +103,7 @@ export function ExpressHandler({
101
103
  C6,
102
104
  mysqlPool,
103
105
  sqlAllowListPath,
106
+ websocketBroadcast,
104
107
  requestMethod: method,
105
108
  restModel: C6.TABLES[table]
106
109
  })(payload);