itty-packager 1.0.11 โ†’ 1.1.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.
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(bun bin/itty.js lint:*)"
4
+ "Bash(bun bin/itty.js lint:*)",
5
+ "Bash(bun bin/itty.js prepare:*)",
6
+ "Bash(bun bin/itty.js publish:*)"
5
7
  ],
6
8
  "deny": []
7
9
  }
package/bin/itty.js CHANGED
@@ -5,6 +5,7 @@ import { parseArgs } from 'node:util'
5
5
  const subcommands = {
6
6
  build: () => import('../lib/commands/build.js').then(m => m.buildCommand),
7
7
  lint: () => import('../lib/commands/lint.js').then(m => m.lintCommand),
8
+ prepare: () => import('../lib/commands/prepare.js').then(m => m.prepareCommand),
8
9
  publish: () => import('../lib/commands/publish.js').then(m => m.publishCommand),
9
10
  // Future subcommands can be added here:
10
11
  // deploy: () => import('../lib/commands/deploy.js').then(m => m.deployCommand),
@@ -73,6 +74,7 @@ Usage: itty <subcommand> [options]
73
74
  Subcommands:
74
75
  build Build your library with rollup and typescript
75
76
  lint Lint your code with ESLint
77
+ prepare Run lint, test, and build in sequence
76
78
  publish Version and publish your package to npm
77
79
 
78
80
  Global Options:
@@ -0,0 +1,153 @@
1
+ import { parseArgs } from 'node:util'
2
+ import { spawn } from 'node:child_process'
3
+ import fs from 'fs-extra'
4
+ import path from 'node:path'
5
+ import { build } from '../builder.js'
6
+ import { lintCommand } from './lint.js'
7
+
8
+ export async function prepareCommand(args) {
9
+ const { values: prepareArgs } = parseArgs({
10
+ args,
11
+ options: {
12
+ verbose: {
13
+ type: 'boolean',
14
+ short: 'v',
15
+ description: 'Show all output from underlying commands'
16
+ },
17
+ help: {
18
+ type: 'boolean',
19
+ short: 'h',
20
+ description: 'Show help'
21
+ }
22
+ },
23
+ allowPositionals: false
24
+ })
25
+
26
+ if (prepareArgs.help) {
27
+ console.log(`
28
+ itty prepare - Run lint, test, and build in sequence
29
+
30
+ Usage: itty prepare [options]
31
+
32
+ Options:
33
+ -v, --verbose Show all output from underlying commands
34
+ -h, --help Show help
35
+
36
+ Examples:
37
+ itty prepare # Run lint, test, build silently (show only failures)
38
+ itty prepare --verbose # Run with full output from all commands
39
+
40
+ Note:
41
+ - Uses package.json scripts if available (lint, test), falls back to built-in commands
42
+ - Only shows output when commands fail, unless --verbose is used
43
+ - Stops on first failure
44
+ `)
45
+ return
46
+ }
47
+
48
+ const cwd = process.cwd()
49
+ const packageJsonPath = path.join(cwd, 'package.json')
50
+
51
+ let packageJson = {}
52
+ if (await fs.pathExists(packageJsonPath)) {
53
+ packageJson = await fs.readJson(packageJsonPath)
54
+ }
55
+
56
+ const scripts = packageJson.scripts || {}
57
+ const verbose = prepareArgs.verbose
58
+
59
+ console.log('๐Ÿš€ Running prepare sequence...')
60
+
61
+ // 1. Lint
62
+ try {
63
+ if (scripts.lint) {
64
+ console.log('๐Ÿ” Running lint script...')
65
+ await runNpmScript('lint', verbose)
66
+ } else {
67
+ console.log('๐Ÿ” Running built-in lint...')
68
+ await lintCommand([])
69
+ }
70
+ if (!verbose) console.log('โœ… Lint passed')
71
+ } catch (error) {
72
+ throw new Error(`Lint failed: ${error.message}`)
73
+ }
74
+
75
+ // 2. Test
76
+ try {
77
+ if (scripts.test) {
78
+ console.log('๐Ÿงช Running test script...')
79
+ await runNpmScript('test', verbose)
80
+ if (!verbose) console.log('โœ… Tests passed')
81
+ } else {
82
+ console.log('๐Ÿงช No test script found, skipping tests')
83
+ }
84
+ } catch (error) {
85
+ throw new Error(`Tests failed: ${error.message}`)
86
+ }
87
+
88
+ // 3. Build
89
+ try {
90
+ if (scripts.build) {
91
+ console.log('๐Ÿ”จ Running build script...')
92
+ await runNpmScript('build', verbose)
93
+ if (!verbose) console.log('โœ… Build completed')
94
+ } else {
95
+ // Check if there's a src directory or TypeScript files to build
96
+ const srcExists = await fs.pathExists(path.join(cwd, 'src'))
97
+ if (srcExists) {
98
+ console.log('๐Ÿ”จ Running built-in build...')
99
+ await build({})
100
+ if (!verbose) console.log('โœ… Build completed')
101
+ } else {
102
+ console.log('๐Ÿ”จ No build script or src directory found, skipping build')
103
+ }
104
+ }
105
+ } catch (error) {
106
+ throw new Error(`Build failed: ${error.message}`)
107
+ }
108
+
109
+ console.log('๐ŸŽ‰ Prepare sequence completed successfully')
110
+ }
111
+
112
+ async function runNpmScript(scriptName, verbose) {
113
+ return new Promise((resolve, reject) => {
114
+ const stdio = verbose ? 'inherit' : 'pipe'
115
+ const npm = spawn('npm', ['run', scriptName], {
116
+ stdio,
117
+ cwd: process.cwd(),
118
+ shell: true
119
+ })
120
+
121
+ let stdout = ''
122
+ let stderr = ''
123
+
124
+ if (!verbose) {
125
+ npm.stdout?.on('data', (data) => {
126
+ stdout += data.toString()
127
+ })
128
+
129
+ npm.stderr?.on('data', (data) => {
130
+ stderr += data.toString()
131
+ })
132
+ }
133
+
134
+ npm.on('close', (code) => {
135
+ if (code === 0) {
136
+ resolve()
137
+ } else {
138
+ // Show output on failure even if not verbose
139
+ if (!verbose && (stdout || stderr)) {
140
+ console.error('\n--- Output from failed command ---')
141
+ if (stdout) console.log(stdout)
142
+ if (stderr) console.error(stderr)
143
+ console.error('--- End output ---\n')
144
+ }
145
+ reject(new Error(`Script '${scriptName}' exited with code ${code}`))
146
+ }
147
+ })
148
+
149
+ npm.on('error', (error) => {
150
+ reject(new Error(`Failed to run script '${scriptName}': ${error.message}`))
151
+ })
152
+ })
153
+ }
@@ -2,6 +2,7 @@ import { parseArgs } from 'node:util'
2
2
  import { spawn } from 'node:child_process'
3
3
  import fs from 'fs-extra'
4
4
  import path from 'node:path'
5
+ import { prepareCommand } from './prepare.js'
5
6
 
6
7
  const SEMVER_TYPES = ['major', 'minor', 'patch']
7
8
 
@@ -169,6 +170,10 @@ export async function publishCommand(args) {
169
170
  type: 'boolean',
170
171
  description: 'Do not copy LICENSE file to published package'
171
172
  },
173
+ prepare: {
174
+ type: 'boolean',
175
+ description: 'Run prepare (lint, test, build) before publishing'
176
+ },
172
177
  verbose: {
173
178
  type: 'boolean',
174
179
  short: 'v',
@@ -201,6 +206,7 @@ Publish Options:
201
206
  --dry-run Build and prepare but do not publish
202
207
  --no-cleanup Leave temporary directory after publishing
203
208
  --public Publish as public package (--access=public)
209
+ --prepare Run prepare (lint, test, build) before publishing
204
210
  --no-license Do not copy LICENSE file to published package
205
211
  -v, --verbose Show detailed output including npm and git command details
206
212
 
@@ -246,9 +252,16 @@ This creates a clean, flat package structure in node_modules.
246
252
  const shouldPush = publishArgs.push
247
253
  const noGit = publishArgs['no-git']
248
254
  const noLicense = publishArgs['no-license']
255
+ const shouldPrepare = publishArgs.prepare
249
256
  const verbose = publishArgs.verbose
250
257
 
251
258
  try {
259
+ // Run prepare if requested
260
+ if (shouldPrepare) {
261
+ console.log('๐Ÿš€ Running prepare sequence before publishing...')
262
+ await prepareCommand(verbose ? ['--verbose'] : [])
263
+ console.log('โœ… Prepare completed successfully\n')
264
+ }
252
265
  // Read package.json
253
266
  const pkgPath = path.join(rootPath, 'package.json')
254
267
  const pkg = await fs.readJSON(pkgPath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itty-packager",
3
- "version": "1.0.11",
3
+ "version": "1.1.0",
4
4
  "description": "Universal build tool for itty libraries",
5
5
  "type": "module",
6
6
  "bin": {