@cap-js-community/common 0.1.6 → 0.2.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js-community/common",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "CAP Node.js Community Common",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "engines": {
@@ -44,26 +44,26 @@
44
44
  "audit": "npm audit --only=prod"
45
45
  },
46
46
  "dependencies": {
47
- "@cap-js/sqlite": "^1.11.0",
48
- "commander": "^13.1.0",
49
- "redis": "^4.7.0",
47
+ "@cap-js/sqlite": "^2.0.1",
48
+ "commander": "^14.0.0",
49
+ "redis": "^4.7.1",
50
50
  "verror": "^1.10.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@cap-js-community/common": "./",
54
54
  "@cap-js/cds-test": "^0.3.0",
55
- "@sap/cds": "^8.9.3",
56
- "@sap/cds-common-content": "^2.1.0",
57
- "@sap/cds-dk": "^8.9.3",
58
- "eslint": "9.26.0",
59
- "eslint-config-prettier": "10.1.3",
60
- "eslint-plugin-jest": "28.11.0",
61
- "eslint-plugin-n": "^17.17.0",
55
+ "@sap/cds": "^9.0.2",
56
+ "@sap/cds-common-content": "^3.0.1",
57
+ "@sap/cds-dk": "^9.0.4",
58
+ "eslint": "9.28.0",
59
+ "eslint-config-prettier": "10.1.5",
60
+ "eslint-plugin-jest": "28.12.0",
61
+ "eslint-plugin-n": "^17.19.0",
62
62
  "jest": "29.7.0",
63
63
  "jest-html-reporters": "3.1.7",
64
64
  "jest-junit": "16.0.0",
65
65
  "prettier": "3.5.3",
66
- "shelljs": "^0.9.2"
66
+ "shelljs": "^0.10.0"
67
67
  },
