@cap-js-community/common 0.2.3 → 0.2.4

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/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## Version 0.2.4 - 2025-07-03
9
+
10
+ ### Fixed
11
+
12
+ - Multi-tenancy fixes
13
+ - Improve reference detection
14
+ - Deactivate TTL for negative value and static entities
15
+
8
16
  ## Version 0.2.3 - 2025-07-01
9
17
 
10
18
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js-community/common",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "CAP Node.js Community Common",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "engines": {
@@ -45,7 +45,7 @@
45
45
  "audit": "npm audit --only=prod"
46
46
  },
47
47
  "dependencies": {
48
- "@cap-js/sqlite": "^2.0.1",
48
+ "@cap-js/sqlite": "^2.0.2",
49
49
  "commander": "^14.0.0",
50
50
  "redis": "^4.7.1",
51
51
  "verror": "^1.10.1"
@@ -53,14 +53,14 @@
53
53
  "devDependencies": {
54
54
  "@cap-js-community/common": "./",
55
55
  "@cap-js/cds-test": "^0.4.0",
56
- "@sap/cds": "^9.0.4",
56
+ "@sap/cds": "^9.1.0",
57
57
  "@sap/cds-common-content": "^3.0.1",
58
- "@sap/cds-dk": "^9.0.5",
59
- "eslint": "9.30.0",
58
+ "@sap/cds-dk": "^9.1.0",
59
+ "eslint": "9.30.1",
60
60
  "eslint-config-prettier": "10.1.5",
61
61
  "eslint-plugin-jest": "29.0.1",
62
62
  "eslint-plugin-n": "^17.20.0",
63
- "jest": "30.0.3",
63
+ "jest": "30.0.4",
64
64
  "jest-html-reporters": "3.1.7",
65
65
  "jest-junit": "16.0.0",
66
66
  "prettier": "3.6.2",
@@ -73,10 +73,14 @@ class ReplicationCache {
73
73
  this.options?.credentials?.database &&
74
74
  this.options?.credentials?.database !== Constants.InMemory
75
75
  ) {
76
- this.log.debug("Preparing replication cache template database");
77
- this.template = createDB(Tenant.Template, this.model, this.options).catch((err) => {
78
- this.log.error("Preparing replication cache failed", err);
79
- });
76
+ this.log.info("Preparing replication cache template database");
77
+ this.template = createDB(Tenant.Template, this.model, this.options)
78
+ .then(() => {
79
+ this.log.info("Prepared replication cache template database");
80
+ })
81
+ .catch((err) => {
82
+ this.log.error("Preparing replication cache failed", err);
83
+ });
80
84
  }
81
85
  }
82
86
  }
