@designesy/score 0.5.0 → 0.5.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/README.md +110 -110
- package/dist/cli.js +28 -26
- package/dist/engine.js +7 -6
- package/package.json +55 -55
package/README.md
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
# @designesy/score
|
|
2
|
-
|
|
3
|
-
Standalone 42-check design-contract scoring engine. Fetches a URL, extracts CSS + `:root` tokens, runs all checks locally, with **no server required**. Zero dependencies.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install --save-dev @designesy/score
|
|
9
|
-
# or
|
|
10
|
-
npx @designesy/score <url>
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## CLI
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
# Score a site (prints formatted report)
|
|
17
|
-
npx @designesy/score designesy.org
|
|
18
|
-
|
|
19
|
-
# CI gate: fail if below threshold
|
|
20
|
-
npx @designesy/score linear.app --min-score 70 --min-grade B
|
|
21
|
-
|
|
22
|
-
# JSON output for pipelines
|
|
23
|
-
npx @designesy/score vercel.com --json
|
|
24
|
-
|
|
25
|
-
# Markdown review format (jakubkrehel-compatible)
|
|
26
|
-
npx @designesy/score stripe.com --format review
|
|
27
|
-
|
|
28
|
-
# Scoring scope: contract (strict, all checks penalize absence) or universal (fair to external sites)
|
|
29
|
-
npx @designesy/score designesy.org --scope contract
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Options
|
|
33
|
-
|
|
34
|
-
| Flag | Description |
|
|
35
|
-
|---|---|
|
|
36
|
-
| `--format <f>` | Emission format: `designesy` (default), `canonical`, `review`, `google` |
|
|
37
|
-
| `--scope <s>` | Scoring scope: `contract` (strict) or `universal` (fair, default auto-detect) |
|
|
38
|
-
| `--min-score <n>` | Exit 1 if score < n |
|
|
39
|
-
| `--min-grade <g>` | Exit 1 if grade worse than g (A/B/C/D/F) |
|
|
40
|
-
| `--json` | Output raw JSON (no formatted report) |
|
|
41
|
-
| `--quiet` | Only output on failure (CI noise reduction) |
|
|
42
|
-
| `--help, -h` | Show help |
|
|
43
|
-
|
|
44
|
-
## Library
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
import { scoreUrl } from '@designesy/score';
|
|
48
|
-
|
|
49
|
-
const result = await scoreUrl('https://linear.app');
|
|
50
|
-
console.log(result.score); // 72.5
|
|
51
|
-
console.log(result.grade); // 'C'
|
|
52
|
-
console.log(result.pass); // 28
|
|
53
|
-
console.log(result.fail); // 3
|
|
54
|
-
console.log(result.checks); // [{ id: 'v01', status: 'PASS', detail: '...' }, ...]
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## The 42 checks
|
|
58
|
-
|
|
59
|
-
| Category | Checks | Weight |
|
|
60
|
-
|---|---|---|
|
|
61
|
-
| cadence | v14, v15, v16, v17, v18, v19, v20, v26, v28, x01, x02, x03 | 18 |
|
|
62
|
-
| accessibility | v06, v22, v24, v25, v27, v35 | 15 |
|
|
63
|
-
| semantic | v42, v43 | 12 |
|
|
64
|
-
| motion | v05, v11, v12, v23 | 10 |
|
|
65
|
-
| tokens | v01, v29 | 9 |
|
|
66
|
-
| takt | v10, v13 | 8 |
|
|
67
|
-
| copywriting | v38, v39, v40, v41 | 8 |
|
|
68
|
-
| poise | v04, v08, v09 | 7 |
|
|
69
|
-
| identity | v07, v34 | 6 |
|
|
70
|
-
| interaction | v03 | 6 |
|
|
71
|
-
| performance | v21 | 6 |
|
|
72
|
-
| security | v36 | 5 |
|
|
73
|
-
| spec | v37 | 4 |
|
|
74
|
-
| responsive | v02 | 3 |
|
|
75
|
-
|
|
76
|
-
Plus 12 anti-slop deductions (S1 to S12) and 7 originality lifts (O1 to O7).
|
|
77
|
-
|
|
78
|
-
## Scoring
|
|
79
|
-
|
|
80
|
-
- Weighted per-category scoring (PASS = 1.0, WARN = 0.5, FAIL = 0, SKIP/MANUAL excluded)
|
|
81
|
-
- Anti-slop deductions (up to -20pts for generic AI patterns)
|
|
82
|
-
- Originality lifts (up to +8pts for bespoke craft signals)
|
|
83
|
-
- Accessibility floor (score capped at C/70 when any a11y FAIL exists)
|
|
84
|
-
- Hard-fail ceilings (critical issues cap the score further)
|
|
85
|
-
|
|
86
|
-
## Scope system
|
|
87
|
-
|
|
88
|
-
- **contract** (default for designesy.org): All 42 checks active. Absence = WARN/FAIL.
|
|
89
|
-
- **universal** (default for external sites): Optional features SKIP on absence instead of penalizing.
|
|
90
|
-
|
|
91
|
-
Auto-detect: `designesy.org` → contract, everything else → universal.
|
|
92
|
-
|
|
93
|
-
## Zero dependencies
|
|
94
|
-
|
|
95
|
-
Uses only Node.js built-ins:
|
|
96
|
-
- `node:https` for URL fetching (avoids the Windows libuv/undici crash)
|
|
97
|
-
- `node:dns` for SSRF guard (DNS resolution validation)
|
|
98
|
-
- No `ipaddr.js`, no `undici`, no `fetch()`, no external packages
|
|
99
|
-
|
|
100
|
-
## SSRF guard
|
|
101
|
-
|
|
102
|
-
Built-in SSRF protection rejects:
|
|
103
|
-
- Private IP ranges (10.x, 127.x, 169.254.x, 172.16-31.x, 192.168.x)
|
|
104
|
-
- Cloud metadata endpoints (169.254.169.254)
|
|
105
|
-
- All IPv6 addresses
|
|
106
|
-
- Encoded IP bypasses (decimal, octal, hex)
|
|
107
|
-
- Redirect chains to internal addresses
|
|
108
|
-
|
|
109
|
-
## License
|
|
110
|
-
|
|
1
|
+
# @designesy/score
|
|
2
|
+
|
|
3
|
+
Standalone 42-check design-contract scoring engine. Fetches a URL, extracts CSS + `:root` tokens, runs all checks locally, with **no server required**. Zero dependencies.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @designesy/score
|
|
9
|
+
# or
|
|
10
|
+
npx @designesy/score <url>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## CLI
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Score a site (prints formatted report)
|
|
17
|
+
npx @designesy/score designesy.org
|
|
18
|
+
|
|
19
|
+
# CI gate: fail if below threshold
|
|
20
|
+
npx @designesy/score linear.app --min-score 70 --min-grade B
|
|
21
|
+
|
|
22
|
+
# JSON output for pipelines
|
|
23
|
+
npx @designesy/score vercel.com --json
|
|
24
|
+
|
|
25
|
+
# Markdown review format (jakubkrehel-compatible)
|
|
26
|
+
npx @designesy/score stripe.com --format review
|
|
27
|
+
|
|
28
|
+
# Scoring scope: contract (strict, all checks penalize absence) or universal (fair to external sites)
|
|
29
|
+
npx @designesy/score designesy.org --scope contract
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Options
|
|
33
|
+
|
|
34
|
+
| Flag | Description |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `--format <f>` | Emission format: `designesy` (default), `canonical`, `review`, `google` |
|
|
37
|
+
| `--scope <s>` | Scoring scope: `contract` (strict) or `universal` (fair, default auto-detect) |
|
|
38
|
+
| `--min-score <n>` | Exit 1 if score < n |
|
|
39
|
+
| `--min-grade <g>` | Exit 1 if grade worse than g (A/B/C/D/F) |
|
|
40
|
+
| `--json` | Output raw JSON (no formatted report) |
|
|
41
|
+
| `--quiet` | Only output on failure (CI noise reduction) |
|
|
42
|
+
| `--help, -h` | Show help |
|
|
43
|
+
|
|
44
|
+
## Library
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { scoreUrl } from '@designesy/score';
|
|
48
|
+
|
|
49
|
+
const result = await scoreUrl('https://linear.app');
|
|
50
|
+
console.log(result.score); // 72.5
|
|
51
|
+
console.log(result.grade); // 'C'
|
|
52
|
+
console.log(result.pass); // 28
|
|
53
|
+
console.log(result.fail); // 3
|
|
54
|
+
console.log(result.checks); // [{ id: 'v01', status: 'PASS', detail: '...' }, ...]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## The 42 checks
|
|
58
|
+
|
|
59
|
+
| Category | Checks | Weight |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| cadence | v14, v15, v16, v17, v18, v19, v20, v26, v28, x01, x02, x03 | 18 |
|
|
62
|
+
| accessibility | v06, v22, v24, v25, v27, v35 | 15 |
|
|
63
|
+
| semantic | v42, v43 | 12 |
|
|
64
|
+
| motion | v05, v11, v12, v23 | 10 |
|
|
65
|
+
| tokens | v01, v29 | 9 |
|
|
66
|
+
| takt | v10, v13 | 8 |
|
|
67
|
+
| copywriting | v38, v39, v40, v41 | 8 |
|
|
68
|
+
| poise | v04, v08, v09 | 7 |
|
|
69
|
+
| identity | v07, v34 | 6 |
|
|
70
|
+
| interaction | v03 | 6 |
|
|
71
|
+
| performance | v21 | 6 |
|
|
72
|
+
| security | v36 | 5 |
|
|
73
|
+
| spec | v37 | 4 |
|
|
74
|
+
| responsive | v02 | 3 |
|
|
75
|
+
|
|
76
|
+
Plus 12 anti-slop deductions (S1 to S12) and 7 originality lifts (O1 to O7).
|
|
77
|
+
|
|
78
|
+
## Scoring
|
|
79
|
+
|
|
80
|
+
- Weighted per-category scoring (PASS = 1.0, WARN = 0.5, FAIL = 0, SKIP/MANUAL excluded)
|
|
81
|
+
- Anti-slop deductions (up to -20pts for generic AI patterns)
|
|
82
|
+
- Originality lifts (up to +8pts for bespoke craft signals)
|
|
83
|
+
- Accessibility floor (score capped at C/70 when any a11y FAIL exists)
|
|
84
|
+
- Hard-fail ceilings (critical issues cap the score further)
|
|
85
|
+
|
|
86
|
+
## Scope system
|
|
87
|
+
|
|
88
|
+
- **contract** (default for designesy.org): All 42 checks active. Absence = WARN/FAIL.
|
|
89
|
+
- **universal** (default for external sites): Optional features SKIP on absence instead of penalizing.
|
|
90
|
+
|
|
91
|
+
Auto-detect: `designesy.org` → contract, everything else → universal.
|
|
92
|
+
|
|
93
|
+
## Zero dependencies
|
|
94
|
+
|
|
95
|
+
Uses only Node.js built-ins:
|
|
96
|
+
- `node:https` for URL fetching (avoids the Windows libuv/undici crash)
|
|
97
|
+
- `node:dns` for SSRF guard (DNS resolution validation)
|
|
98
|
+
- No `ipaddr.js`, no `undici`, no `fetch()`, no external packages
|
|
99
|
+
|
|
100
|
+
## SSRF guard
|
|
101
|
+
|
|
102
|
+
Built-in SSRF protection rejects:
|
|
103
|
+
- Private IP ranges (10.x, 127.x, 169.254.x, 172.16-31.x, 192.168.x)
|
|
104
|
+
- Cloud metadata endpoints (169.254.169.254)
|
|
105
|
+
- All IPv6 addresses
|
|
106
|
+
- Encoded IP bypasses (decimal, octal, hex)
|
|
107
|
+
- Redirect chains to internal addresses
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
111
|
MIT © [Designesy](https://www.designesy.org)
|
package/dist/cli.js
CHANGED
|
@@ -97,29 +97,29 @@ function formatReport(result, url) {
|
|
|
97
97
|
return lines.join('\n');
|
|
98
98
|
}
|
|
99
99
|
function printUsage() {
|
|
100
|
-
console.log(`
|
|
101
|
-
designesy-score: Score a URL against the 42-check Designesy engine.
|
|
102
|
-
|
|
103
|
-
Runs locally: no server required. Fetches the URL, extracts CSS + tokens,
|
|
104
|
-
and runs all 42 checks in one process.
|
|
105
|
-
|
|
106
|
-
Usage:
|
|
107
|
-
designesy-score <url> [options]
|
|
108
|
-
|
|
109
|
-
Options:
|
|
110
|
-
--format <f> Emission format: designesy (default), canonical, review, google
|
|
111
|
-
--scope <s> Scoring scope: contract (strict) or universal (fair, default auto)
|
|
112
|
-
--min-score <n> Exit 1 if score < n (default: 0 = disabled)
|
|
113
|
-
--min-grade <g> Exit 1 if grade worse than g (A/B/C/D/F, default: disabled)
|
|
114
|
-
--json Output raw JSON (no formatted report)
|
|
115
|
-
--quiet Only output on failure
|
|
116
|
-
--help, -h Show this help
|
|
117
|
-
|
|
118
|
-
Examples:
|
|
119
|
-
designesy-score designesy.org
|
|
120
|
-
designesy-score linear.app --min-score 70 --min-grade B
|
|
121
|
-
designesy-score vercel.com --format canonical --json
|
|
122
|
-
designesy-score stripe.com --format review
|
|
100
|
+
console.log(`
|
|
101
|
+
designesy-score: Score a URL against the 42-check Designesy engine.
|
|
102
|
+
|
|
103
|
+
Runs locally: no server required. Fetches the URL, extracts CSS + tokens,
|
|
104
|
+
and runs all 42 checks in one process.
|
|
105
|
+
|
|
106
|
+
Usage:
|
|
107
|
+
designesy-score <url> [options]
|
|
108
|
+
|
|
109
|
+
Options:
|
|
110
|
+
--format <f> Emission format: designesy (default), canonical, review, google
|
|
111
|
+
--scope <s> Scoring scope: contract (strict) or universal (fair, default auto)
|
|
112
|
+
--min-score <n> Exit 1 if score < n (default: 0 = disabled)
|
|
113
|
+
--min-grade <g> Exit 1 if grade worse than g (A/B/C/D/F, default: disabled)
|
|
114
|
+
--json Output raw JSON (no formatted report)
|
|
115
|
+
--quiet Only output on failure
|
|
116
|
+
--help, -h Show this help
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
designesy-score designesy.org
|
|
120
|
+
designesy-score linear.app --min-score 70 --min-grade B
|
|
121
|
+
designesy-score vercel.com --format canonical --json
|
|
122
|
+
designesy-score stripe.com --format review
|
|
123
123
|
`);
|
|
124
124
|
}
|
|
125
125
|
function parseArgs(argv) {
|
|
@@ -189,8 +189,10 @@ async function main() {
|
|
|
189
189
|
let scope;
|
|
190
190
|
if (args.scope === 'contract' || args.scope === 'universal')
|
|
191
191
|
scope = args.scope;
|
|
192
|
+
// Progress and the gate verdict go to stderr: stdout carries only the
|
|
193
|
+
// result, so --json and the JSON formats pipe straight into a parser.
|
|
192
194
|
if (!args.quiet) {
|
|
193
|
-
console.
|
|
195
|
+
console.error(`${DIM}Scoring ${url} locally (42-check engine, scope=${scope || 'auto'})…${RESET}`);
|
|
194
196
|
}
|
|
195
197
|
let result;
|
|
196
198
|
try {
|
|
@@ -238,7 +240,7 @@ async function main() {
|
|
|
238
240
|
// gate, and it must not be compared against a floor — there is no measurement
|
|
239
241
|
// to compare. This is the exit-code consequence of the unreachable state.
|
|
240
242
|
if (score === null || grade === null) {
|
|
241
|
-
console.error(`
|
|
243
|
+
console.error(`
|
|
242
244
|
${BOLD}Quality gate failed${RESET}: ${result.unreachableDetail ?? 'the target could not be read'}`);
|
|
243
245
|
process.exit(1);
|
|
244
246
|
}
|
|
@@ -251,7 +253,7 @@ ${BOLD}Quality gate failed${RESET}: ${result.unreachableDetail ?? 'the target co
|
|
|
251
253
|
process.exit(1);
|
|
252
254
|
}
|
|
253
255
|
if (!args.quiet) {
|
|
254
|
-
console.
|
|
256
|
+
console.error(`\n${BOLD}Quality gate passed${RESET}`);
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
259
|
main().catch((e) => {
|
package/dist/engine.js
CHANGED
|
@@ -2035,13 +2035,14 @@ async function checkDesignMdSpec(targetUrl) {
|
|
|
2035
2035
|
lintDesignMd = mod.lint;
|
|
2036
2036
|
}
|
|
2037
2037
|
catch (e) {
|
|
2038
|
-
//
|
|
2039
|
-
// PASS
|
|
2040
|
-
//
|
|
2041
|
-
//
|
|
2042
|
-
//
|
|
2038
|
+
// MANUAL, not PASS and not WARN. The file was fetched but NOTHING validated
|
|
2039
|
+
// it: PASS would assert validation that never happened (the false-PASS
|
|
2040
|
+
// class of the all-SKIP review verdict). WARN charged the scored site for a
|
|
2041
|
+
// package missing from THIS runtime, so the same page scored lower from the
|
|
2042
|
+
// npm CLI than from the API. Unverified-here is what MANUAL means (v02,
|
|
2043
|
+
// v04, v21): weight 0, resolved by a run that has the linter.
|
|
2043
2044
|
const msg = e instanceof Error ? e.message : 'unknown error';
|
|
2044
|
-
return { id: 'v37', item: ITEM, category: CATEGORY, status: '
|
|
2045
|
+
return { id: 'v37', item: ITEM, category: CATEGORY, status: 'MANUAL', detail: `/DESIGN.md fetched but linter unavailable: ${msg}. The @google/design.md package may not be installed in this runtime; run the full audit to resolve.` };
|
|
2045
2046
|
}
|
|
2046
2047
|
try {
|
|
2047
2048
|
const report = lintDesignMd(r.text);
|
package/package.json
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@designesy/score",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Standalone 42-check design-contract scoring engine: fetches a URL, extracts CSS + tokens, and runs all checks locally. Zero dependencies.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Designesy <hello@designesy.org>",
|
|
7
|
-
"homepage": "https://www.designesy.org/score",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/LE-VAI/designesy-org.git",
|
|
11
|
-
"directory": "packages/score"
|
|
12
|
-
},
|
|
13
|
-
"bugs": {
|
|
14
|
-
"url": "https://github.com/LE-VAI/designesy-org/issues"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"design-system",
|
|
18
|
-
"design-contract",
|
|
19
|
-
"design-verification",
|
|
20
|
-
"accessibility",
|
|
21
|
-
"wcag",
|
|
22
|
-
"core-web-vitals",
|
|
23
|
-
"ci",
|
|
24
|
-
"quality-gate",
|
|
25
|
-
"designesy"
|
|
26
|
-
],
|
|
27
|
-
"type": "module",
|
|
28
|
-
"exports": {
|
|
29
|
-
".": {
|
|
30
|
-
"import": "./dist/engine.js",
|
|
31
|
-
"types": "./dist/engine.d.ts"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"main": "./dist/engine.js",
|
|
35
|
-
"types": "./dist/engine.d.ts",
|
|
36
|
-
"bin": {
|
|
37
|
-
"designesy-score": "dist/cli.js"
|
|
38
|
-
},
|
|
39
|
-
"files": [
|
|
40
|
-
"dist",
|
|
41
|
-
"README.md"
|
|
42
|
-
],
|
|
43
|
-
"engines": {
|
|
44
|
-
"node": ">=18.0.0"
|
|
45
|
-
},
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@types/node": "^26.2.0",
|
|
48
|
-
"typescript": "^5.7.0"
|
|
49
|
-
},
|
|
50
|
-
"scripts": {
|
|
51
|
-
"build": "tsc -p tsconfig.json",
|
|
52
|
-
"test": "node --test",
|
|
53
|
-
"prepublishOnly": "npm run build"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@designesy/score",
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Standalone 42-check design-contract scoring engine: fetches a URL, extracts CSS + tokens, and runs all checks locally. Zero dependencies.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Designesy <hello@designesy.org>",
|
|
7
|
+
"homepage": "https://www.designesy.org/score",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/LE-VAI/designesy-org.git",
|
|
11
|
+
"directory": "packages/score"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/LE-VAI/designesy-org/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"design-system",
|
|
18
|
+
"design-contract",
|
|
19
|
+
"design-verification",
|
|
20
|
+
"accessibility",
|
|
21
|
+
"wcag",
|
|
22
|
+
"core-web-vitals",
|
|
23
|
+
"ci",
|
|
24
|
+
"quality-gate",
|
|
25
|
+
"designesy"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": "./dist/engine.js",
|
|
31
|
+
"types": "./dist/engine.d.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"main": "./dist/engine.js",
|
|
35
|
+
"types": "./dist/engine.d.ts",
|
|
36
|
+
"bin": {
|
|
37
|
+
"designesy-score": "dist/cli.js"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^26.2.0",
|
|
48
|
+
"typescript": "^5.7.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc -p tsconfig.json",
|
|
52
|
+
"test": "node --test",
|
|
53
|
+
"prepublishOnly": "npm run build"
|
|
54
|
+
}
|
|
55
|
+
}
|