@zukhruf/fs 0.3.25 → 0.3.26
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/README.md +1 -2
- package/dist/safe-file-name.d.ts +10 -9
- package/dist/safe-file-name.d.ts.map +1 -1
- package/dist/safe-file-name.js +13 -10
- package/dist/safe-file-name.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,9 +66,8 @@ await createExclusive(join('/var/lib/app/locks', `${name}.lock`), 'pid 4242');
|
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
- A key that fits gets its URI encoding, with each `.` as `%2E`. Thus a name is never `.` or `..`. The name of `job.lock` is `job%2Elock`, so it is never the name of `job` plus the suffix `.lock`.
|
|
69
|
+
- The encoding also encodes each uppercase letter. The names of `Sync`, `sync` and `SYNC` are `%53ync`, `sync` and `%53%59%4E%43`. APFS and NTFS compare file names without case. On these file systems too, each key gets its own file, as on Linux.
|
|
69
70
|
- A key that does not fit, or that is not well-formed Unicode, gets a hashed name: the first 32 characters of its encoding, `%%`, and the SHA-256 of its UTF-16 code units in hex. A hashed name has at most 98 characters. An encoding never holds `%%`, so a hashed name is never the name of a key that fits.
|
|
70
|
-
- The rule does not change between versions. Processes of two versions find the same file for a key.
|
|
71
|
-
- On a case-insensitive file system, keys that differ only by case get one file.
|
|
72
71
|
|
|
73
72
|
## Try again while Windows refuses a file for a moment
|
|
74
73
|
|
package/dist/safe-file-name.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Maps any key to a single path segment that still fits a file name after the
|
|
3
|
-
* caller adds up to `longestSuffix` characters.
|
|
4
|
-
*
|
|
5
|
-
* a key
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* caller adds up to `longestSuffix` characters. The name is the URI encoding of
|
|
4
|
+
* the key, with each dot and each uppercase letter encoded too. A name thus has
|
|
5
|
+
* no dot: a key can never be `.` or `..`, and a suffix such as `.lock` can never
|
|
6
|
+
* make the name of another key. A name is ASCII, and it has no uppercase letter
|
|
7
|
+
* outside an escape, whose hex digits are always uppercase. Thus two keys never
|
|
8
|
+
* get names that are equal without case. APFS and NTFS compare file names
|
|
9
|
+
* without case, and there too each key gets its own file, as on Linux.
|
|
8
10
|
*
|
|
9
11
|
* A key whose encoding does not fit, or that is not well-formed Unicode and so
|
|
10
12
|
* has no encoding, gets the start of its encoding, `%%`, and the SHA-256 of its
|
|
11
|
-
* UTF-16 code units.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* two digests into one name; and the code units keep lone surrogates apart.
|
|
13
|
+
* UTF-16 code units. No encoding contains `%%`, so the two kinds of name never
|
|
14
|
+
* meet; the digest is lowercase hex, so case cannot fold two digests into one
|
|
15
|
+
* name; and the code units keep lone surrogates apart.
|
|
15
16
|
*/
|
|
16
17
|
export declare function safeFileName(key: string, longestSuffix: number): string;
|
|
17
18
|
//# sourceMappingURL=safe-file-name.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-file-name.d.ts","sourceRoot":"","sources":["../src/safe-file-name.ts"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"safe-file-name.d.ts","sourceRoot":"","sources":["../src/safe-file-name.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAYvE"}
|
package/dist/safe-file-name.js
CHANGED
|
@@ -5,18 +5,19 @@ const longestFileName = 255;
|
|
|
5
5
|
const visibleStart = 32;
|
|
6
6
|
/**
|
|
7
7
|
* Maps any key to a single path segment that still fits a file name after the
|
|
8
|
-
* caller adds up to `longestSuffix` characters.
|
|
9
|
-
*
|
|
10
|
-
* a key
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* caller adds up to `longestSuffix` characters. The name is the URI encoding of
|
|
9
|
+
* the key, with each dot and each uppercase letter encoded too. A name thus has
|
|
10
|
+
* no dot: a key can never be `.` or `..`, and a suffix such as `.lock` can never
|
|
11
|
+
* make the name of another key. A name is ASCII, and it has no uppercase letter
|
|
12
|
+
* outside an escape, whose hex digits are always uppercase. Thus two keys never
|
|
13
|
+
* get names that are equal without case. APFS and NTFS compare file names
|
|
14
|
+
* without case, and there too each key gets its own file, as on Linux.
|
|
13
15
|
*
|
|
14
16
|
* A key whose encoding does not fit, or that is not well-formed Unicode and so
|
|
15
17
|
* has no encoding, gets the start of its encoding, `%%`, and the SHA-256 of its
|
|
16
|
-
* UTF-16 code units.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* two digests into one name; and the code units keep lone surrogates apart.
|
|
18
|
+
* UTF-16 code units. No encoding contains `%%`, so the two kinds of name never
|
|
19
|
+
* meet; the digest is lowercase hex, so case cannot fold two digests into one
|
|
20
|
+
* name; and the code units keep lone surrogates apart.
|
|
20
21
|
*/
|
|
21
22
|
export function safeFileName(key, longestSuffix) {
|
|
22
23
|
if (key.isWellFormed()) {
|
|
@@ -33,6 +34,8 @@ export function safeFileName(key, longestSuffix) {
|
|
|
33
34
|
return `${start}%%${digest}`;
|
|
34
35
|
}
|
|
35
36
|
function encode(key) {
|
|
36
|
-
return encodeURIComponent(key).replaceAll(
|
|
37
|
+
return encodeURIComponent(key).replaceAll(/%[0-9A-F]{2}|[.A-Z]/g, (match) => match.length === 1
|
|
38
|
+
? `%${match.charCodeAt(0).toString(16).toUpperCase()}`
|
|
39
|
+
: match);
|
|
37
40
|
}
|
|
38
41
|
//# sourceMappingURL=safe-file-name.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-file-name.js","sourceRoot":"","sources":["../src/safe-file-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,oEAAoE;AACpE,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,2EAA2E;AAC3E,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"safe-file-name.js","sourceRoot":"","sources":["../src/safe-file-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,oEAAoE;AACpE,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,2EAA2E;AAC3E,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,aAAqB;IAC7D,IAAI,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,aAAa,IAAI,eAAe;YAAE,OAAO,OAAO,CAAC;IACxE,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;SACrC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;SACtB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC;SAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;SACnC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO,GAAG,KAAK,KAAK,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,MAAM,CAAC,GAAW;IACzB,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,KAAK,EAAE,EAAE,CAC1E,KAAK,CAAC,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE;QACtD,CAAC,CAAC,KAAK,CACV,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/fs",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.26",
|
|
4
4
|
"description": "File writes that a reader never sees half done: replace a file in one step, with or without a sync to the disk, or create it only when it is absent. A lock on a file that the kernel frees when its holder dies. Also retries the short refusals of Windows, and names a file after any key.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|