slonik-interceptor-query-cache 46.4.0 → 46.6.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/CHANGELOG.md +8 -0
- package/dist/factories/createQueryCacheInterceptor.d.ts.map +1 -1
- package/dist/utilities/extractCacheAttributes.d.ts.map +1 -1
- package/dist/utilities/extractCacheAttributes.js +20 -28
- package/dist/utilities/extractCacheAttributes.js.map +1 -1
- package/dist/utilities/extractCacheAttributes.test.js +16 -16
- package/dist/utilities/normalizeCacheAttributes.d.ts.map +1 -1
- package/package.json +5 -6
- package/src/utilities/extractCacheAttributes.test.ts +16 -16
- package/src/utilities/extractCacheAttributes.ts +22 -30
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# slonik-interceptor-query-cache
|
|
2
2
|
|
|
3
|
+
## 46.6.0
|
|
4
|
+
|
|
5
|
+
## 46.5.0
|
|
6
|
+
|
|
7
|
+
### Minor Changes
|
|
8
|
+
|
|
9
|
+
- [`8a31366`](https://github.com/gajus/slonik/commit/8a31366b29474224a3bde6119f5261c63a09836d) Thanks [@gajus](https://github.com/gajus)! - improved implementation performance
|
|
10
|
+
|
|
3
11
|
## 46.4.0
|
|
4
12
|
|
|
5
13
|
## 46.3.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createQueryCacheInterceptor.d.ts","sourceRoot":"","sources":["../../src/factories/createQueryCacheInterceptor.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,QAAQ,CAAC;AAMhB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAMF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAQF,KAAK,OAAO,GAAG;IACb,GAAG,EAAE,CACH,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;IACjD,GAAG,EAAE,CACH,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,WAAW,CAAC,cAAc,CAAC,KACrC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"createQueryCacheInterceptor.d.ts","sourceRoot":"","sources":["../../src/factories/createQueryCacheInterceptor.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,QAAQ,CAAC;AAMhB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAMF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAQF,KAAK,OAAO,GAAG;IACb,GAAG,EAAE,CACH,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;IACjD,GAAG,EAAE,CACH,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,WAAW,CAAC,cAAc,CAAC,KACrC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,oBAAoB,kBAAkB,KACrC,WAiFF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractCacheAttributes.d.ts","sourceRoot":"","sources":["../../src/utilities/extractCacheAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"extractCacheAttributes.d.ts","sourceRoot":"","sources":["../../src/utilities/extractCacheAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AAMvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAQF,eAAO,MAAM,sBAAsB,GACjC,SAAS,MAAM,EACf,QAAQ,SAAS,wBAAwB,EAAE,KAC1C,wBAAwB,GAAG,IAuB7B,CAAC"}
|
|
@@ -1,40 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.extractCacheAttributes = void 0;
|
|
7
4
|
const node_crypto_1 = require("node:crypto");
|
|
8
|
-
const strip_comments_1 = __importDefault(require("strip-comments"));
|
|
9
5
|
const hash = (subject) => {
|
|
10
|
-
return (0, node_crypto_1.createHash)('
|
|
11
|
-
outputLength: 12,
|
|
12
|
-
})
|
|
13
|
-
.update(subject)
|
|
14
|
-
.digest('hex');
|
|
6
|
+
return (0, node_crypto_1.createHash)('sha256').update(subject).digest('hex').slice(0, 24);
|
|
15
7
|
};
|
|
8
|
+
const TtlRegex = /-- @cache-ttl (\d+)/u;
|
|
9
|
+
const DiscardEmptyRegex = /-- @cache-discard-empty (true|false)/u;
|
|
10
|
+
const KeyRegex = /-- @cache-key ([$\w\-:/]+)/iu;
|
|
11
|
+
const CommentRegex = /^\s*--.*$/gmu;
|
|
16
12
|
// TODO throw an error if an unknown attribute is used
|
|
17
13
|
const extractCacheAttributes = (subject, values) => {
|
|
18
|
-
const ttl =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.replaceAll(/^\s*--.*$/gmu, '')
|
|
22
|
-
.replaceAll(/\s/gu, ''));
|
|
23
|
-
const discardEmpty = (/-- @cache-discard-empty (true|false)/u.exec(subject)?.[1] ?? 'false') ===
|
|
24
|
-
'true';
|
|
25
|
-
const valueHash = hash(JSON.stringify(values));
|
|
26
|
-
if (ttl) {
|
|
27
|
-
const key = /-- @cache-key ([$\w\-:/]+)/iu.exec(subject)?.[1] ??
|
|
28
|
-
'query:$bodyHash:$valueHash';
|
|
29
|
-
return {
|
|
30
|
-
bodyHash,
|
|
31
|
-
discardEmpty,
|
|
32
|
-
key,
|
|
33
|
-
ttl: Number(ttl),
|
|
34
|
-
valueHash,
|
|
35
|
-
};
|
|
14
|
+
const ttl = subject.match(TtlRegex)?.[1];
|
|
15
|
+
if (!ttl) {
|
|
16
|
+
return null;
|
|
36
17
|
}
|
|
37
|
-
|
|
18
|
+
// Remove any comments from the query that begin with `--`
|
|
19
|
+
const bodyHash = hash(subject.replaceAll(CommentRegex, ''));
|
|
20
|
+
const discardEmpty = subject.match(DiscardEmptyRegex)?.[1] === 'true';
|
|
21
|
+
const valueHash = hash(JSON.stringify(values));
|
|
22
|
+
const key = subject.match(KeyRegex)?.[1] ?? `query:$bodyHash:$valueHash`;
|
|
23
|
+
return {
|
|
24
|
+
bodyHash,
|
|
25
|
+
discardEmpty,
|
|
26
|
+
key,
|
|
27
|
+
ttl: Number(ttl),
|
|
28
|
+
valueHash,
|
|
29
|
+
};
|
|
38
30
|
};
|
|
39
31
|
exports.extractCacheAttributes = extractCacheAttributes;
|
|
40
32
|
//# sourceMappingURL=extractCacheAttributes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractCacheAttributes.js","sourceRoot":"","sources":["../../src/utilities/extractCacheAttributes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extractCacheAttributes.js","sourceRoot":"","sources":["../../src/utilities/extractCacheAttributes.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAGzC,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,EAAE;IAC/B,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC,CAAC;AAUF,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AACxC,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAClE,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAChD,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC,sDAAsD;AAC/C,MAAM,sBAAsB,GAAG,CACpC,OAAe,EACf,MAA2C,EACV,EAAE;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEzC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;IAE5D,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;IAEtE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE/C,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,4BAA4B,CAAC;IAEzE,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,GAAG;QACH,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC;QAChB,SAAS;KACV,CAAC;AACJ,CAAC,CAAC;AA1BW,QAAA,sBAAsB,0BA0BjC"}
|
|
@@ -10,68 +10,68 @@ const ava_1 = __importDefault(require("ava"));
|
|
|
10
10
|
});
|
|
11
11
|
(0, ava_1.default)('extracts @cache-ttl', (t) => {
|
|
12
12
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60', []), {
|
|
13
|
-
bodyHash: '
|
|
13
|
+
bodyHash: 'e3b0c44298fc1c149afbf4c8',
|
|
14
14
|
discardEmpty: false,
|
|
15
15
|
key: 'query:$bodyHash:$valueHash',
|
|
16
16
|
ttl: 60,
|
|
17
|
-
valueHash: '
|
|
17
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
18
18
|
});
|
|
19
19
|
});
|
|
20
20
|
(0, ava_1.default)('extracts @cache-discard-empty', (t) => {
|
|
21
21
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60\n-- @cache-discard-empty false', []), {
|
|
22
|
-
bodyHash: '
|
|
22
|
+
bodyHash: '01ba4719c80b6fe911b091a7',
|
|
23
23
|
discardEmpty: false,
|
|
24
24
|
key: 'query:$bodyHash:$valueHash',
|
|
25
25
|
ttl: 60,
|
|
26
|
-
valueHash: '
|
|
26
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
27
27
|
});
|
|
28
28
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60\n-- @cache-discard-empty true', []), {
|
|
29
|
-
bodyHash: '
|
|
29
|
+
bodyHash: '01ba4719c80b6fe911b091a7',
|
|
30
30
|
discardEmpty: true,
|
|
31
31
|
key: 'query:$bodyHash:$valueHash',
|
|
32
32
|
ttl: 60,
|
|
33
|
-
valueHash: '
|
|
33
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
36
|
(0, ava_1.default)('computes the parameter value hash', (t) => {
|
|
37
37
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60', [1]), {
|
|
38
|
-
bodyHash: '
|
|
38
|
+
bodyHash: 'e3b0c44298fc1c149afbf4c8',
|
|
39
39
|
discardEmpty: false,
|
|
40
40
|
key: 'query:$bodyHash:$valueHash',
|
|
41
41
|
ttl: 60,
|
|
42
|
-
valueHash: '
|
|
42
|
+
valueHash: '080a9ed428559ef602668b4c',
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
(0, ava_1.default)('computes the body hash; white spaces do not affect the body hash', (t) => {
|
|
46
46
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60\nSELECT 1', []), {
|
|
47
|
-
bodyHash: '
|
|
47
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
48
48
|
discardEmpty: false,
|
|
49
49
|
key: 'query:$bodyHash:$valueHash',
|
|
50
50
|
ttl: 60,
|
|
51
|
-
valueHash: '
|
|
51
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
52
52
|
});
|
|
53
53
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60\n\nSELECT 1', []), {
|
|
54
|
-
bodyHash: '
|
|
54
|
+
bodyHash: 'db4396c23e75fa095eddf372',
|
|
55
55
|
discardEmpty: false,
|
|
56
56
|
key: 'query:$bodyHash:$valueHash',
|
|
57
57
|
ttl: 60,
|
|
58
|
-
valueHash: '
|
|
58
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
61
|
(0, ava_1.default)('computes the body hash; comments do not affect the body hash', (t) => {
|
|
62
62
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 60\nSELECT 1', []), {
|
|
63
|
-
bodyHash: '
|
|
63
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
64
64
|
discardEmpty: false,
|
|
65
65
|
key: 'query:$bodyHash:$valueHash',
|
|
66
66
|
ttl: 60,
|
|
67
|
-
valueHash: '
|
|
67
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
68
68
|
});
|
|
69
69
|
t.deepEqual((0, extractCacheAttributes_1.extractCacheAttributes)('-- @cache-ttl 120\nSELECT 1', []), {
|
|
70
|
-
bodyHash: '
|
|
70
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
71
71
|
discardEmpty: false,
|
|
72
72
|
key: 'query:$bodyHash:$valueHash',
|
|
73
73
|
ttl: 120,
|
|
74
|
-
valueHash: '
|
|
74
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
77
|
//# sourceMappingURL=extractCacheAttributes.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeCacheAttributes.d.ts","sourceRoot":"","sources":["../../src/utilities/normalizeCacheAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,eAAO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"normalizeCacheAttributes.d.ts","sourceRoot":"","sources":["../../src/utilities/normalizeCacheAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,eAAO,MAAM,wBAAwB,GACnC,0BAA0B,wBAAwB,KACjD,eAQF,CAAC"}
|
package/package.json
CHANGED
|
@@ -16,17 +16,16 @@
|
|
|
16
16
|
]
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"roarr": "^7.21.1"
|
|
20
|
-
"strip-comments": "^2.0.1"
|
|
19
|
+
"roarr": "^7.21.1"
|
|
21
20
|
},
|
|
22
21
|
"description": "Logs Slonik queries.",
|
|
23
22
|
"devDependencies": {
|
|
24
23
|
"ava": "^6.1.3",
|
|
25
|
-
"eslint": "^9.
|
|
26
|
-
"slonik": "^46.
|
|
24
|
+
"eslint": "^9.25.1",
|
|
25
|
+
"slonik": "^46.6.0",
|
|
27
26
|
"ts-node": "^10.4.0",
|
|
28
27
|
"typescript": "^5.6.3",
|
|
29
|
-
"@slonik/eslint-config": "^46.
|
|
28
|
+
"@slonik/eslint-config": "^46.6.0"
|
|
30
29
|
},
|
|
31
30
|
"engines": {
|
|
32
31
|
"node": ">=18"
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"url": "https://github.com/gajus/slonik"
|
|
48
47
|
},
|
|
49
48
|
"typings": "./dist/index.d.ts",
|
|
50
|
-
"version": "46.
|
|
49
|
+
"version": "46.6.0",
|
|
51
50
|
"scripts": {
|
|
52
51
|
"build": "rm -fr ./dist && tsc",
|
|
53
52
|
"lint": "eslint ./src && tsc --noEmit",
|
|
@@ -7,11 +7,11 @@ test('returns null when query does not contain cache attributes', (t) => {
|
|
|
7
7
|
|
|
8
8
|
test('extracts @cache-ttl', (t) => {
|
|
9
9
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 60', []), {
|
|
10
|
-
bodyHash: '
|
|
10
|
+
bodyHash: 'e3b0c44298fc1c149afbf4c8',
|
|
11
11
|
discardEmpty: false,
|
|
12
12
|
key: 'query:$bodyHash:$valueHash',
|
|
13
13
|
ttl: 60,
|
|
14
|
-
valueHash: '
|
|
14
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
|
|
@@ -22,11 +22,11 @@ test('extracts @cache-discard-empty', (t) => {
|
|
|
22
22
|
[],
|
|
23
23
|
),
|
|
24
24
|
{
|
|
25
|
-
bodyHash: '
|
|
25
|
+
bodyHash: '01ba4719c80b6fe911b091a7',
|
|
26
26
|
discardEmpty: false,
|
|
27
27
|
key: 'query:$bodyHash:$valueHash',
|
|
28
28
|
ttl: 60,
|
|
29
|
-
valueHash: '
|
|
29
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
30
30
|
},
|
|
31
31
|
);
|
|
32
32
|
|
|
@@ -36,57 +36,57 @@ test('extracts @cache-discard-empty', (t) => {
|
|
|
36
36
|
[],
|
|
37
37
|
),
|
|
38
38
|
{
|
|
39
|
-
bodyHash: '
|
|
39
|
+
bodyHash: '01ba4719c80b6fe911b091a7',
|
|
40
40
|
discardEmpty: true,
|
|
41
41
|
key: 'query:$bodyHash:$valueHash',
|
|
42
42
|
ttl: 60,
|
|
43
|
-
valueHash: '
|
|
43
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
44
44
|
},
|
|
45
45
|
);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
test('computes the parameter value hash', (t) => {
|
|
49
49
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 60', [1]), {
|
|
50
|
-
bodyHash: '
|
|
50
|
+
bodyHash: 'e3b0c44298fc1c149afbf4c8',
|
|
51
51
|
discardEmpty: false,
|
|
52
52
|
key: 'query:$bodyHash:$valueHash',
|
|
53
53
|
ttl: 60,
|
|
54
|
-
valueHash: '
|
|
54
|
+
valueHash: '080a9ed428559ef602668b4c',
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
test('computes the body hash; white spaces do not affect the body hash', (t) => {
|
|
59
59
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 60\nSELECT 1', []), {
|
|
60
|
-
bodyHash: '
|
|
60
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
61
61
|
discardEmpty: false,
|
|
62
62
|
key: 'query:$bodyHash:$valueHash',
|
|
63
63
|
ttl: 60,
|
|
64
|
-
valueHash: '
|
|
64
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 60\n\nSELECT 1', []), {
|
|
68
|
-
bodyHash: '
|
|
68
|
+
bodyHash: 'db4396c23e75fa095eddf372',
|
|
69
69
|
discardEmpty: false,
|
|
70
70
|
key: 'query:$bodyHash:$valueHash',
|
|
71
71
|
ttl: 60,
|
|
72
|
-
valueHash: '
|
|
72
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
test('computes the body hash; comments do not affect the body hash', (t) => {
|
|
77
77
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 60\nSELECT 1', []), {
|
|
78
|
-
bodyHash: '
|
|
78
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
79
79
|
discardEmpty: false,
|
|
80
80
|
key: 'query:$bodyHash:$valueHash',
|
|
81
81
|
ttl: 60,
|
|
82
|
-
valueHash: '
|
|
82
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
t.deepEqual(extractCacheAttributes('-- @cache-ttl 120\nSELECT 1', []), {
|
|
86
|
-
bodyHash: '
|
|
86
|
+
bodyHash: 'f815101480e0c02658d3bac8',
|
|
87
87
|
discardEmpty: false,
|
|
88
88
|
key: 'query:$bodyHash:$valueHash',
|
|
89
89
|
ttl: 120,
|
|
90
|
-
valueHash: '
|
|
90
|
+
valueHash: '4f53cda18c2baa0c0354bb5f',
|
|
91
91
|
});
|
|
92
92
|
});
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { type PrimitiveValueExpression } from 'slonik';
|
|
3
|
-
import stripComments from 'strip-comments';
|
|
4
3
|
|
|
5
4
|
const hash = (subject: string) => {
|
|
6
|
-
return createHash('
|
|
7
|
-
outputLength: 12,
|
|
8
|
-
})
|
|
9
|
-
.update(subject)
|
|
10
|
-
.digest('hex');
|
|
5
|
+
return createHash('sha256').update(subject).digest('hex').slice(0, 24);
|
|
11
6
|
};
|
|
12
7
|
|
|
13
8
|
export type ExtractedCacheAttributes = {
|
|
@@ -18,39 +13,36 @@ export type ExtractedCacheAttributes = {
|
|
|
18
13
|
valueHash: string;
|
|
19
14
|
};
|
|
20
15
|
|
|
16
|
+
const TtlRegex = /-- @cache-ttl (\d+)/u;
|
|
17
|
+
const DiscardEmptyRegex = /-- @cache-discard-empty (true|false)/u;
|
|
18
|
+
const KeyRegex = /-- @cache-key ([$\w\-:/]+)/iu;
|
|
19
|
+
const CommentRegex = /^\s*--.*$/gmu;
|
|
20
|
+
|
|
21
21
|
// TODO throw an error if an unknown attribute is used
|
|
22
22
|
export const extractCacheAttributes = (
|
|
23
23
|
subject: string,
|
|
24
24
|
values: readonly PrimitiveValueExpression[],
|
|
25
25
|
): ExtractedCacheAttributes | null => {
|
|
26
|
-
const ttl =
|
|
26
|
+
const ttl = subject.match(TtlRegex)?.[1];
|
|
27
|
+
|
|
28
|
+
if (!ttl) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
27
31
|
|
|
28
|
-
//
|
|
29
|
-
const bodyHash = hash(
|
|
30
|
-
stripComments(subject)
|
|
31
|
-
.replaceAll(/^\s*--.*$/gmu, '')
|
|
32
|
-
.replaceAll(/\s/gu, ''),
|
|
33
|
-
);
|
|
32
|
+
// Remove any comments from the query that begin with `--`
|
|
33
|
+
const bodyHash = hash(subject.replaceAll(CommentRegex, ''));
|
|
34
34
|
|
|
35
|
-
const discardEmpty =
|
|
36
|
-
(/-- @cache-discard-empty (true|false)/u.exec(subject)?.[1] ?? 'false') ===
|
|
37
|
-
'true';
|
|
35
|
+
const discardEmpty = subject.match(DiscardEmptyRegex)?.[1] === 'true';
|
|
38
36
|
|
|
39
37
|
const valueHash = hash(JSON.stringify(values));
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
const key =
|
|
43
|
-
/-- @cache-key ([$\w\-:/]+)/iu.exec(subject)?.[1] ??
|
|
44
|
-
'query:$bodyHash:$valueHash';
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
bodyHash,
|
|
48
|
-
discardEmpty,
|
|
49
|
-
key,
|
|
50
|
-
ttl: Number(ttl),
|
|
51
|
-
valueHash,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
39
|
+
const key = subject.match(KeyRegex)?.[1] ?? `query:$bodyHash:$valueHash`;
|
|
54
40
|
|
|
55
|
-
return
|
|
41
|
+
return {
|
|
42
|
+
bodyHash,
|
|
43
|
+
discardEmpty,
|
|
44
|
+
key,
|
|
45
|
+
ttl: Number(ttl),
|
|
46
|
+
valueHash,
|
|
47
|
+
};
|
|
56
48
|
};
|