68
68
  "cds": {
69
69
  "requires": {
@@ -8,7 +8,7 @@ const crypto = require("crypto");
8
8
  const COMPONENT_NAME = "migrationCheck";
9
9
  const STRING_DEFAULT_LENGTH = 5000;
10
10
 
11
- const Checks = [releasedEntityCheck, newEntityCheck, uniqueIndexCheck];
11
+ const Checks = [releasedEntityCheck, newEntityCheck, uniqueIndexCheck, journalModeCheck];
12
12
  const Messages = {
13
13
  ReleasedEntityCannotBeRemoved: "A released entity cannot be removed",
14
14
  ReleasedEntityDraftEnablementCannotBeChanged: "The draft enablement state of a released entity cannot be changed",
@@ -25,6 +25,8 @@ const Messages = {
25
25
  ReleasedElementCardinalityCannotBeChanged: "The cardinality of a released element cannot be changed",
26
26
  ReleasedElementOnConditionCannotBeChanged: "The ON condition of a released element cannot be changed",
27
27
  ReleasedElementKeysConditionCannotBeChanged: "The keys condition of a released element cannot be changed",
28
+ ReleasedEntityJournalModeAndEntityChangeIsNotAllowed:
29
+ "Enabling journal mode and changing entity in same cycle is not allowed",
28
30
  ReleasedEntityIndexChangeIsNotAllowed: "Changes to the index of a released entity are not allowed",
29
31
  ReleasedEntityIndexChangeIsNotWhitelisted: "Changes to the index of a released entity must be whitelisted",
30
32
  ReleasedElementTypeExtensionIsNotWhitelisted: "Extending the type of a released element requires whitelisting",
@@ -310,200 +312,255 @@ class MigrationCheck {
310
312
 
311
313
  function releasedEntityCheck(csnBuild, csnProd, whitelist, options) {
312
314
  const messages = [];
313
- visitPersistenceEntities(csnProd, (definitionProd) => {
314
- let lookupName = definitionProd.name;
315
- if (lookupName.startsWith("cds.xt.") && !options.checkMtx) {
316
- return;
317
- }
318
- const definitionBuild = csnBuild.definitions[lookupName];
319
- if (!definitionBuild) {
320
- report(messages, MessagesCodes.ReleasedEntityCannotBeRemoved, definitionProd.name);
321
- return;
322
- }
323
- if (definitionProd["@odata.draft.enabled"] !== definitionBuild["@odata.draft.enabled"]) {
324
- report(messages, MessagesCodes.ReleasedEntityDraftEnablementCannotBeChanged, definitionProd.name);
325
- }
326
- const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionProd.name];
327
- Object.keys(definitionProd.elements || {}).forEach((elementProdName) => {
328
- const elementProd = definitionProd.elements[elementProdName];
329
- const elementBuild = definitionBuild.elements[elementProdName];
330
- const elementWhitelist =
331
- definitionWhitelist && definitionWhitelist.elements && definitionWhitelist.elements[elementProdName];
332
- if (elementBuild) {
333
- if (["cds.Association", "cds.Composition"].includes(elementProd.type)) {
334
- if (!((elementProd.on && elementBuild.on) || (elementProd.keys && elementBuild.keys))) {
335
- report(
336
- messages,
337
- MessagesCodes.ReleasedElementManagedUnmanagedCannotBeChanged,
338
- definitionProd.name,
339
- elementProdName,
340
- );
341
- return;
342
- }
343
- }
315
+ visitPersistenceEntities(
316
+ csnProd,
317
+ (definitionProd) => {
318
+ let lookupName = definitionProd.name;
319
+ if (lookupName.startsWith("cds.xt.") && !options.checkMtx) {
320
+ return;
321
+ }
322
+ const definitionBuild = csnBuild.definitions[lookupName];
323
+ if (!definitionBuild) {
324
+ report(messages, MessagesCodes.ReleasedEntityCannotBeRemoved, definitionProd.name);
325
+ return;
344
326
  }
345
- if (elementProd.on) {
346
- return; // Skip unmanaged association / composition
327
+ if (definitionProd["@odata.draft.enabled"] !== definitionBuild["@odata.draft.enabled"]) {
328
+ report(messages, MessagesCodes.ReleasedEntityDraftEnablementCannotBeChanged, definitionProd.name);
347
329
  }
348
- if (!elementBuild) {
349
- if (!elementProd.virtual) {
350
- report(messages, MessagesCodes.ReleasedElementCannotBeRemoved, definitionProd.name, elementProdName);
330
+ const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionProd.name];
331
+ Object.keys(definitionProd.elements || {}).forEach((elementProdName) => {
332
+ const elementProd = definitionProd.elements[elementProdName];
333
+ const elementBuild = definitionBuild.elements[elementProdName];
334
+ const elementWhitelist =
335
+ definitionWhitelist && definitionWhitelist.elements && definitionWhitelist.elements[elementProdName];
336
+ if (elementBuild) {
337
+ if (["cds.Association", "cds.Composition"].includes(elementProd.type)) {
338
+ if (!((elementProd.on && elementBuild.on) || (elementProd.keys && elementBuild.keys))) {
339
+ report(
340
+ messages,
341
+ MessagesCodes.ReleasedElementManagedUnmanagedCannotBeChanged,
342
+ definitionProd.name,
343
+ elementProdName,
344
+ );
345
+ }
346
+ }
351
347
  }
352
- } else if (elementProd.key !== elementBuild.key) {
353
- report(messages, MessagesCodes.ReleasedElementKeyCannotBeChanged, definitionProd.name, elementProdName);
354
- } else if (elementProd.virtual !== elementBuild.virtual) {
355
- report(messages, MessagesCodes.ReleasedElementVirtualCannotBeChanged, definitionProd.name, elementProdName);
356
- } else if (elementProd.localized && !elementBuild.localized) {
357
- report(
358
- messages,
359
- MessagesCodes.ReleasedElementLocalizationCannotBeChanged,
360
- definitionProd.name,
361
- elementProdName,
362
- );
363
- } else if (!elementProd.notNull && elementBuild.notNull) {
364
- report(messages, MessagesCodes.ReleasedElementNullableCannotBeChanged, definitionProd.name, elementProdName);
365
- } else if (normalizeType(csnProd, elementProd.type) !== normalizeType(csnBuild, elementBuild.type)) {
366
- report(messages, MessagesCodes.ReleasedElementTypeCannotBeChanged, definitionProd.name, elementProdName);
367
- } else if ((elementProd.length || STRING_DEFAULT_LENGTH) > (elementBuild.length || STRING_DEFAULT_LENGTH)) {
368
- report(messages, MessagesCodes.ReleasedElementTypeCannotBeShortened, definitionProd.name, elementProdName);
369
- } else if ((elementProd.length || STRING_DEFAULT_LENGTH) < (elementBuild.length || STRING_DEFAULT_LENGTH)) {
370
- if (!elementWhitelist && options.whitelist) {
371
- report(
372
- messages,
373
- MessagesCodes.ReleasedElementTypeExtensionIsNotWhitelisted,
374
- definitionProd.name,
375
- elementProdName,
376
- );
348
+ if (elementProd.on) {
349
+ return; // Skip unmanaged association / composition
377
350
  }
378
- } else if (elementProd.scale > elementBuild.scale || elementProd.precision > elementBuild.precision) {
379
- report(
380
- messages,
381
- MessagesCodes.ReleasedElementScalePrecisionCannotBeLower,
382
- definitionProd.name,
383
- elementProdName,
384
- );
385
- } else if (elementProd.scale < elementBuild.scale || elementProd.precision < elementBuild.precision) {
386
- if (!elementWhitelist && options.whitelist) {
351
+ if (!elementBuild) {
352
+ if (!elementProd.virtual) {
353
+ report(messages, MessagesCodes.ReleasedElementCannotBeRemoved, definitionProd.name, elementProdName);
354
+ }
355
+ } else if (elementProd.key !== elementBuild.key) {
356
+ report(messages, MessagesCodes.ReleasedElementKeyCannotBeChanged, definitionProd.name, elementProdName);
357
+ } else if (elementProd.virtual !== elementBuild.virtual) {
358
+ report(messages, MessagesCodes.ReleasedElementVirtualCannotBeChanged, definitionProd.name, elementProdName);
359
+ } else if (elementProd.localized && !elementBuild.localized) {
387
360
  report(
388
361
  messages,
389
- MessagesCodes.ReleasedElementScalePrecisionExtensionIsNotWhitelisted,
362
+ MessagesCodes.ReleasedElementLocalizationCannotBeChanged,
390
363
  definitionProd.name,
391
364
  elementProdName,
392
365
  );
393
- }
394
- } else if (elementProd.target !== elementBuild.target) {
395
- if (
396
- isPersistenceEntity(csnProd, elementProd.target) ||
397
- isPersistenceEntity(csnBuild, elementBuild.target) ||
398
- JSON.stringify(entityKeyInfo(csnProd, elementProd.target)) !==
399
- JSON.stringify(entityKeyInfo(csnBuild, elementBuild.target))
400
- ) {
401
- report(messages, MessagesCodes.ReleasedElementTargetCannotBeChanged, definitionProd.name, elementProdName);
402
- }
403
- } else if (
404
- (elementProd.cardinality && elementProd.cardinality.max) !==
405
- (elementBuild.cardinality && elementBuild.cardinality.max)
406
- ) {
407
- report(messages, MessagesCodes.ReleasedElementCardinalityCannotBeChanged, definitionProd.name, elementProdName);
408
- } else if (JSON.stringify(elementProd.on) !== JSON.stringify(elementBuild.on)) {
409
- if (isPersistenceEntity(csnProd, elementProd.target) || isPersistenceEntity(csnBuild, elementBuild.target)) {
366
+ } else if (!elementProd.notNull && elementBuild.notNull) {
367
+ report(messages, MessagesCodes.ReleasedElementNullableCannotBeChanged, definitionProd.name, elementProdName);
368
+ } else if (normalizeType(csnProd, elementProd.type) !== normalizeType(csnBuild, elementBuild.type)) {
369
+ report(messages, MessagesCodes.ReleasedElementTypeCannotBeChanged, definitionProd.name, elementProdName);
370
+ } else if ((elementProd.length || STRING_DEFAULT_LENGTH) > (elementBuild.length || STRING_DEFAULT_LENGTH)) {
371
+ report(messages, MessagesCodes.ReleasedElementTypeCannotBeShortened, definitionProd.name, elementProdName);
372
+ } else if ((elementProd.length || STRING_DEFAULT_LENGTH) < (elementBuild.length || STRING_DEFAULT_LENGTH)) {
373
+ if (!elementWhitelist && options.whitelist) {
374
+ report(
375
+ messages,
376
+ MessagesCodes.ReleasedElementTypeExtensionIsNotWhitelisted,
377
+ definitionProd.name,
378
+ elementProdName,
379
+ );
380
+ }
381
+ } else if (elementProd.scale > elementBuild.scale || elementProd.precision > elementBuild.precision) {
410
382
  report(
411
383
  messages,
412
- MessagesCodes.ReleasedElementOnConditionCannotBeChanged,
384
+ MessagesCodes.ReleasedElementScalePrecisionCannotBeLower,
413
385
  definitionProd.name,
414
386
  elementProdName,
415
387
  );
416
- }
417
- } else if (JSON.stringify(elementProd.keys) !== JSON.stringify(elementBuild.keys)) {
418
- if (isPersistenceEntity(csnProd, elementProd.target) || isPersistenceEntity(csnBuild, elementBuild.target)) {
388
+ } else if (elementProd.scale < elementBuild.scale || elementProd.precision < elementBuild.precision) {
389
+ if (!elementWhitelist && options.whitelist) {
390
+ report(
391
+ messages,
392
+ MessagesCodes.ReleasedElementScalePrecisionExtensionIsNotWhitelisted,
393
+ definitionProd.name,
394
+ elementProdName,
395
+ );
396
+ }
397
+ } else if (elementProd.target !== elementBuild.target) {
398
+ if (
399
+ isPersistenceEntity(csnProd, elementProd.target) ||
400
+ isPersistenceEntity(csnBuild, elementBuild.target) ||
401
+ JSON.stringify(entityKeyInfo(csnProd, elementProd.target)) !==
402
+ JSON.stringify(entityKeyInfo(csnBuild, elementBuild.target))
403
+ ) {
404
+ report(messages, MessagesCodes.ReleasedElementTargetCannotBeChanged, definitionProd.name, elementProdName);
405
+ }
406
+ } else if (
407
+ (elementProd.cardinality && elementProd.cardinality.max) !==
408
+ (elementBuild.cardinality && elementBuild.cardinality.max)
409
+ ) {
419
410
  report(
420
411
  messages,
421
- MessagesCodes.ReleasedElementKeysConditionCannotBeChanged,
412
+ MessagesCodes.ReleasedElementCardinalityCannotBeChanged,
422
413
  definitionProd.name,
423
414
  elementProdName,
424
415
  );
416
+ } else if (JSON.stringify(elementProd.on) !== JSON.stringify(elementBuild.on)) {
417
+ if (isPersistenceEntity(csnProd, elementProd.target) || isPersistenceEntity(csnBuild, elementBuild.target)) {
418
+ report(
419
+ messages,
420
+ MessagesCodes.ReleasedElementOnConditionCannotBeChanged,
421
+ definitionProd.name,
422
+ elementProdName,
423
+ );
424
+ }
425
+ } else if (JSON.stringify(elementProd.keys) !== JSON.stringify(elementBuild.keys)) {
426
+ if (isPersistenceEntity(csnProd, elementProd.target) || isPersistenceEntity(csnBuild, elementBuild.target)) {
427
+ report(
428
+ messages,
429
+ MessagesCodes.ReleasedElementKeysConditionCannotBeChanged,
430
+ definitionProd.name,
431
+ elementProdName,
432
+ );
433
+ }
425
434
  }
426
- }
427
- });
428
- });
435
+ });
436
+ },
437
+ options.filter,
438
+ );
429
439
  return messages;
430
440
  }
431
441
 
432
442
  function newEntityCheck(csnBuild, csnProd, whitelist, options) {
433
443
  const messages = [];
434
- visitPersistenceEntities(csnBuild, (definitionBuild, { draft } = {}) => {
435
- let lookupName = definitionBuild.name;
436
- const definitionProd = csnProd.definitions[lookupName];
437
- const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionBuild.name];
438
- if (!definitionProd && !definitionWhitelist && options.whitelist) {
439
- report(messages, MessagesCodes.NewEntityIsNotWhitelisted, definitionBuild.name);
440
- return;
441
- }
442
- if (definitionProd) {
443
- Object.keys(definitionBuild.elements || {}).forEach((elementBuildName) => {
444
- const elementBuild = definitionBuild.elements[elementBuildName];
445
- if (elementBuild.virtual) {
446
- return;
447
- }
448
- const elementProd = definitionProd.elements[elementBuildName];
449
- const elementWhitelist =
450
- definitionWhitelist && definitionWhitelist.elements && definitionWhitelist.elements[elementBuildName];
451
- if (!elementProd) {
452
- if (!elementWhitelist && options.whitelist) {
453
- report(messages, MessagesCodes.NewEntityElementIsNotWhitelisted, definitionBuild.name, elementBuildName);
444
+ visitPersistenceEntities(
445
+ csnBuild,
446
+ (definitionBuild, { draft } = {}) => {
447
+ let lookupName = definitionBuild.name;
448
+ const definitionProd = csnProd.definitions[lookupName];
449
+ const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionBuild.name];
450
+ if (!definitionProd && !definitionWhitelist && options.whitelist) {
451
+ report(messages, MessagesCodes.NewEntityIsNotWhitelisted, definitionBuild.name);
452
+ return;
453
+ }
454
+ if (definitionProd) {
455
+ Object.keys(definitionBuild.elements || {}).forEach((elementBuildName) => {
456
+ const elementBuild = definitionBuild.elements[elementBuildName];
457
+ if (elementBuild.virtual) {
458
+ return;
454
459
  }
455
- if (
456
- !draft &&
457
- elementBuild.notNull &&
458
- (elementBuild.default === undefined || elementBuild.default?.val === null)
459
- ) {
460
- report(messages, MessagesCodes.NewEntityElementNotNullableDefault, definitionBuild.name, elementBuildName);
460
+ const elementProd = definitionProd.elements[elementBuildName];
461
+ const elementWhitelist =
462
+ definitionWhitelist && definitionWhitelist.elements && definitionWhitelist.elements[elementBuildName];
463
+ if (!elementProd) {
464
+ if (!elementWhitelist && options.whitelist) {
465
+ report(messages, MessagesCodes.NewEntityElementIsNotWhitelisted, definitionBuild.name, elementBuildName);
466
+ }
467
+ if (
468
+ !draft &&
469
+ elementBuild.notNull &&
470
+ (elementBuild.default === undefined || elementBuild.default?.val === null)
471
+ ) {
472
+ report(
473
+ messages,
474
+ MessagesCodes.NewEntityElementNotNullableDefault,
475
+ definitionBuild.name,
476
+ elementBuildName,
477
+ );
478
+ }
461
479
  }
462
- }
463
- });
464
- }
465
- });
480
+ });
481
+ }
482
+ },
483
+ options.filter,
484
+ );
466
485
  return messages;
467
486
  }
468
487
 
469
488
  function uniqueIndexCheck(csnBuild, csnProd, whitelist, options) {
470
489
  const messages = [];
471
- visitPersistenceEntities(csnBuild, (definitionBuild) => {
472
- const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionBuild.name];
473
- const definitionProd = csnProd.definitions[definitionBuild.name];
474
- if (definitionProd) {
475
- Object.keys(definitionBuild).forEach((key) => {
476
- if (key.startsWith("@assert.unique.")) {
477
- const uniqueIndexAnnotationBuild = definitionBuild[key];
478
- const uniqueIndexAnnotationProd = definitionProd[key];
479
- if (uniqueIndexAnnotationBuild && !uniqueIndexAnnotationProd && !definitionWhitelist && options.whitelist) {
480
- report(messages, MessagesCodes.NewEntityIndexIsNotWhitelisted, definitionBuild.name);
481
- } else if (uniqueIndexAnnotationBuild && uniqueIndexAnnotationProd) {
482
- const checkProd = uniqueIndexAnnotationProd.every((indexPartProd) => {
483
- return uniqueIndexAnnotationBuild.find((indexPartBuild) => {
484
- return (indexPartProd["="] || indexPartProd) === (indexPartBuild["="] || indexPartBuild);
490
+ visitPersistenceEntities(
491
+ csnBuild,
492
+ (definitionBuild) => {
493
+ const definitionWhitelist = whitelist.definitions && whitelist.definitions[definitionBuild.name];
494
+ const definitionProd = csnProd.definitions[definitionBuild.name];
495
+ if (definitionProd) {
496
+ Object.keys(definitionBuild).forEach((key) => {
497
+ if (key.startsWith("@assert.unique.")) {
498
+ const uniqueIndexAnnotationBuild = definitionBuild[key];
499
+ const uniqueIndexAnnotationProd = definitionProd[key];
500
+ if (uniqueIndexAnnotationBuild && !uniqueIndexAnnotationProd && !definitionWhitelist && options.whitelist) {
501
+ report(messages, MessagesCodes.NewEntityIndexIsNotWhitelisted, definitionBuild.name);
502
+ } else if (uniqueIndexAnnotationBuild && uniqueIndexAnnotationProd) {
503
+ const checkProd = uniqueIndexAnnotationProd.every((indexPartProd) => {
504
+ return uniqueIndexAnnotationBuild.find((indexPartBuild) => {
505
+ return (indexPartProd["="] || indexPartProd) === (indexPartBuild["="] || indexPartBuild);
506
+ });
485
507
  });
486
- });
487
- if (!checkProd) {
488
- report(messages, MessagesCodes.ReleasedEntityIndexChangeIsNotAllowed, definitionBuild.name);
489
- }
490
- const checkBuild = uniqueIndexAnnotationBuild.every((indexPartBuild) => {
491
- return uniqueIndexAnnotationProd.find((indexPartProd) => {
492
- return (indexPartBuild["="] || indexPartBuild) === (indexPartProd["="] || indexPartProd);
508
+ if (!checkProd) {
509
+ report(messages, MessagesCodes.ReleasedEntityIndexChangeIsNotAllowed, definitionBuild.name);
510
+ }
511
+ const checkBuild = uniqueIndexAnnotationBuild.every((indexPartBuild) => {
512
+ return uniqueIndexAnnotationProd.find((indexPartProd) => {
513
+ return (indexPartBuild["="] || indexPartBuild) === (indexPartProd["="] || indexPartProd);
514
+ });
493
515
  });
494
- });
495
- if (!checkBuild && !definitionWhitelist && options.whitelist) {
496
- report(messages, MessagesCodes.ReleasedEntityIndexChangeIsNotWhitelisted, definitionBuild.name);
516
+ if (!checkBuild && !definitionWhitelist && options.whitelist) {
517
+ report(messages, MessagesCodes.ReleasedEntityIndexChangeIsNotWhitelisted, definitionBuild.name);
518
+ }
497
519
  }
498
520
  }
521
+ });
522
+ }
523
+ },
524
+ options.filter,
525
+ );
526
+ return messages;
527
+ }
528
+
529
+ function journalModeCheck(csnBuild, csnProd, whitelist, options) {
530
+ const messages = [];
531
+ if (options.check === "journalModeCheck") {
532
+ // Recursion
533
+ return messages;
534
+ }
535
+ visitPersistenceEntities(
536
+ csnBuild,
537
+ (definitionBuild) => {
538
+ const definitionProd = csnProd.definitions[definitionBuild.name];
539
+ if (definitionProd) {
540
+ if (definitionBuild["@cds.persistence.journal"] && !definitionProd["@cds.persistence.journal"]) {
541
+ const entityMessages = Checks.reduce((messages, check) => {
542
+ messages.push(
543
+ ...check(
544
+ csnBuild,
545
+ csnProd,
546
+ {},
547
+ { ...options, filter: [definitionBuild.name], check: "journalModeCheck" },
548
+ ),
549
+ );
550
+ return messages;
551
+ }, []);
552
+ if (entityMessages.length > 0) {
553
+ report(messages, MessagesCodes.ReleasedEntityJournalModeAndEntityChangeIsNotAllowed, definitionBuild.name);
554
+ }
499
555
  }
500
- });
501
- }
502
- });
556
+ }
557
+ },
558
+ options.filter,
559
+ );
503
560
  return messages;
504
561
  }
505
562
 
506
- function visitPersistenceEntities(csn, onEntity) {
563
+ function visitPersistenceEntities(csn, onEntity, filter) {
507
564
  if (!onEntity) {
508
565
  return;
509
566
  }
@@ -511,6 +568,9 @@ function visitPersistenceEntities(csn, onEntity) {
511
568
  return csn.definitions[name].kind === "service";
512
569
  });
513
570
  return Object.keys(csn.definitions).forEach((name) => {
571
+ if (filter && !filter.includes(name)) {
572
+ return;
573
+ }
514
574
  // Normal persistence entity
515
575
  const definition = csn.definitions[name];
516
576
  if (
@@ -490,7 +490,7 @@ class ReplicationCache {
490
490
  search(query) {
491
491
  let search = true;
492
492
  if (query.SELECT.search?.length > 0) {
493
- const ref = query.target.name;
493
+ const ref = query._target.name;
494
494
  this.stats.search[ref] ??= 0;
495
495
  this.stats.search[ref]++;
496
496
  this.log.debug("Replication cache skipped for search", {
@@ -504,7 +504,7 @@ class ReplicationCache {
504
504
  localized(query, refs) {
505
505
  let localized = true;
506
506
  if (query.SELECT.localized) {
507
- const ref = query.target.name;
507
+ const ref = query._target.name;
508
508
  this.stats.localized[ref] ??= 0;
509
509
  this.stats.localized[ref]++;
510
510
  this.log.debug("Replication cache not enabled for 'localized' without deploy feature", {
@@ -852,19 +852,20 @@ function fromRefs(model, query) {
852
852
  return refs;
853
853
  }, []);
854
854
  }
855
- if (query.target) {
855
+ if (query._target) {
856
+ const target = model.definitions[query._target.name];
856
857
  if (query.SELECT.orderBy) {
857
- refs = refs.concat(expressionRefs(model, query.target, query.SELECT.orderBy));
858
+ refs = refs.concat(expressionRefs(model, target, query.SELECT.orderBy));
858
859
  }
859
860
  if (query.SELECT.columns) {
860
- refs = refs.concat(expressionRefs(model, query.target, query.SELECT.columns));
861
- refs = refs.concat(expandRefs(model, query.target, query.SELECT.columns));
861
+ refs = refs.concat(expressionRefs(model, target, query.SELECT.columns));
862
+ refs = refs.concat(expandRefs(model, target, query.SELECT.columns));
862
863
  }
863
864
  if (query.SELECT.where) {
864
- refs = refs.concat(expressionRefs(model, query.target, query.SELECT.where));
865
+ refs = refs.concat(expressionRefs(model, target, query.SELECT.where));
865
866
  }
866
867
  if (query.SELECT.having) {
867
- refs = refs.concat(expressionRefs(model, query.target, query.SELECT.having));
868
+ refs = refs.concat(expressionRefs(model, target, query.SELECT.having));
868
869
  }
869
870
  }
870
871
  return refs;