gtin-checksum 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marius Pahomi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # gtin-checksum
2
+
3
+ [![npm version](https://img.shields.io/npm/v/gtin-checksum.svg)](https://www.npmjs.com/package/gtin-checksum)
4
+ [![license](https://img.shields.io/npm/l/gtin-checksum.svg)](./LICENSE)
5
+ [![types](https://img.shields.io/npm/types/gtin-checksum.svg)](./src/index.ts)
6
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/gtin-checksum)](https://bundlephobia.com/package/gtin-checksum)
7
+
8
+ > GS1 modulo-10 check-digit calculator and validator for **GTIN-8**, **GTIN-12 (UPC-A)**, **GTIN-13 (EAN-13)**, and **GTIN-14 (ITF-14)**. Zero runtime dependencies, TypeScript-native, ESM-only, tested against public GS1 / Wikipedia test vectors.
9
+
10
+ A correctly computed GTIN check digit is the difference between a product feed that lands in Google Merchant Center and one that gets rejected for "Invalid GTIN". This module exists because the algorithm is one short page in the [GS1 General Specifications](https://www.gs1.org/services/how-calculate-check-digit-manually) — but every e-commerce stack ends up re-implementing it, usually with a subtle bug at the weight-alternation step.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ npm install gtin-checksum
16
+ ```
17
+
18
+ Node 18+ · ESM-only · `~1 KB` minified.
19
+
20
+ ## Usage
21
+
22
+ ```ts
23
+ import {
24
+ computeCheckDigit,
25
+ isValidGtin,
26
+ appendCheckDigit,
27
+ gtinVariant,
28
+ } from 'gtin-checksum';
29
+
30
+ computeCheckDigit('400638133393'); // 1
31
+ appendCheckDigit('400638133393'); // '4006381333931'
32
+
33
+ isValidGtin('4006381333931'); // true (GTIN-13)
34
+ isValidGtin('036000291452'); // true (GTIN-12 / UPC-A)
35
+ isValidGtin('73513537'); // true (GTIN-8)
36
+ isValidGtin('00012345678905'); // true (GTIN-14 / ITF-14)
37
+ isValidGtin('4006381333932'); // false (wrong check digit)
38
+ isValidGtin('not-a-number'); // false (no throw — returns false)
39
+
40
+ gtinVariant('4006381333931'); // 13
41
+ gtinVariant('not-a-number'); // null
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### `computeCheckDigit(dataDigits: string): number`
47
+
48
+ Returns the GS1 modulo-10 check digit (0-9) for the given **data digits** — i.e. the GTIN **without** its trailing check digit. Throws `RangeError` on non-digit input or a length that is not one of 7, 11, 12, 13 (corresponding to GTIN-8/12/13/14).
49
+
50
+ ### `isValidGtin(gtin: string): boolean`
51
+
52
+ Returns `true` iff the input is a string of all digits whose length is 8, 12, 13, or 14, and whose trailing digit matches the computed check digit. **Never throws** — returns `false` for any malformed input.
53
+
54
+ ### `appendCheckDigit(dataDigits: string): string`
55
+
56
+ Convenience wrapper. Returns the full GTIN by appending the computed check digit to the input.
57
+
58
+ ### `gtinVariant(gtin: string): 8 | 12 | 13 | 14 | null`
59
+
60
+ Returns the GTIN length if it matches one of the four canonical variants; `null` otherwise. Does **not** verify the check digit — use `isValidGtin` for that.
61
+
62
+ ### `GTIN_LENGTHS`
63
+
64
+ Readonly tuple `[8, 12, 13, 14]` — the four canonical GTIN lengths.
65
+
66
+ ## Algorithm
67
+
68
+ Per [GS1 General Specifications §7.9](https://www.gs1.org/services/how-calculate-check-digit-manually):
69
+
70
+ 1. Starting at the **rightmost data digit** (i.e. the digit immediately to the left of the check digit position), multiply by **3**.
71
+ 2. Move left, alternating weights **1** and **3**.
72
+ 3. Sum the products.
73
+ 4. The check digit is `(10 - sum mod 10) mod 10` — i.e. the smallest non-negative value that makes the total a multiple of 10.
74
+
75
+ ### Worked example (GTIN-13: `4006381333931`)
76
+
77
+ | Position (from left) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
78
+ | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
79
+ | Digit | 4 | 0 | 0 | 6 | 3 | 8 | 1 | 3 | 3 | 3 | 9 | 3 | **1** (check) |
80
+ | Weight | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | — |
81
+ | Product | 4 | 0 | 0 | 18 | 3 | 24 | 1 | 9 | 3 | 9 | 9 | 9 | — |
82
+
83
+ Sum = 89 · `(10 − 89 mod 10) mod 10 = (10 − 9) mod 10 = 1` · check digit matches.
84
+
85
+ ## Why a separate package
86
+
87
+ Most e-commerce projects pull a 50 KB barcode library that drags in symbology renderers, image generators, and `canvas` peer-dependencies — just to validate a check digit. This module is the opposite: 4 exported functions, zero dependencies, types-first, and an explicit test suite against named public vectors so you can audit correctness without trusting opaque vendor code.
88
+
89
+ Built and maintained by [Marius Pahomi](https://www.feedarc.com/author/marius) at [FeedArc](https://www.feedarc.com) — where verifying GTINs at scale is a daily concern.
90
+
91
+ ## Development
92
+
93
+ ```sh
94
+ npm install
95
+ npm test # vitest, all test vectors
96
+ npm run build # emits dist/ with d.ts + sourcemaps
97
+ ```
98
+
99
+ ## Contributing
100
+
101
+ Bug reports and additional test vectors (especially edge cases — pseudo-GTINs, embedded weight/price codes, restricted ranges) are welcome via [GitHub Issues](https://github.com/marius103/gtin-checksum/issues).
102
+
103
+ ## License
104
+
105
+ [MIT](./LICENSE) © Marius Pahomi
@@ -0,0 +1,70 @@
1
+ /**
2
+ * GS1 modulo-10 check-digit utilities for GTIN-8, GTIN-12 (UPC-A),
3
+ * GTIN-13 (EAN-13), and GTIN-14 (ITF-14).
4
+ *
5
+ * Algorithm (per GS1 General Specifications §7.9):
6
+ *
7
+ * Starting at the rightmost data digit (position N-2, where N includes
8
+ * the check digit), multiply by 3. Move left, alternating weights 1
9
+ * and 3. Sum the products. The check digit is the value that, when
10
+ * added to the sum, produces a multiple of 10 — equivalently:
11
+ *
12
+ * checkDigit = (10 - (sum mod 10)) mod 10
13
+ *
14
+ * Public reference: https://www.gs1.org/services/how-calculate-check-digit-manually
15
+ *
16
+ * This implementation has zero runtime dependencies and treats all input
17
+ * strictly — non-digit characters and incorrect lengths throw early.
18
+ */
19
+ /** Valid GTIN total lengths (including the check digit). */
20
+ export declare const GTIN_LENGTHS: readonly [8, 12, 13, 14];
21
+ export type GtinLength = (typeof GTIN_LENGTHS)[number];
22
+ /**
23
+ * Compute the GS1 modulo-10 check digit for a string of data digits
24
+ * (i.e. the GTIN WITHOUT the trailing check digit).
25
+ *
26
+ * The data length must be 7, 11, 12, or 13 — producing a GTIN-8,
27
+ * GTIN-12, GTIN-13, or GTIN-14 respectively. Any other length throws.
28
+ *
29
+ * @param dataDigits GTIN without the trailing check digit.
30
+ * @returns The check digit as a single integer 0-9.
31
+ * @throws RangeError if the input contains non-digits or has an
32
+ * unsupported length.
33
+ *
34
+ * @example
35
+ * computeCheckDigit('400638133393'); // 1 → full GTIN-13: 4006381333931
36
+ * computeCheckDigit('03600029145'); // 2 → full GTIN-12: 036000291452
37
+ */
38
+ export declare function computeCheckDigit(dataDigits: string): number;
39
+ /**
40
+ * Validate a full GTIN by checking its embedded check digit against
41
+ * the GS1 modulo-10 algorithm.
42
+ *
43
+ * @param gtin Full GTIN string (8, 12, 13, or 14 digits).
44
+ * @returns true iff the string is a syntactically valid GTIN with a
45
+ * matching check digit. Returns false for any malformed input — does
46
+ * not throw.
47
+ *
48
+ * @example
49
+ * isValidGtin('4006381333931'); // true
50
+ * isValidGtin('4006381333932'); // false (wrong check digit)
51
+ * isValidGtin('not-a-number'); // false
52
+ */
53
+ export declare function isValidGtin(gtin: string): boolean;
54
+ /**
55
+ * Append the correct check digit to a string of data digits, returning
56
+ * the full GTIN. Convenience wrapper around `computeCheckDigit`.
57
+ *
58
+ * @param dataDigits GTIN without the trailing check digit.
59
+ * @returns Full GTIN string (one digit longer than the input).
60
+ *
61
+ * @example
62
+ * appendCheckDigit('400638133393'); // '4006381333931'
63
+ */
64
+ export declare function appendCheckDigit(dataDigits: string): string;
65
+ /**
66
+ * Infer the GTIN variant from a full GTIN's length. Returns null if the
67
+ * length is not a valid GTIN length.
68
+ */
69
+ export declare function gtinVariant(gtin: string): GtinLength | null;
70
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,YAAY,0BAA2B,CAAC;AACrD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAyB5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAK3D"}
package/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * GS1 modulo-10 check-digit utilities for GTIN-8, GTIN-12 (UPC-A),
3
+ * GTIN-13 (EAN-13), and GTIN-14 (ITF-14).
4
+ *
5
+ * Algorithm (per GS1 General Specifications §7.9):
6
+ *
7
+ * Starting at the rightmost data digit (position N-2, where N includes
8
+ * the check digit), multiply by 3. Move left, alternating weights 1
9
+ * and 3. Sum the products. The check digit is the value that, when
10
+ * added to the sum, produces a multiple of 10 — equivalently:
11
+ *
12
+ * checkDigit = (10 - (sum mod 10)) mod 10
13
+ *
14
+ * Public reference: https://www.gs1.org/services/how-calculate-check-digit-manually
15
+ *
16
+ * This implementation has zero runtime dependencies and treats all input
17
+ * strictly — non-digit characters and incorrect lengths throw early.
18
+ */
19
+ /** Valid GTIN total lengths (including the check digit). */
20
+ export const GTIN_LENGTHS = [8, 12, 13, 14];
21
+ /**
22
+ * Compute the GS1 modulo-10 check digit for a string of data digits
23
+ * (i.e. the GTIN WITHOUT the trailing check digit).
24
+ *
25
+ * The data length must be 7, 11, 12, or 13 — producing a GTIN-8,
26
+ * GTIN-12, GTIN-13, or GTIN-14 respectively. Any other length throws.
27
+ *
28
+ * @param dataDigits GTIN without the trailing check digit.
29
+ * @returns The check digit as a single integer 0-9.
30
+ * @throws RangeError if the input contains non-digits or has an
31
+ * unsupported length.
32
+ *
33
+ * @example
34
+ * computeCheckDigit('400638133393'); // 1 → full GTIN-13: 4006381333931
35
+ * computeCheckDigit('03600029145'); // 2 → full GTIN-12: 036000291452
36
+ */
37
+ export function computeCheckDigit(dataDigits) {
38
+ if (typeof dataDigits !== 'string') {
39
+ throw new TypeError('dataDigits must be a string');
40
+ }
41
+ if (!/^\d+$/.test(dataDigits)) {
42
+ throw new RangeError(`dataDigits must contain only ASCII digits 0-9 (got: ${JSON.stringify(dataDigits)})`);
43
+ }
44
+ const validDataLengths = GTIN_LENGTHS.map((n) => n - 1);
45
+ if (!validDataLengths.includes(dataDigits.length)) {
46
+ throw new RangeError(`dataDigits length must be one of ${validDataLengths.join(', ')} ` +
47
+ `(for GTIN-${GTIN_LENGTHS.join('/')}); got ${dataDigits.length}`);
48
+ }
49
+ // Walk right-to-left. Rightmost data digit gets weight 3, next 1,
50
+ // then 3, then 1, etc.
51
+ let sum = 0;
52
+ for (let i = 0; i < dataDigits.length; i++) {
53
+ const digit = dataDigits.charCodeAt(dataDigits.length - 1 - i) - 48;
54
+ const weight = i % 2 === 0 ? 3 : 1;
55
+ sum += digit * weight;
56
+ }
57
+ return (10 - (sum % 10)) % 10;
58
+ }
59
+ /**
60
+ * Validate a full GTIN by checking its embedded check digit against
61
+ * the GS1 modulo-10 algorithm.
62
+ *
63
+ * @param gtin Full GTIN string (8, 12, 13, or 14 digits).
64
+ * @returns true iff the string is a syntactically valid GTIN with a
65
+ * matching check digit. Returns false for any malformed input — does
66
+ * not throw.
67
+ *
68
+ * @example
69
+ * isValidGtin('4006381333931'); // true
70
+ * isValidGtin('4006381333932'); // false (wrong check digit)
71
+ * isValidGtin('not-a-number'); // false
72
+ */
73
+ export function isValidGtin(gtin) {
74
+ if (typeof gtin !== 'string')
75
+ return false;
76
+ if (!/^\d+$/.test(gtin))
77
+ return false;
78
+ if (!GTIN_LENGTHS.includes(gtin.length))
79
+ return false;
80
+ const data = gtin.slice(0, -1);
81
+ const expected = computeCheckDigit(data);
82
+ const actual = gtin.charCodeAt(gtin.length - 1) - 48;
83
+ return expected === actual;
84
+ }
85
+ /**
86
+ * Append the correct check digit to a string of data digits, returning
87
+ * the full GTIN. Convenience wrapper around `computeCheckDigit`.
88
+ *
89
+ * @param dataDigits GTIN without the trailing check digit.
90
+ * @returns Full GTIN string (one digit longer than the input).
91
+ *
92
+ * @example
93
+ * appendCheckDigit('400638133393'); // '4006381333931'
94
+ */
95
+ export function appendCheckDigit(dataDigits) {
96
+ return `${dataDigits}${computeCheckDigit(dataDigits)}`;
97
+ }
98
+ /**
99
+ * Infer the GTIN variant from a full GTIN's length. Returns null if the
100
+ * length is not a valid GTIN length.
101
+ */
102
+ export function gtinVariant(gtin) {
103
+ const n = gtin.length;
104
+ return GTIN_LENGTHS.includes(n)
105
+ ? n
106
+ : null;
107
+ }
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAU,CAAC;AAGrD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAClB,uDAAuD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CACrF,CAAC;IACJ,CAAC;IACD,MAAM,gBAAgB,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,UAAU,CAClB,oCAAoC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAChE,aAAa,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,UAAU,CAAC,MAAM,EAAE,CACnE,CAAC;IACJ,CAAC;IACD,kEAAkE;IAClE,uBAAuB;IACvB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,GAAG,IAAI,KAAK,GAAG,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,CAAE,YAAkC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACrD,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,GAAG,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,OAAQ,YAAkC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpD,CAAC,CAAE,CAAgB;QACnB,CAAC,CAAC,IAAI,CAAC;AACX,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "gtin-checksum",
3
+ "version": "1.0.0",
4
+ "description": "GS1 modulo-10 check-digit calculator and validator for GTIN-8, GTIN-12 (UPC-A), GTIN-13 (EAN-13), and GTIN-14 (ITF-14). Zero dependencies, TypeScript-native, tested against official GS1 test vectors.",
5
+ "keywords": [
6
+ "gtin",
7
+ "gtin-8",
8
+ "gtin-12",
9
+ "gtin-13",
10
+ "gtin-14",
11
+ "upc",
12
+ "upc-a",
13
+ "ean",
14
+ "ean-13",
15
+ "ean-8",
16
+ "itf-14",
17
+ "gs1",
18
+ "check-digit",
19
+ "checksum",
20
+ "modulo-10",
21
+ "barcode",
22
+ "product-feed",
23
+ "ecommerce"
24
+ ],
25
+ "homepage": "https://github.com/marius103/gtin-checksum#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/marius103/gtin-checksum/issues"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/marius103/gtin-checksum.git"
32
+ },
33
+ "license": "MIT",
34
+ "author": {
35
+ "name": "Marius Pahomi",
36
+ "url": "https://www.feedarc.com/author/marius"
37
+ },
38
+ "type": "module",
39
+ "main": "./dist/index.js",
40
+ "types": "./dist/index.d.ts",
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/index.d.ts",
44
+ "import": "./dist/index.js"
45
+ }
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md",
50
+ "LICENSE"
51
+ ],
52
+ "scripts": {
53
+ "build": "tsc -p tsconfig.build.json",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest",
56
+ "prepublishOnly": "npm test && npm run build"
57
+ },
58
+ "devDependencies": {
59
+ "typescript": "^5.6.0",
60
+ "vitest": "^2.1.0"
61
+ },
62
+ "engines": {
63
+ "node": ">=18"
64
+ },
65
+ "publishConfig": {
66
+ "access": "public"
67
+ }
68
+ }