latchkey 3.10.0 → 3.10.1
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/dist/src/dailyCounting.d.ts +3 -0
- package/dist/src/dailyCounting.d.ts.map +1 -1
- package/dist/src/dailyCounting.js +6 -2
- package/dist/src/dailyCounting.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/dailyCounting.test.js +36 -1
- package/dist/tests/dailyCounting.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* Reads `LATCHKEY_DIR/last-daily-count` for an ISO timestamp.
|
|
5
5
|
* If the file is missing or the timestamp is older than 24 hours,
|
|
6
6
|
* spawns a detached curl process to ping the counting endpoint.
|
|
7
|
+
*
|
|
8
|
+
* The tracker file is written atomically, which also means a symlinked
|
|
9
|
+
* tracker file is written through instead of being replaced.
|
|
7
10
|
*/
|
|
8
11
|
import type { Config } from './config.js';
|
|
9
12
|
export declare function countDailyIfNeeded(config: Config): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dailyCounting.d.ts","sourceRoot":"","sources":["../../src/dailyCounting.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dailyCounting.d.ts","sourceRoot":"","sources":["../../src/dailyCounting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAyB1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAkBvD"}
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
* Reads `LATCHKEY_DIR/last-daily-count` for an ISO timestamp.
|
|
5
5
|
* If the file is missing or the timestamp is older than 24 hours,
|
|
6
6
|
* spawns a detached curl process to ping the counting endpoint.
|
|
7
|
+
*
|
|
8
|
+
* The tracker file is written atomically, which also means a symlinked
|
|
9
|
+
* tracker file is written through instead of being replaced.
|
|
7
10
|
*/
|
|
8
|
-
import { existsSync, readFileSync
|
|
11
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
9
12
|
import { platform } from 'node:os';
|
|
10
13
|
import { join } from 'node:path';
|
|
14
|
+
import { writeFileAtomic } from './atomicWrite.js';
|
|
11
15
|
import { runDetached } from './curl.js';
|
|
12
16
|
const DAILY_COUNT_FILENAME = 'last-daily-count';
|
|
13
17
|
const COUNTING_URL = 'https://latchkey.goatcounter.com/count?p=/daily';
|
|
@@ -30,7 +34,7 @@ export function countDailyIfNeeded(config) {
|
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
36
|
const filePath = join(config.directory, DAILY_COUNT_FILENAME);
|
|
33
|
-
|
|
37
|
+
writeFileAtomic(filePath, new Date().toISOString());
|
|
34
38
|
runDetached([
|
|
35
39
|
'--silent',
|
|
36
40
|
'--max-time',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dailyCounting.js","sourceRoot":"","sources":["../../src/dailyCounting.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dailyCounting.js","sourceRoot":"","sources":["../../src/dailyCounting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAChD,MAAM,YAAY,GAAG,iDAAiD,CAAC;AACvE,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAE9D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAEpC,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,uBAAuB,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,IAAI,MAAM,CAAC,gBAAgB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAC9D,eAAe,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAEpD,WAAW,CAAC;QACV,UAAU;QACV,YAAY;QACZ,MAAM,CAAC,eAAe,CAAC;QACvB,UAAU;QACV,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW;QAC5C,IAAI;QACJ,sCAAsC;QACtC,YAAY;KACb,CAAC,CAAC;AACL,CAAC"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "3.10.
|
|
1
|
+
export declare const VERSION = "3.10.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/src/version.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mkdtempSync, readFileSync, rmSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync, existsSync, lstatSync, } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { Config } from '../src/config.js';
|
|
@@ -69,6 +69,41 @@ describe('countDailyIfNeeded', () => {
|
|
|
69
69
|
countDailyIfNeeded(countingDisabledConfig);
|
|
70
70
|
expect(detachedCalls).toHaveLength(0);
|
|
71
71
|
});
|
|
72
|
+
it('should write through a symlinked tracker file instead of replacing it', () => {
|
|
73
|
+
const externalDirectory = mkdtempSync(join(tmpdir(), 'latchkey-daily-count-external-'));
|
|
74
|
+
const externalPath = join(externalDirectory, 'tracker');
|
|
75
|
+
const filePath = join(directory, 'last-daily-count');
|
|
76
|
+
const oldDate = new Date(Date.now() - 25 * 60 * 60 * 1000);
|
|
77
|
+
writeFileSync(externalPath, oldDate.toISOString(), 'utf-8');
|
|
78
|
+
symlinkSync(externalPath, filePath);
|
|
79
|
+
try {
|
|
80
|
+
countDailyIfNeeded(config);
|
|
81
|
+
expect(detachedCalls).toHaveLength(1);
|
|
82
|
+
expect(lstatSync(filePath).isSymbolicLink()).toBe(true);
|
|
83
|
+
const timestamp = new Date(readFileSync(externalPath, 'utf-8').trim());
|
|
84
|
+
expect(Date.now() - timestamp.getTime()).toBeLessThan(5000);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
rmSync(externalDirectory, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
it('should write through a dangling symlinked tracker file', () => {
|
|
91
|
+
const externalDirectory = mkdtempSync(join(tmpdir(), 'latchkey-daily-count-external-'));
|
|
92
|
+
const externalPath = join(externalDirectory, 'tracker');
|
|
93
|
+
const filePath = join(directory, 'last-daily-count');
|
|
94
|
+
symlinkSync(externalPath, filePath);
|
|
95
|
+
try {
|
|
96
|
+
countDailyIfNeeded(config);
|
|
97
|
+
expect(detachedCalls).toHaveLength(1);
|
|
98
|
+
expect(lstatSync(filePath).isSymbolicLink()).toBe(true);
|
|
99
|
+
expect(existsSync(externalPath)).toBe(true);
|
|
100
|
+
const timestamp = new Date(readFileSync(externalPath, 'utf-8').trim());
|
|
101
|
+
expect(isNaN(timestamp.getTime())).toBe(false);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
rmSync(externalDirectory, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
72
107
|
it('should not fire a request when the timestamp is exactly 23 hours old', () => {
|
|
73
108
|
const filePath = join(directory, 'last-daily-count');
|
|
74
109
|
const recentDate = new Date(Date.now() - 23 * 60 * 60 * 1000);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dailyCounting.test.js","sourceRoot":"","sources":["../../tests/dailyCounting.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"dailyCounting.test.js","sourceRoot":"","sources":["../../tests/dailyCounting.test.ts"],"names":[],"mappings":"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"}
|