()
| 78 | // ── Phase 1: Pre-pack validation ─────────────────────────────────── |
| 79 | |
| 80 | function phase1_config() { |
| 81 | heading('Phase 1a: Package.json validation'); |
| 82 | |
| 83 | const pkg = readPkg(); |
| 84 | |
| 85 | // 1. files field exists |
| 86 | const files = pkg.files as string[] | undefined; |
| 87 | check('#1 `files` field exists', Array.isArray(files) && files.length > 0, |
| 88 | 'Add a "files" array to package.json to control what ships'); |
| 89 | |
| 90 | // 2. exports structure |
| 91 | const exports = pkg.exports as Record<string, Record<string, string>> | undefined; |
| 92 | check('#2 `exports["."]` defined', !!exports?.['.'], |
| 93 | 'Missing exports["."] in package.json'); |
| 94 | |
| 95 | if (exports?.['.']) { |
| 96 | check('#3 `exports["."].types` field exists', !!exports['.'].types, |
| 97 | 'Missing types condition in exports["."]'); |
| 98 | } else { |
| 99 | fail('#3 `exports["."].types` field exists', 'Skipped — no exports'); |
| 100 | } |
| 101 | |
| 102 | // 4. main field |
| 103 | const main = pkg.main as string | undefined; |
| 104 | check('#4 `main` field exists', !!main, |
| 105 | 'Missing "main" field in package.json'); |
| 106 | |
| 107 | // 5. types field |
| 108 | const types = pkg.types as string | undefined; |
| 109 | check('#5 `types` field exists', !!types, |
| 110 | 'Missing "types" field in package.json'); |
| 111 | |
| 112 | // 5c. bin map exposes a Windows-friendly alias (no dot in the name). |
| 113 | // The `design.md` bin file is unrunnable on Windows because the `.md` |
| 114 | // suffix collides with the Markdown file association, so PowerShell |
| 115 | // opens the shim in the user's Markdown editor instead of executing it. |
| 116 | // A dot-free alias such as `designmd` lets the npm CMD/PowerShell shims |
| 117 | // resolve cleanly via PATHEXT. See https://github.com/google-labs-code/design.md/issues/54. |
| 118 | const bin = pkg.bin as Record<string, string> | string | undefined; |
| 119 | const binEntries = typeof bin === 'object' && bin !== null ? Object.keys(bin) : []; |
| 120 | const hasDotFreeAlias = binEntries.some((name) => !name.includes('.')); |
| 121 | check('#5c bin map exposes a Windows-friendly alias (no dot in the name)', |
| 122 | hasDotFreeAlias, |
| 123 | `bin entries: ${binEntries.join(', ') || '(none)'} — add an alias without a dot for Windows compatibility`); |
| 124 | } |
| 125 | |
| 126 | function phase1_paths() { |
| 127 | heading('Phase 1b: Path resolution (post-build)'); |
no test coverage detected
searching dependent graphs…