@zag-js/file-utils 2.0.0-next.2 → 2.0.0-next.3

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/index.d.mts CHANGED
@@ -4,8 +4,8 @@ export { DownloadFileOptions, downloadFile } from './download-file.mjs';
4
4
  export { getAcceptAttrString } from './get-accept-attr.mjs';
5
5
  export { getFileDataUrl } from './get-file-data-url.mjs';
6
6
  export { getTotalFileSize } from './get-total-file-size.mjs';
7
- export { isFileEqual } from './is-file-equal.mjs';
7
+ export { getFileKey, isFileEqual } from './is-file-equal.mjs';
8
8
  export { isValidFileSize } from './is-valid-file-size.mjs';
9
- export { isValidFileType } from './is-valid-file-type.mjs';
9
+ export { createFileTypeValidator, isValidFileType } from './is-valid-file-type.mjs';
10
10
  export { getFileMimeType } from './get-file-mime-type.mjs';
11
11
  export { ApplicationFileMimeType, AudioFileMimeType, FileError, FileMimeType, FileMimeTypeGroup, FontFileMimeType, ImageFileMimeType, TextFileMimeType, VideoFileMimeType } from './types.mjs';
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ export { DownloadFileOptions, downloadFile } from './download-file.js';
4
4
  export { getAcceptAttrString } from './get-accept-attr.js';
5
5
  export { getFileDataUrl } from './get-file-data-url.js';
6
6
  export { getTotalFileSize } from './get-total-file-size.js';
7
- export { isFileEqual } from './is-file-equal.js';
7
+ export { getFileKey, isFileEqual } from './is-file-equal.js';
8
8
  export { isValidFileSize } from './is-valid-file-size.js';
9
- export { isValidFileType } from './is-valid-file-type.js';
9
+ export { createFileTypeValidator, isValidFileType } from './is-valid-file-type.js';
10
10
  export { getFileMimeType } from './get-file-mime-type.js';
11
11
  export { ApplicationFileMimeType, AudioFileMimeType, FileError, FileMimeType, FileMimeTypeGroup, FontFileMimeType, ImageFileMimeType, TextFileMimeType, VideoFileMimeType } from './types.js';
@@ -1,3 +1,4 @@
1
1
  declare const isFileEqual: (file1: File, file2: File) => boolean;
2
+ declare const getFileKey: (file: File) => string;
2
3
 
3
- export { isFileEqual };
4
+ export { getFileKey, isFileEqual };
@@ -1,3 +1,4 @@
1
1
  declare const isFileEqual: (file1: File, file2: File) => boolean;
2
+ declare const getFileKey: (file: File) => string;
2
3
 
3
- export { isFileEqual };
4
+ export { getFileKey, isFileEqual };
@@ -20,13 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/is-file-equal.ts
21
21
  var is_file_equal_exports = {};
22
22
  __export(is_file_equal_exports, {
23
+ getFileKey: () => getFileKey,
23
24
  isFileEqual: () => isFileEqual
24
25
  });
25
26
  module.exports = __toCommonJS(is_file_equal_exports);
26
27
  var isFileEqual = (file1, file2) => {
27
28
  return file1.name === file2.name && file1.size === file2.size && file1.type === file2.type;
28
29
  };
30
+ var getFileKey = (file) => {
31
+ return `${file.name}|${file.size}|${file.type}`;
32
+ };
29
33
  // Annotate the CommonJS export names for ESM import in node:
30
34
  0 && (module.exports = {
35
+ getFileKey,
31
36
  isFileEqual
32
37
  });
@@ -2,6 +2,10 @@
2
2
  var isFileEqual = (file1, file2) => {
3
3
  return file1.name === file2.name && file1.size === file2.size && file1.type === file2.type;
4
4
  };
5
+ var getFileKey = (file) => {
6
+ return `${file.name}|${file.size}|${file.type}`;
7
+ };
5
8
  export {
9
+ getFileKey,
6
10
  isFileEqual
7
11
  };
@@ -1,5 +1,9 @@
1
1
  import { FileError } from './types.mjs';
2
2
 
3
+ /**
4
+ * Parses `accept` once and returns a validator, so checking many files does not re-parse it per file.
5
+ */
6
+ declare function createFileTypeValidator(accept: string[] | string | undefined): (file: File) => [boolean, FileError | null];
3
7
  declare function isValidFileType(file: File, accept: string | undefined): [boolean, FileError | null];
