@cap-js-community/common 0.2.3 → 0.2.5
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,20 @@ 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.5 - 2025-07-07
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Normalize newline character in hash calculation
|
|
13
|
+
|
|
14
|
+
## Version 0.2.4 - 2025-07-03
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Multi-tenancy fixes
|
|
19
|
+
- Improve reference detection
|
|
20
|
+
- Deactivate TTL for negative value and static entities
|
|
21
|
+
|
|
8
22
|
## Version 0.2.3 - 2025-07-01
|
|
9
23
|
|
|
10
24
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js-community/common",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
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.
|
|
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
|
|
56
|
+
"@sap/cds": "^9.1.0",
|
|
57
57
|
"@sap/cds-common-content": "^3.0.1",
|
|
58
|
-
"@sap/cds-dk": "^9.0
|
|
59
|
-
"eslint": "9.30.
|
|
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
|
-
"eslint-plugin-n": "^17.
|
|
63
|
-
"jest": "30.0.
|
|
62
|
+
"eslint-plugin-n": "^17.21.0",
|
|
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",
|
|
@@ -652,6 +652,7 @@ function normalizeType(csn, type) {
|
|
|
652
652
|
return typeof type === "object" ? JSON.stringify(type) : type;
|
|
653
653
|
}
|
|
654
654
|
|
|
655
|
-
const hash = (buffer, algorithm = "sha256") =>
|
|
655
|
+
const hash = (buffer, algorithm = "sha256") =>
|
|
656
|
+
crypto.createHash(algorithm).update(buffer.toString().replace(/\r\n/g, "\n")).digest("hex");
|
|
656
657
|
|
|
657
658
|
module.exports = MigrationCheck;
|
|
@@ -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.
|
|
77
|
-
this.template = createDB(Tenant.Template, this.model, this.options)
|
|
78
|
-
|
|
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(
|
|
224
|
-
|
|
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.
|
|
618
|
-
this.
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
930
|
-
aliases
|
|
931
|
-
|
|
932
|
-
|
|
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
|
}
|