@carbonorm/carbonnode 3.7.16 → 3.7.18

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.
@@ -59,5 +59,32 @@ describe('sakila-db generated C6 bindings', () => {
59
59
  await waitForRequests();
60
60
  });
61
61
  }
62
+
63
+ it('[actor] PUT fully qualified keys', async () => {
64
+ const Actor = C6.ORM.Actor;
65
+ const testId = 1;
66
+
67
+ let result = await Actor.Get({ [Actor.ACTOR_ID]: testId } as any);
68
+ let data = result?.data ?? result;
69
+ const originalLastName = data?.rest?.[0]?.last_name;
70
+
71
+ await Actor.Put({
72
+ [Actor.ACTOR_ID]: testId,
73
+ [Actor.LAST_NAME]: 'Updated',
74
+ } as any);
75
+
76
+ result = await Actor.Get({
77
+ [Actor.ACTOR_ID]: testId,
78
+ cacheResults: false,
79
+ } as any);
80
+ data = result?.data ?? result;
81
+ expect(data?.rest?.[0]?.last_name).toBe('Updated');
82
+
83
+ await Actor.Put({
84
+ [Actor.ACTOR_ID]: testId,
85
+ [Actor.LAST_NAME]: originalLastName,
86
+ } as any);
87
+ await waitForRequests();
88
+ });
62
89
  });
63
90
 
@@ -1940,7 +1940,7 @@ export type RestTableInterfaces = iActor
1940
1940
 
1941
1941
  export const C6 : iC6Object<RestTableInterfaces> = {
1942
1942
  ...C6Constants,
1943
- C6VERSION: '3.7.16',
1943
+ C6VERSION: '3.7.18',
1944
1944
  IMPORT: async (tableName: string) : Promise<iDynamicApiImport> => {
1945
1945
 
1946
1946
  tableName = tableName.toLowerCase();
@@ -71,8 +71,8 @@ export default function <
71
71
  }
72
72
  }
73
73
  }
74
- } else if (Object.values(tableDefinition.COLUMNS).includes(value)) {
75
- // Already a fully qualified column name
74
+ } else if (Object.keys(tableDefinition.COLUMNS).includes(value)) {
75
+ // Already using a fully qualified column name
76
76
  const columnValue = restfulObject[value];
77
77
  payload[value] = columnValue;
78
78
 
@@ -19,7 +19,6 @@ import {apiRequestCache, checkCache, userCustomClearCache} from "../utils/cacheM
19
19
  import {sortAndSerializeQueryObject} from "../utils/sortAndSerializeQueryObject";
20
20
  import {Executor} from "./Executor";
21
21
  import {toastOptions, toastOptionsDevs} from "variables/toastOptions";
22
- import {normalizeSingularRequest} from "../utils/normalizeSingularRequest";
23
22
 
24
23
  export class HttpExecutor<
25
24
  G extends OrmGenerics
@@ -334,9 +333,6 @@ export class HttpExecutor<
334
333
 
335
334
  }
336
335
 
337
- let addBackPK: (() => void) | undefined;
338
- let removedPrimaryKV: { key: string; value: any } | undefined;
339
-
340
336
  let apiResponse: G['RestTableInterface'][G['PrimaryKey']] | string | boolean | number | undefined;
341
337
 
342
338
  let returnGetNextPageFunction = false;
@@ -350,7 +346,9 @@ export class HttpExecutor<
350
346
 
351
347
  // todo - aggregate primary key check with condition check
352
348
  // check if PK exists in query, clone so pop does not affect the real data
353
- const primaryKey = structuredClone(TABLES[operatingTable]?.PRIMARY)?.pop()?.split('.')?.pop();
349
+ const primaryKeyList = structuredClone(TABLES[operatingTable]?.PRIMARY);
350
+ const primaryKeyFullyQualified = primaryKeyList?.pop();
351
+ const primaryKey = primaryKeyFullyQualified?.split('.')?.pop();
354
352
 