4
8
 
5
- export { isValidFileType };
9
+ export { createFileTypeValidator, isValidFileType };
@@ -1,5 +1,9 @@
1
1
  import { FileError } from './types.js';
2
2
 
3
+ /**
4
+ * Parses `accept` once and returns a validator, so checking many files does not re-parse it per file.
5
+ */
6
+ declare function createFileTypeValidator(accept: string[] | string | undefined): (file: File) => [boolean, FileError | null];
3
7
  declare function isValidFileType(file: File, accept: string | undefined): [boolean, FileError | null];
4
8
 
5
- export { isValidFileType };
9
+ export { createFileTypeValidator, isValidFileType };
@@ -20,35 +20,50 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/is-valid-file-type.ts
21
21
  var is_valid_file_type_exports = {};
22
22
  __export(is_valid_file_type_exports, {
23
+ createFileTypeValidator: () => createFileTypeValidator,
23
24
  isValidFileType: () => isValidFileType
24
25
  });
25
26
  module.exports = __toCommonJS(is_valid_file_type_exports);
26
27
  var import_get_file_mime_type = require("./get-file-mime-type.js");
27
- function isFileAccepted(file, accept) {
28
- if (file && accept) {
29
- const types = Array.isArray(accept) ? accept : typeof accept === "string" ? accept.split(",") : [];
30
- if (types.length === 0) return true;
31
- const fileName = file.name || "";
32
- const mimeType = (file.type || (0, import_get_file_mime_type.getFileMimeType)(fileName) || "").toLowerCase();
33
- const baseMimeType = mimeType.replace(/\/.*$/, "");
34
- return types.some((type) => {
35
- const validType = type.trim().toLowerCase();
36
- if (validType.charAt(0) === ".") {
37
- return fileName.toLowerCase().endsWith(validType);
38
- }
39
- if (validType.endsWith("/*")) {
40
- return baseMimeType === validType.replace(/\/.*$/, "");
41
- }
42
- return mimeType === validType;
43
- });
28
+ function parseAccept(accept) {
29
+ if (!accept) return null;
30
+ const types = Array.isArray(accept) ? accept : accept.split(",");
31
+ const matchers = { extensions: [], baseMimes: [], mimes: [] };
32
+ for (const type of types) {
33
+ const validType = type.trim().toLowerCase();
34
+ if (validType.charAt(0) === ".") matchers.extensions.push(validType);
35
+ else if (validType.endsWith("/*")) matchers.baseMimes.push(validType.slice(0, validType.indexOf("/")));
36
+ else matchers.mimes.push(validType);
44
37
  }
45
- return true;
38
+ if (!matchers.extensions.length && !matchers.baseMimes.length && !matchers.mimes.length) return null;
39
+ return matchers;
40
+ }
41
+ function matches(matchers, file) {
42
+ const fileName = file.name || "";
43
+ const mimeType = (file.type || (0, import_get_file_mime_type.getFileMimeType)(fileName) || "").toLowerCase();
44
+ if (matchers.mimes.includes(mimeType)) return true;
45
+ if (matchers.baseMimes.length) {
46
+ const slash = mimeType.indexOf("/");
47
+ if (matchers.baseMimes.includes(slash === -1 ? mimeType : mimeType.slice(0, slash))) return true;
48
+ }
49
+ if (matchers.extensions.length) {
50
+ const lowerName = fileName.toLowerCase();
51
+ if (matchers.extensions.some((ext) => lowerName.endsWith(ext))) return true;
52
+ }
53
+ return false;
54
+ }
55
+ function createFileTypeValidator(accept) {
56
+ const matchers = parseAccept(accept);
57
+ return function isValidFileType2(file) {
58
+ const isAcceptable = file.type === "application/x-moz-file" || !matchers || matches(matchers, file);
59
+ return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
60
+ };
46
61
  }
47
62
  function isValidFileType(file, accept) {
48
- const isAcceptable = file.type === "application/x-moz-file" || isFileAccepted(file, accept);
49
- return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
63
+ return createFileTypeValidator(accept)(file);
50
64
  }
51
65
  // Annotate the CommonJS export names for ESM import in node:
52
66
  0 && (module.exports = {
67
+ createFileTypeValidator,
53
68
  isValidFileType
54
69
  });
@@ -1,29 +1,43 @@
1
1
  // src/is-valid-file-type.ts
2
2
  import { getFileMimeType } from "./get-file-mime-type.mjs";
3
- function isFileAccepted(file, accept) {
4
- if (file && accept) {
5
- const types = Array.isArray(accept) ? accept : typeof accept === "string" ? accept.split(",") : [];
6
- if (types.length === 0) return true;
7
- const fileName = file.name || "";
8
- const mimeType = (file.type || getFileMimeType(fileName) || "").toLowerCase();
9
- const baseMimeType = mimeType.replace(/\/.*$/, "");
10
- return types.some((type) => {
11
- const validType = type.trim().toLowerCase();
12
- if (validType.charAt(0) === ".") {
13
- return fileName.toLowerCase().endsWith(validType);
14
- }
15
- if (validType.endsWith("/*")) {
16
- return baseMimeType === validType.replace(/\/.*$/, "");
17
- }
18
- return mimeType === validType;
19
- });
3
+ function parseAccept(accept) {
4
+ if (!accept) return null;
5
+ const types = Array.isArray(accept) ? accept : accept.split(",");
6
+ const matchers = { extensions: [], baseMimes: [], mimes: [] };
7
+ for (const type of types) {
8
+ const validType = type.trim().toLowerCase();
9
+ if (validType.charAt(0) === ".") matchers.extensions.push(validType);
10
+ else if (validType.endsWith("/*")) matchers.baseMimes.push(validType.slice(0, validType.indexOf("/")));
11
+ else matchers.mimes.push(validType);
20
12
  }
21
- return true;
13
+ if (!matchers.extensions.length && !matchers.baseMimes.length && !matchers.mimes.length) return null;
14
+ return matchers;
15
+ }
16
+ function matches(matchers, file) {
17
+ const fileName = file.name || "";
18
+ const mimeType = (file.type || getFileMimeType(fileName) || "").toLowerCase();
19
+ if (matchers.mimes.includes(mimeType)) return true;
20
+ if (matchers.baseMimes.length) {
21
+ const slash = mimeType.indexOf("/");
22
+ if (matchers.baseMimes.includes(slash === -1 ? mimeType : mimeType.slice(0, slash))) return true;
23
+ }
24
+ if (matchers.extensions.length) {
25
+ const lowerName = fileName.toLowerCase();
26
+ if (matchers.extensions.some((ext) => lowerName.endsWith(ext))) return true;
27
+ }
28
+ return false;
29
+ }
30
+ function createFileTypeValidator(accept) {
31
+ const matchers = parseAccept(accept);
32
+ return function isValidFileType2(file) {
33
+ const isAcceptable = file.type === "application/x-moz-file" || !matchers || matches(matchers, file);
34
+ return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
35
+ };
22
36
  }
23
37
  function isValidFileType(file, accept) {
24
- const isAcceptable = file.type === "application/x-moz-file" || isFileAccepted(file, accept);
25
- return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
38
+ return createFileTypeValidator(accept)(file);
26
39
  }
27
40
  export {
41
+ createFileTypeValidator,
28
42
  isValidFileType
29
43
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/file-utils",
3
- "version": "2.0.0-next.2",
3
+ "version": "2.0.0-next.3",
4
4
  "description": "JS File API utilities",
5
5
  "keywords": [
6
6
  "js",
@@ -27,10 +27,11 @@
27
27
  },
28
28
  "clean-package": "../../../clean-package.config.json",
29
29
  "dependencies": {
30
- "@zag-js/i18n-utils": "2.0.0-next.2"
30
+ "@zag-js/i18n-utils": "2.0.0-next.3"
31
31
  },
32
32
  "devDependencies": {
33
- "clean-package": "2.2.0"
33
+ "clean-package": "2.2.0",
34
+ "vitest": "^4.1.2"
34
35
  },
35
36
  "module": "dist/index.mjs",
36
37
  "types": "dist/index.d.ts",
@@ -49,6 +50,7 @@
49
50
  },
50
51
  "scripts": {
51
52
  "build": "tsup",
53
+ "test": "vitest",
52
54
  "lint": "oxlint src",
53
55
  "typecheck": "tsc --noEmit",
54
56
  "mime": "node script/mime-types.mjs"