itty-packager 1.0.7 → 1.0.9

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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(bun bin/itty.js lint:*)"
5
+ ],
6
+ "deny": []
7
+ }
8
+ }
package/CLAUDE.md ADDED
@@ -0,0 +1,77 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Commands
6
+
7
+ ### Development Commands
8
+ - `bun bin/itty.js lint` - Lint the codebase using the CLI tool itself
9
+ - `bun bin/itty.js build` - Build the project (not typically needed as this is the build tool itself)
10
+ - `echo 'No tests yet'` - Current test command (no test suite implemented)
11
+
12
+ ### Release Commands
13
+ - `bun bin/itty.js publish --patch --tag --dry-run --src=. --no-license` - Dry run release
14
+ - `bun bin/itty.js publish --patch --tag --push --src=. --no-license` - Patch release (quiet by default)
15
+ - `bun bin/itty.js publish --minor --tag --push --src=. --no-license` - Minor release
16
+ - `bun bin/itty.js publish --major --tag --push --src=. --no-license` - Major release
17
+ - Add `--verbose` flag to any command for detailed output including npm and git details
18
+
19
+ ### CLI Usage
20
+ The main CLI entry point is `bin/itty.js` which provides three core commands:
21
+ - `itty build` - TypeScript compilation with Rollup
22
+ - `itty lint` - ESLint with built-in TypeScript configuration
23
+ - `itty publish` - Version bumping and npm publishing
24
+
25
+ ## Architecture
26
+
27
+ ### Core Components
28
+
29
+ **CLI Entry Point** (`bin/itty.js`):
30
+ - Main executable that dynamically imports command modules
31
+ - Handles global flags (--help, --version) and subcommand routing
32
+ - Supports build, lint, and publish subcommands
33
+
34
+ **Build System** (`lib/builder.js`):
35
+ - Core build logic using Rollup and TypeScript
36
+ - Handles ESM/CJS hybrid builds, minification with terser, sourcemaps
37
+ - Automatically updates package.json exports based on build outputs
38
+ - Supports snippet generation for README injection
39
+ - Single file exports map to root export, multiple files get individual exports
40
+
41
+ **Command Modules** (`lib/commands/`):
42
+ - **build.js**: Wraps builder.js with CLI argument parsing
43
+ - **lint.js**: ESLint integration with smart config detection
44
+ - **publish.js**: Version bumping, package extraction, and npm publishing
45
+
46
+ **ESLint Configuration** (`lib/configs/`):
47
+ - **createConfig.mjs**: Factory function for extending base TypeScript ESLint config
48
+ - **eslint.config.mjs**: Base configuration with TypeScript support
49
+ - Automatically used when no local ESLint config is found
50
+
51
+ ### Key Architectural Patterns
52
+
53
+ **Dynamic Command Loading**: Commands are lazily loaded to improve startup time and allow future extensibility.
54
+
55
+ **Smart Configuration**: The lint command detects local ESLint configs and falls back to built-in TypeScript configuration when none exists.
56
+
57
+ **Clean Package Publishing**: The publish command creates a flat package structure by extracting build artifacts to a temporary directory, copying essential files (README, LICENSE, CHANGELOG), and transforming package.json paths before publishing.
58
+
59
+ **Extensible ESLint**: Projects can extend the built-in config using `createConfig()` from `itty-packager/lib/configs/createConfig.mjs`.
60
+
61
+ ### Build Output Handling
62
+
63
+ The build system automatically manages package.json exports:
64
+ - Single TypeScript file → root export (`"."`)
65
+ - Multiple TypeScript files → individual named exports
66
+ - Paths are automatically updated to point to dist/ directory
67
+ - ESM builds by default, CJS optional with `--hybrid` flag
68
+
69
+ ### Publishing Workflow
70
+
71
+ The publish command transforms the package structure:
72
+ 1. Extracts build artifacts from dist/ to temporary directory
73
+ 2. Copies root files (README.md, LICENSE, .npmrc)
74
+ 3. Transforms package.json paths (e.g., `./dist/file.mjs` → `./file.mjs`)
75
+ 4. Publishes the clean, flat structure
76
+ 5. Updates root package.json with new version
77
+ 6. Optionally handles git tagging and pushing
package/README.md CHANGED
@@ -138,7 +138,7 @@ Version bump and publish your package to npm with clean, flat package structure.
138
138
  - `--no-cleanup` - Leave temporary directory after publishing