355
353
  if (needsConditionOrPrimaryCheck) {
356
354
 
@@ -374,7 +372,7 @@ export class HttpExecutor<
374
372
 
375
373
  if (undefined === query
376
374
  || null === query
377
- || false === primaryKey in query) {
375
+ || (!(primaryKey! in query) && !(primaryKeyFullyQualified && primaryKeyFullyQualified in query))) {
378
376
 
379
377
  if (true === debug && isLocal()) {
380
378
 
@@ -386,8 +384,8 @@ export class HttpExecutor<
386
384
 
387
385
  }
388
386
 
389
- if (undefined === query?.[primaryKey]
390
- || null === query?.[primaryKey]) {
387
+ const providedPrimary = query?.[primaryKey!] ?? (primaryKeyFullyQualified ? query?.[primaryKeyFullyQualified] : undefined);
388
+ if (undefined === providedPrimary || null === providedPrimary) {
391
389
 
392
390
  toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!')
393
391
 
@@ -405,27 +403,21 @@ export class HttpExecutor<
405
403
  if (POST !== requestMethod
406
404
  && undefined !== query
407
405
  && null !== query
408
- && undefined !== primaryKey
409
- && primaryKey in query) {
410
-
411
- restRequestUri += query[primaryKey] + '/'
412
-
413
- const removedPkValue = query[primaryKey];
414
- removedPrimaryKV = { key: primaryKey, value: removedPkValue };
415
-
416
- addBackPK = () => {
417
- query ??= {} as RequestQueryBody<
418
- G['RequestMethod'],
419
- G['RestTableInterface'],
420
- G['CustomAndRequiredFields'],
421
- G['RequestTableOverrides']
422
- >;
423
- query[primaryKey] = removedPkValue;
424
- }
406
+ && undefined !== primaryKey) {
407
+
408
+ const primaryVal = query[primaryKey!] ?? (primaryKeyFullyQualified ? query[primaryKeyFullyQualified] : undefined);
409
+
410
+ if (undefined !== primaryVal) {
411
+
412
+ restRequestUri += primaryVal + '/'
413
+
414
+ console.log('query', query, 'primaryKey', primaryKey)
425
415
 
426
- delete query[primaryKey]
416
+ } else {
417
+
418
+ console.log('query', query)
427
419
 
428
- console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue)
420
+ }
429
421
 
430
422
  } else {
431
423
 
@@ -473,19 +465,11 @@ export class HttpExecutor<
473
465
  withCredentials: withCredentials,
474
466
  };
475
467
 
476
- // Normalize singular request (GET/PUT/DELETE) into complex ORM shape
477
- const normalizedQuery = normalizeSingularRequest(
478
- requestMethod as any,
479
- query as any,
480
- restModel as any,
481
- removedPrimaryKV
482
- ) as typeof query;
483
-
484
468
  switch (requestMethod) {
485
469
  case GET:
486
470
  return [{
487
471
  ...baseConfig,
488
- params: normalizedQuery
472
+ params: query
489
473
  }];
490
474
 
491
475
  case POST:
@@ -498,12 +482,12 @@ export class HttpExecutor<
498
482
  return [convert(query), baseConfig];
499
483
 
500
484
  case PUT:
501
- return [convert(normalizedQuery), baseConfig];
485
+ return [convert(query), baseConfig];
502
486
 
503
487
  case DELETE:
504
488
  return [{
505
489
  ...baseConfig,
506
- data: convert(normalizedQuery)
490
+ data: convert(query)
507
491
  }];
508
492
 
509
493
  default:
@@ -523,10 +507,6 @@ export class HttpExecutor<
523
507
 
524
508
  }
525
509
 
526
- // todo - wip verify this works
527
- // we had removed the value from the request to add to the URI.
528
- addBackPK?.(); // adding back so post-processing methods work
529
-
530
510
  // returning the promise with this then is important for tests. todo - we could make that optional.
531
511
  // https://rapidapi.com/guides/axios-async-await
532
512
  return axiosActiveRequest.then(async (response: AxiosResponse<ResponseDataType, any>): Promise<AxiosResponse<ResponseDataType, any>> => {
@@ -35,30 +35,17 @@ export function ExpressHandler({C6, mysqlPool}: { C6: iC6Object, mysqlPool: Pool
35
35
  }
36
36
 
37
37
  const primaryKeyName = primaryKeys[0];
38
- const primaryKeyShort = primaryKeyName.split('.')[1];
39
38
 
40
- if (!(payload[C6C.WHERE]?.[primaryKeyName] ?? undefined)
41
- && !(payload[C6C.WHERE]?.[primaryKeyShort] ?? undefined)) {
42
- // 👇 Call restRequest for the resolved method
43
- switch (method) {
44
- case 'GET':
45
- if (primary) {
46
- payload[C6C.WHERE][primaryKeyName] = primary;
47
- }
48
- break;
49
- case 'PUT':
50
- case 'DELETE':
51
- if (primary) {
52
- payload[C6C.WHERE][primaryKeyName] = primary;
53
- } else {
54
- res.status(400).json({error: `Invalid request: ${method} requires a primary key (${primaryKeyName}).`});
55
- }
56
- break;
57
- case 'POST':
58
- break;
59
- default:
60
- res.status(405).json({error: `Method ${method} not allowed`});
61
- return;
39
+ // If a primary key was provided in the URL, merge it into the payload.
40
+ // Support both complex requests using WHERE and singular requests
41
+ // where the primary key lives at the root of the payload.
42
+ if (primary) {
43
+ if (payload[C6C.WHERE]) {
44
+ payload[C6C.WHERE][primaryKeyName] =
45
+ payload[C6C.WHERE][primaryKeyName] ?? primary;
46
+ } else {
47
+ (payload as any)[primaryKeyName] =
48
+ (payload as any)[primaryKeyName] ?? primary;
62
49
  }
63
50
  }
64
51
 
@@ -60,7 +60,9 @@ export function normalizeSingularRequest<
60
60
  if (value === undefined) {
61
61
  // 2) fully-qualified key matching this short key (from PRIMARY list or by concatenation)
62
62
  const fqCandidate = `${restModel.TABLE_NAME}.${pkShort}`;
63
- const fqKey = pkFulls.find(fq => fq === fqCandidate || fq.endsWith(`.${pkShort}`)) ?? fqCandidate;
63
+ const fqKey = pkFulls.find(
64
+ fq => fq === fqCandidate || fq.endsWith(`.${pkShort}`)
65
+ ) ?? fqCandidate;
64
66
  value = requestObj[fqKey];
65
67
  }
66
68
  if (value === undefined && removedPrimary) {
@@ -93,9 +95,18 @@ export function normalizeSingularRequest<
93
95
  ...rest
94
96
  } = request as any;
95
97
 
98
+ // Map short primary keys to fully-qualified column names
99
+ const shortToFull: Record<string, string> = {};
100
+ for (const [full, short] of Object.entries(restModel.COLUMNS || {})) {
101
+ shortToFull[short as string] = full;
102
+ }
103
+ const pkFullValues = Object.fromEntries(
104
+ Object.entries(pkValues).map(([k, v]) => [shortToFull[k] ?? k, v])
105
+ );
106
+
96
107
  if (requestMethod === C6C.GET) {
97
108
  const normalized: any = {
98
- WHERE: { ...pkValues },
109
+ WHERE: { ...pkFullValues },
99
110
  };
100
111
  // Preserve pagination if any was added previously
101
112
  if ((request as any)[C6C.PAGINATION]) {
@@ -115,7 +126,7 @@ export function normalizeSingularRequest<
115
126
  if (requestMethod === C6C.DELETE) {
116
127
  const normalized: any = {
117
128
  [C6C.DELETE]: true,
118
- WHERE: { ...pkValues },
129
+ WHERE: { ...pkFullValues },
119
130
  };
120
131
  return {
121
132
  ...normalized,
@@ -143,7 +154,7 @@ export function normalizeSingularRequest<
143
154
 
144
155
  const normalized: any = {
145
156
  [C6C.UPDATE]: updateBody,
146
- WHERE: { ...pkValues },
157
+ WHERE: { ...pkFullValues },
147
158
  };
148
159
 
149
160
  return {