@@ -220,9 +224,17 @@ class ReplicationCache {
220
224
  if (this.options.measure) {
221
225
  return this.measure(
222
226
  async () => {
223
- return db.tx({ ...req.context }, async (tx) => {
224
- return tx.run(req.query);
225
- });
227
+ return db.tx(
228
+ {
229
+ tenant: req.context.tenant,
230
+ locale: req.context.locale,
231
+ user: req.context.user,
232
+ http: req.context.http,
233
+ },
234
+ async (tx) => {
235
+ return tx.run(req.query);
236
+ },
237
+ );
226
238
  },
227
239
  async () => {
228
240
  await next();
@@ -585,6 +597,7 @@ class ReplicationCacheEntry {
585
597
  this.db = tenant.db;
586
598
  this.ref = ref;
587
599
  this.definition = this.csn[ref];
600
+ this.static = !!this.definition[Annotations.ReplicateStatic];
588
601
  this.preload = this.cache.options.preload && this.definition[Annotations.ReplicatePreload];
589
602
  this.name = this.definition.name.replace(/\./gi, "_");
590
603
  this.status = Status.New;
@@ -614,13 +627,15 @@ class ReplicationCacheEntry {
614
627
  await this.load(thread);
615
628
  this.status = Status.Ready;
616
629
  this.failures = 0;
617
- this.timeout = setTimeout(async () => {
618
- this.cache.log.debug("Replication cache ref TTL reached", {
619
- tenant: this.tenant.id,
620
- ref: this.ref,
621
- });
622
- await this.clear(true);
623
- }, this.ttl).unref();
630
+ if (this.ttl > 0 && !this.static) {
631
+ this.timeout = setTimeout(async () => {
632
+ this.cache.log.debug("Replication cache ref TTL reached", {
633
+ tenant: this.tenant.id,
634
+ ref: this.ref,
635
+ });
636
+ await this.clear(true);
637
+ }, this.ttl).unref();
638
+ }
624
639
  }
625
640
  this.cache.log.debug("Preparing replication cache ref finished", {
626
641
  tenant: this.tenant.id,
@@ -779,7 +794,11 @@ async function createDB(tenant, model, options) {
779
794
  const db = new SQLiteService(tenant ?? Tenant.Default, model, {
780
795
  kind: "sqlite",
781
796
  impl: "@cap-js/sqlite",
782
- credentials: { ...options.credentials, database: filePath },
797
+ multiTenant: false,
798
+ credentials: {
799
+ ...options.credentials,
800
+ database: filePath,
801
+ },
783
802
  });
784
803
  await db.init();
785
804
  if (options.deploy && (filePath === Constants.InMemory || tenant === Tenant.Template)) {
@@ -870,14 +889,17 @@ function selectFromRefs(model, query) {
870
889
  if (query.SELECT.from.ref) {
871
890
  refs = resolveRefs(model, query.SELECT.from.ref);
872
891
  } else if (query.SELECT.from.args) {
873
- refs = query.SELECT.from.args.reduce((refs, arg) => {
892
+ for (const arg of query.SELECT.from.args) {
874
893
  if (arg.ref) {
875
894
  refs = refs.concat(resolveRefs(model, arg.ref));
876
895
  } else if (arg.args) {
877
896
  refs = refs.concat(selectFromRefs(model, { SELECT: { from: { args: arg.args } } }));
878
897
  }
879
- return refs;
880
- }, []);
898
+ }
899
+ } else if (query.SELECT.from.SET?.args) {
900
+ for (const arg of query.SELECT.from.SET.args) {
901
+ refs = refs.concat(selectFromRefs(model, arg));
902
+ }
881
903
  } else if (query.SELECT.from.SELECT) {
882
904
  refs = selectFromRefs(model, query.SELECT.from);
883
905
  }
@@ -895,6 +917,10 @@ function selectFromPrimaryRef(model, query) {
895
917
  return selectFromPrimaryRef(model, { SELECT: { from: { args: arg.args } } });
896
918
  }
897
919
  }
920
+ } else if (query.SELECT.from.SET?.args) {
921
+ for (const arg of query.SELECT.from.SET.args) {
922
+ return selectFromPrimaryRef(model, arg);
923
+ }
898
924
  } else if (query.SELECT.from.SELECT) {
899
925
  return selectFromPrimaryRef(model, query.SELECT.from);
900
926
  }
@@ -905,9 +931,7 @@ function selectFromAliases(model, definition, query) {
905
931
  if (definition?.name) {
906
932
  aliases["$self"] = definition.name;
907
933
  }
908
- if (query.SELECT.from.SELECT) {
909
- // Sub-select aliases are not (yet) supported
910
- } else if (query.SELECT.from.ref) {
934
+ if (query.SELECT.from.ref) {
911
935
  const ref = resolveRef(model, query.SELECT.from.ref);
912
936
  if (query.SELECT.from.as) {
913
937
  aliases[query.SELECT.from.as] = ref;
@@ -926,14 +950,24 @@ function selectFromAliases(model, definition, query) {
926
950
  aliases[as] = ref;
927
951
  }
928
952
  } else if (arg.args) {
929
- for (const subArg of arg.args) {
930
- aliases = {
931
- ...aliases,
932
- ...selectFromAliases(model, definition, { SELECT: { from: { args: subArg.args } } }),
933
- };
934
- }
953
+ aliases = {
954
+ ...aliases,
955
+ ...selectFromAliases(model, definition, { SELECT: { from: { args: arg.args } } }),
956
+ };
935
957
  }
936
958
  }
959
+ } else if (query.SELECT.from.SET?.args) {
960
+ for (const arg of query.SELECT.from.SET.args) {
961
+ aliases = {
962
+ ...aliases,
963
+ ...selectFromAliases(model, definition, arg),
964
+ };
965
+ }
966
+ } else if (query.SELECT.from.SELECT) {
967
+ aliases = {
968
+ ...aliases,
969
+ ...selectFromAliases(model, definition, query.SELECT.from),
970
+ };
937
971
  }
938
972
  return aliases;
939
973
  }