139
139
  - `--public` - Publish as public package (`--access=public`)
140
140
  - `--no-license` - Do not copy LICENSE file to published package
141
- - `--no-changelog` - Do not copy CHANGELOG.md file to published package
141
+ - `-v, --verbose` - Show detailed output including npm and git command details
142
142
 
143
143
  **Git Options:**
144
144
  - `--tag` - Create git tag for release
@@ -148,7 +148,7 @@ Version bump and publish your package to npm with clean, flat package structure.
148
148
  **Default Behavior:**
149
149
  - Defaults to patch version bump if no type specified
150
150
  - Extracts build artifacts to temporary directory
151
- - Copies root files: `README.md`, `LICENSE`, `CHANGELOG.md`, `.npmrc` (if they exist)
151
+ - Copies root files: `README.md`, `LICENSE`, `.npmrc` (if they exist)
152
152
  - Transforms package.json paths (e.g., `./dist/file.mjs` → `./file.mjs`)
153
153
  - Creates clean, flat package structure in node_modules
154
154
 
@@ -158,6 +158,7 @@ itty publish # Patch bump and publish from dist/ (default)
158
158
  itty publish --minor --tag # Minor bump, publish, and create git tag
159
159
  itty publish --type=alpha # Pre-release alpha version
160
160
  itty publish --dry-run # Test the publish process
161
+ itty publish --verbose # Show detailed output during publish
161
162
  itty publish --no-license # Publish without copying LICENSE file
162
163
  ```
163
164
 
@@ -166,7 +167,7 @@ itty publish --no-license # Publish without copying LICENSE file
166
167
  The publish command creates a clean package structure by:
167
168
 
168
169
  1. **Extracting build artifacts** from your `dist/` directory to package root
169
- 2. **Copying essential files** like README, LICENSE, CHANGELOG
170
+ 2. **Copying essential files** like README, LICENSE
170
171
  3. **Transforming paths** in package.json to point to root-level files
171
172
  4. **Publishing the clean structure** so users get flat imports
172
173
 
@@ -72,19 +72,35 @@ function versionBump(currentVersion, type) {
72
72
  }
73
73
  }
74
74
 
75
- async function runCommand(command, cwd = process.cwd()) {
75
+ async function runCommand(command, cwd = process.cwd(), verbose = false) {
76
76
  return new Promise((resolve, reject) => {
77
77
  const [cmd, ...args] = command.split(' ')
78
78
  const proc = spawn(cmd, args, {
79
- stdio: 'inherit',
79
+ stdio: verbose ? 'inherit' : 'pipe',
80
80
  cwd,
81
81
  shell: true
82
82
  })
83
83
 
84
+ let stdout = ''
85
+ let stderr = ''
86
+
87
+ if (!verbose) {
88
+ proc.stdout?.on('data', (data) => {
89
+ stdout += data.toString()
90
+ })
91
+ proc.stderr?.on('data', (data) => {
92
+ stderr += data.toString()
93
+ })
94
+ }
95
+
84
96
  proc.on('close', (code) => {
85
97
  if (code === 0) {
86
- resolve()
98
+ resolve({ stdout, stderr })
87
99
  } else {
100
+ // Always show error output regardless of verbose setting
101
+ if (!verbose && stderr) {
102
+ console.error(stderr)
103
+ }
88
104
  reject(new Error(`Command failed with exit code ${code}: ${command}`))
89
105
  }
90
106
  })
@@ -153,9 +169,10 @@ export async function publishCommand(args) {
153
169
  type: 'boolean',
154
170
  description: 'Do not copy LICENSE file to published package'
155
171
  },
156
- 'no-changelog': {
172
+ verbose: {
157
173
  type: 'boolean',
158
- description: 'Do not copy CHANGELOG.md file to published package'
174
+ short: 'v',
175
+ description: 'Show detailed output including npm and git command details'
159
176
  },
160
177
  help: {
161
178
  type: 'boolean',
@@ -185,7 +202,7 @@ Publish Options:
185
202
  --no-cleanup Leave temporary directory after publishing
186
203
  --public Publish as public package (--access=public)
187
204
  --no-license Do not copy LICENSE file to published package
188
- --no-changelog Do not copy CHANGELOG.md file to published package
205
+ -v, --verbose Show detailed output including npm and git command details
189
206
 
190
207
  Git Options:
191
208
  --tag Create git tag for release
@@ -229,7 +246,7 @@ This creates a clean, flat package structure in node_modules.
229
246
  const shouldPush = publishArgs.push
230
247
  const noGit = publishArgs['no-git']
231
248
  const noLicense = publishArgs['no-license']
232
- const noChangelog = publishArgs['no-changelog']
249
+ const verbose = publishArgs.verbose
233
250
 
234
251
  try {
235
252
  // Read package.json
@@ -238,7 +255,7 @@ This creates a clean, flat package structure in node_modules.
238
255
  const newVersion = versionBump(pkg.version, releaseType)
239
256
 
240
257
  console.log(`📦 Publishing ${pkg.name} v${pkg.version} → v${newVersion}`)
241
- console.log(`📁 Source: ${publishArgs.src}/`)
258
+ if (verbose) console.log(`📁 Source: ${publishArgs.src}/`)
242
259
 
243
260
  // Check if source directory exists
244
261
  if (!await fs.pathExists(srcDir)) {
@@ -246,12 +263,12 @@ This creates a clean, flat package structure in node_modules.
246
263
  }
247
264
 
248
265
  // Clean and create temp directory
249
- console.log(`🧹 Preparing ${publishArgs.dest}/`)
266
+ if (verbose) console.log(`🧹 Preparing ${publishArgs.dest}/`)
250
267
  await fs.emptyDir(tempDir)
251
268
  await fs.ensureDir(tempDir)
252
269
 
253
270
  // Copy source files to temp directory
254
- console.log(`📋 Copying ${publishArgs.src}/ to ${path.relative(rootPath, tempDir)}/`)
271
+ if (verbose) console.log(`📋 Copying ${publishArgs.src}/ to ${path.relative(rootPath, tempDir)}/`)
255
272
 
256
273
  const filter = (src) => {
257
274
  // Always exclude node_modules
@@ -280,14 +297,13 @@ This creates a clean, flat package structure in node_modules.
280
297
 
281
298
  // Add optional files based on flags
282
299
  if (!noLicense) rootFiles.push('LICENSE')
283
- if (!noChangelog) rootFiles.push('CHANGELOG.md')
284
300
 
285
301
  for (const file of rootFiles) {
286
302
  const srcFile = path.join(rootPath, file)
287
303
  const destFile = path.join(tempDir, file)
288
304
 
289
305
  if (await fs.pathExists(srcFile)) {
290
- console.log(`📄 Copying ${file}`)
306
+ if (verbose) console.log(`📄 Copying ${file}`)
291
307
  await fs.copy(srcFile, destFile)
292
308
  }
293
309
  }
@@ -300,7 +316,7 @@ This creates a clean, flat package structure in node_modules.
300
316
  const tempPkgPath = path.join(tempDir, 'package.json')
301
317
 
302
318
  const transformMessage = isRootPublish ? '' : ' (transforming paths)'
303
- console.log(`📝 Updating package.json to v${newVersion}${transformMessage}`)
319
+ if (verbose) console.log(`📝 Updating package.json to v${newVersion}${transformMessage}`)
304
320
  await fs.writeJSON(tempPkgPath, updatedPkg, { spaces: 2 })
305
321
 
306
322
  if (dryRun) {
@@ -315,41 +331,41 @@ This creates a clean, flat package structure in node_modules.
315
331
  SEMVER_TYPES.includes(releaseType) ? '' : `--tag=${releaseType}`
316
332
  ].filter(Boolean).join(' ')
317
333
 
318
- console.log(`Running: ${publishCmd}`)
319
- await runCommand(publishCmd, tempDir)
334
+ if (verbose) console.log(`Running: ${publishCmd}`)
335
+ await runCommand(publishCmd, tempDir, verbose)
320
336
 
321
337
  // Update root package.json
322
- console.log(`📝 Updating root package.json`)
338
+ if (verbose) console.log(`📝 Updating root package.json`)
323
339
  await fs.writeJSON(pkgPath, updatedPkg, { spaces: 2 })
324
340
  }
325
341
 
326
342
  // Git operations
327
343
  if (!noGit && !dryRun) {
328
344
  if (shouldPush || shouldTag) {
329
- console.log(`📋 Committing changes...`)
330
- await runCommand('git add .', rootPath)
331
- await runCommand(`git commit -m "released v${newVersion}"`, rootPath)
345
+ if (verbose) console.log(`📋 Committing changes...`)
346
+ await runCommand('git add .', rootPath, verbose)
347
+ await runCommand(`git commit -m "released v${newVersion}"`, rootPath, verbose)
332
348
  }
333
349
 
334
350
  if (shouldTag) {
335
- console.log(`🏷️ Creating git tag v${newVersion}`)
336
- await runCommand(`git tag -a v${newVersion} -m "Release v${newVersion}"`, rootPath)
351
+ if (verbose) console.log(`🏷️ Creating git tag v${newVersion}`)
352
+ await runCommand(`git tag -a v${newVersion} -m "Release v${newVersion}"`, rootPath, verbose)
337
353
  }
338
354
 
339
355
  if (shouldPush) {
340
- console.log(`📤 Pushing to remote...`)
341
- await runCommand('git push', rootPath)
356
+ if (verbose) console.log(`📤 Pushing to remote...`)
357
+ await runCommand('git push', rootPath, verbose)
342
358
 
343
359
  if (shouldTag) {
344
- console.log(`📤 Pushing tags...`)
345
- await runCommand('git push --tags', rootPath)
360
+ if (verbose) console.log(`📤 Pushing tags...`)
361
+ await runCommand('git push --tags', rootPath, verbose)
346
362
  }
347
363
  }
348
364
  }
349
365
 
350
366
  // Cleanup
351
367
  if (!noCleanup) {
352
- console.log(`🧹 Cleaning up ${publishArgs.dest}/`)
368
+ if (verbose) console.log(`🧹 Cleaning up ${publishArgs.dest}/`)
353
369
  await fs.remove(tempDir)
354
370
  }
355
371
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itty-packager",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Universal build tool for itty libraries",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,10 +9,10 @@
9
9
  "scripts": {
10
10
  "lint": "bun bin/itty.js lint",
11
11
  "test": "echo 'No tests yet'",
12
- "release:dry": "bun bin/itty.js publish --patch --tag --dry-run --src=. --no-license --no-changelog",
13
- "release": "bun bin/itty.js publish --patch --tag --push --src=. --no-license --no-changelog",
14
- "release:minor": "bun bin/itty.js publish --minor --tag --push --src=. --no-license --no-changelog",
15
- "release:major": "bun bin/itty.js publish --major --tag --push --src=. --no-license --no-changelog"
12
+ "release:dry": "bun bin/itty.js publish --patch --tag --dry-run --src=. --no-license",
13
+ "release": "bun bin/itty.js publish --patch --tag --push --src=. --no-license",
14
+ "release:minor": "bun bin/itty.js publish --minor --tag --push --src=. --no-license",
15
+ "release:major": "bun bin/itty.js publish --major --tag --push --src=. --no-license"
16
16
  },
17
17
  "keywords": [
18
18
  "build",