itty-packager 1.6.13 โ 1.8.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/CHANGELOG.md +4 -0
- package/README.md +16 -13
- package/lib/builder.js +11 -6
- package/lib/commands/build.js +19 -13
- package/lib/commands/release.js +112 -90
- package/package.json +2 -2
- package/test/build.spec.ts +34 -0
- package/test/release.spec.ts +8 -8
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ Build your TypeScript library with Rollup, TypeScript compilation, and optional
|
|
|
65
65
|
- `--hybrid` - Build both ESM and CJS (default: ESM only)
|
|
66
66
|
- `--minify` - Minify output with terser (default: `true`)
|
|
67
67
|
- `--no-minify` - Skip minification
|
|
68
|
+
- `--release-from <dir>` - Release directory - exports relative to this (default: same as `--out`)
|
|
68
69
|
- `-s, --snippet <name>` - Generate snippet file for README injection
|
|
69
70
|
- `-h, --help` - Show help
|
|
70
71
|
|
|
@@ -72,15 +73,16 @@ Build your TypeScript library with Rollup, TypeScript compilation, and optional
|
|
|
72
73
|
- Compiles all TypeScript files from `src/` to `dist/`
|
|
73
74
|
- Generates ESM (`.mjs`) output only
|
|
74
75
|
- Minifies output by default
|
|
75
|
-
- Updates `package.json` exports with correct paths
|
|
76
|
+
- Updates `package.json` exports with correct paths (relative to the release directory)
|
|
76
77
|
- Single file exports map to root export, multiple files get individual exports
|
|
77
78
|
|
|
78
79
|
**Examples:**
|
|
79
80
|
```bash
|
|
80
81
|
itty build # Basic ESM build, minified
|
|
81
|
-
itty build --hybrid --sourcemap
|
|
82
|
-
itty build --snippet=connect
|
|
83
|
-
itty build --from=lib --out=build
|
|
82
|
+
itty build --hybrid --sourcemap # Build both ESM/CJS with sourcemaps
|
|
83
|
+
itty build --snippet=connect # Build with snippet generation for README
|
|
84
|
+
itty build --from=lib --out=build # Build from lib/ to build/
|
|
85
|
+
itty build --release-from=. # Exports include output dir prefix (for root releasing)
|
|
84
86
|
```
|
|
85
87
|
|
|
86
88
|
### `itty lint`
|
|
@@ -181,10 +183,11 @@ Version bump and release your package to npm with git operations and clean, flat
|
|
|
181
183
|
- Git tag uses the same message as the commit
|
|
182
184
|
|
|
183
185
|
**Default Behavior:**
|
|
186
|
+
- Verifies npm auth before making any changes (prompts for login if expired)
|
|
184
187
|
- Defaults to patch version bump if no type specified
|
|
188
|
+
- Publishes to npm before git operations (so failed publishes don't leave orphaned tags)
|
|
185
189
|
- Extracts build artifacts to temporary directory
|
|
186
190
|
- Copies root files: `README.md`, `LICENSE`, `.npmrc` (if they exist)
|
|
187
|
-
- Transforms package.json paths (e.g., `./dist/file.mjs` โ `./file.mjs`)
|
|
188
191
|
- Creates clean, flat package structure in node_modules
|
|
189
192
|
|
|
190
193
|
**Examples:**
|
|
@@ -201,22 +204,22 @@ itty release --silent --push # Release with git operations, no interactive pro
|
|
|
201
204
|
|
|
202
205
|
## Package Structure
|
|
203
206
|
|
|
204
|
-
The release
|
|
207
|
+
The build + release commands work together to create a clean package structure:
|
|
205
208
|
|
|
206
|
-
1. **
|
|
207
|
-
2. **
|
|
208
|
-
3. **
|
|
209
|
-
4. **
|
|
209
|
+
1. **Build** compiles to `dist/` and writes exports relative to the release directory (no `dist/` prefix by default)
|
|
210
|
+
2. **Release** extracts build artifacts from `dist/` to a flat package root
|
|
211
|
+
3. **Copies essential files** like README, LICENSE
|
|
212
|
+
4. **Publishes the clean structure** so users get flat imports
|
|
210
213
|
|
|
211
|
-
**
|
|
214
|
+
**In your project:**
|
|
212
215
|
```
|
|
213
|
-
package.json exports: "./
|
|
216
|
+
package.json exports: "./connect.mjs"
|
|
214
217
|
dist/connect.mjs
|
|
215
218
|
README.md
|
|
216
219
|
LICENSE
|
|
217
220
|
```
|
|
218
221
|
|
|
219
|
-
**
|
|
222
|
+
**In node_modules (after publish):**
|
|
220
223
|
```
|
|
221
224
|
package.json exports: "./connect.mjs"
|
|
222
225
|
connect.mjs
|
package/lib/builder.js
CHANGED
|
@@ -14,6 +14,7 @@ export async function build(options = {}) {
|
|
|
14
14
|
const {
|
|
15
15
|
from = 'src',
|
|
16
16
|
out = 'dist',
|
|
17
|
+
'release-from': releaseFrom,
|
|
17
18
|
copy: copyFiles,
|
|
18
19
|
snippet,
|
|
19
20
|
sourcemap = false,
|
|
@@ -21,6 +22,10 @@ export async function build(options = {}) {
|
|
|
21
22
|
minify = true
|
|
22
23
|
} = options
|
|
23
24
|
|
|
25
|
+
// If releasing from the output dir (default), exports need no prefix.
|
|
26
|
+
// If releasing from elsewhere (e.g. root), exports need the output dir prefix.
|
|
27
|
+
const exportPrefix = (releaseFrom ?? out) === out ? '.' : `./${out}`
|
|
28
|
+
|
|
24
29
|
console.log(`๐ฆ Building from ${from}/ to ${out}/`)
|
|
25
30
|
|
|
26
31
|
// Clean output directory
|
|
@@ -55,13 +60,13 @@ export async function build(options = {}) {
|
|
|
55
60
|
// Single file maps to root export
|
|
56
61
|
const file = files[0]
|
|
57
62
|
const exportObj = {
|
|
58
|
-
import:
|
|
59
|
-
types:
|
|
63
|
+
import: `${exportPrefix}/${path.basename(file.esm)}`,
|
|
64
|
+
types: `${exportPrefix}/${path.basename(file.types)}`,
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
// Add CJS export only if hybrid mode is enabled
|
|
63
68
|
if (hybrid) {
|
|
64
|
-
exportObj.require =
|
|
69
|
+
exportObj.require = `${exportPrefix}/${path.basename(file.cjs)}`
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
pkg.exports = {
|
|
@@ -71,13 +76,13 @@ export async function build(options = {}) {
|
|
|
71
76
|
// Multiple files get individual exports
|
|
72
77
|
pkg.exports = files.reduce((acc, file) => {
|
|
73
78
|
const exportObj = {
|
|
74
|
-
import:
|
|
75
|
-
types:
|
|
79
|
+
import: `${exportPrefix}/${path.basename(file.esm)}`,
|
|
80
|
+
types: `${exportPrefix}/${path.basename(file.types)}`,
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
// Add CJS export only if hybrid mode is enabled
|
|
79
84
|
if (hybrid) {
|
|
80
|
-
exportObj.require =
|
|
85
|
+
exportObj.require = `${exportPrefix}/${path.basename(file.cjs)}`
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
acc[file.shortPath] = exportObj
|
package/lib/commands/build.js
CHANGED
|
@@ -38,6 +38,10 @@ export async function buildCommand(args) {
|
|
|
38
38
|
type: 'boolean',
|
|
39
39
|
description: 'Skip minification'
|
|
40
40
|
},
|
|
41
|
+
'release-from': {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Release directory - exports are relative to this (default: same as --out)'
|
|
44
|
+
},
|
|
41
45
|
snippet: {
|
|
42
46
|
type: 'string',
|
|
43
47
|
short: 's',
|
|
@@ -59,22 +63,24 @@ itty build - Build your library with rollup and typescript
|
|
|
59
63
|
Usage: itty build [options]
|
|
60
64
|
|
|
61
65
|
Options:
|
|
62
|
-
-f, --from <dir>
|
|
63
|
-
-o, --out <dir>
|
|
64
|
-
-c, --copy <files>
|
|
65
|
-
--sourcemap
|
|
66
|
-
--hybrid
|
|
67
|
-
--minify
|
|
68
|
-
--no-minify
|
|
69
|
-
|
|
70
|
-
-
|
|
66
|
+
-f, --from <dir> Source directory (default: src)
|
|
67
|
+
-o, --out <dir> Output directory (default: dist)
|
|
68
|
+
-c, --copy <files> Files to copy to output (comma-separated)
|
|
69
|
+
--sourcemap Generate source maps (default: false)
|
|
70
|
+
--hybrid Build both ESM and CJS (default: ESM only)
|
|
71
|
+
--minify Minify output with terser (default: true)
|
|
72
|
+
--no-minify Skip minification
|
|
73
|
+
--release-from <dir> Release directory - exports relative to this (default: same as --out)
|
|
74
|
+
-s, --snippet <name> Generate snippet file for README injection
|
|
75
|
+
-h, --help Show help
|
|
71
76
|
|
|
72
77
|
Examples:
|
|
73
78
|
itty build # Build ESM only, minified, no sourcemaps
|
|
74
|
-
itty build --hybrid --sourcemap
|
|
75
|
-
itty build --no-minify
|
|
76
|
-
itty build --from=lib --out=build
|
|
77
|
-
itty build --snippet=connect
|
|
79
|
+
itty build --hybrid --sourcemap # Build both ESM/CJS with sourcemaps
|
|
80
|
+
itty build --no-minify # Build without minification
|
|
81
|
+
itty build --from=lib --out=build # Build from lib/ to build/
|
|
82
|
+
itty build --snippet=connect # Build with connect snippet generation
|
|
83
|
+
itty build --release-from=. # Exports include output dir prefix (for root releasing)
|
|
78
84
|
`)
|
|
79
85
|
return
|
|
80
86
|
}
|
package/lib/commands/release.js
CHANGED
|
@@ -6,49 +6,6 @@ import { prepareCommand } from './prepare.js'
|
|
|
6
6
|
|
|
7
7
|
const SEMVER_TYPES = ['major', 'minor', 'patch']
|
|
8
8
|
|
|
9
|
-
function transformPackageExports(pkg, srcDir) {
|
|
10
|
-
// Transform package.json exports to remove srcDir prefix from paths
|
|
11
|
-
if (pkg.exports) {
|
|
12
|
-
const transformPath = (exportPath) => {
|
|
13
|
-
if (typeof exportPath === 'string' && exportPath.startsWith(`./${srcDir}/`)) {
|
|
14
|
-
return exportPath.replace(`./${srcDir}/`, './')
|
|
15
|
-
}
|
|
16
|
-
return exportPath
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const transformExportObj = (exportObj) => {
|
|
20
|
-
if (typeof exportObj === 'string') {
|
|
21
|
-
return transformPath(exportObj)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (typeof exportObj === 'object' && exportObj !== null) {
|
|
25
|
-
const transformed = {}
|
|
26
|
-
for (const [key, value] of Object.entries(exportObj)) {
|
|
27
|
-
if (typeof value === 'string') {
|
|
28
|
-
transformed[key] = transformPath(value)
|
|
29
|
-
} else if (typeof value === 'object') {
|
|
30
|
-
transformed[key] = transformExportObj(value)
|
|
31
|
-
} else {
|
|
32
|
-
transformed[key] = value
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return transformed
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return exportObj
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const transformedExports = {}
|
|
42
|
-
for (const [key, value] of Object.entries(pkg.exports)) {
|
|
43
|
-
transformedExports[key] = transformExportObj(value)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return { ...pkg, exports: transformedExports }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return pkg
|
|
50
|
-
}
|
|
51
|
-
|
|
52
9
|
function versionBump(currentVersion, type) {
|
|
53
10
|
const parts = currentVersion.split('.').map(Number)
|
|
54
11
|
|
|
@@ -209,6 +166,54 @@ async function getCommitMessage(newVersion, silent = false) {
|
|
|
209
166
|
})
|
|
210
167
|
}
|
|
211
168
|
|
|
169
|
+
async function promptOtp() {
|
|
170
|
+
return new Promise((resolve, reject) => {
|
|
171
|
+
process.stdout.write('๐ Enter OTP code: ')
|
|
172
|
+
let code = ''
|
|
173
|
+
|
|
174
|
+
process.stdin.setRawMode(true)
|
|
175
|
+
process.stdin.resume()
|
|
176
|
+
|
|
177
|
+
const handleInput = (chunk) => {
|
|
178
|
+
const key = chunk.toString()
|
|
179
|
+
|
|
180
|
+
if (key === '\x03') {
|
|
181
|
+
cleanup()
|
|
182
|
+
reject(new Error('User cancelled with Ctrl+C'))
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (key === '\r' || key === '\n') {
|
|
187
|
+
process.stdout.write('\n')
|
|
188
|
+
cleanup()
|
|
189
|
+
resolve(code.trim())
|
|
190
|
+
return
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (key === '\x7f' || key === '\x08') {
|
|
194
|
+
if (code.length > 0) {
|
|
195
|
+
code = code.slice(0, -1)
|
|
196
|
+
process.stdout.write('\b \b')
|
|
197
|
+
}
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (key >= '0' && key <= '9') {
|
|
202
|
+
code += key
|
|
203
|
+
process.stdout.write(key)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const cleanup = () => {
|
|
208
|
+
process.stdin.setRawMode(false)
|
|
209
|
+
process.stdin.pause()
|
|
210
|
+
process.stdin.removeListener('data', handleInput)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
process.stdin.on('data', handleInput)
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
|
|
212
217
|
async function runCommand(command, cwd = process.cwd(), verbose = false) {
|
|
213
218
|
return new Promise((resolve, reject) => {
|
|
214
219
|
const [cmd, ...args] = command.split(' ')
|
|
@@ -318,6 +323,10 @@ export async function releaseCommand(args) {
|
|
|
318
323
|
type: 'boolean',
|
|
319
324
|
description: 'Skip interactive prompts (use default commit message)'
|
|
320
325
|
},
|
|
326
|
+
otp: {
|
|
327
|
+
type: 'boolean',
|
|
328
|
+
description: 'Prompt for a one-time password (OTP) for npm publish'
|
|
329
|
+
},
|
|
321
330
|
verbose: {
|
|
322
331
|
type: 'boolean',
|
|
323
332
|
short: 'v',
|
|
@@ -354,6 +363,7 @@ Publish Options:
|
|
|
354
363
|
--prepare Run prepare (lint, test, build) before publishing
|
|
355
364
|
--silent Skip interactive prompts (use default commit message)
|
|
356
365
|
--no-license Do not copy LICENSE file to published package
|
|
366
|
+
--otp Prompt for a one-time password (OTP) for npm publish
|
|
357
367
|
-v, --verbose Show detailed output including npm and git command details
|
|
358
368
|
|
|
359
369
|
Git Options:
|
|
@@ -408,6 +418,7 @@ This creates a clean, flat package structure in node_modules.
|
|
|
408
418
|
const noLicense = releaseArgs['no-license']
|
|
409
419
|
const shouldPrepare = releaseArgs.prepare
|
|
410
420
|
const silent = releaseArgs.silent
|
|
421
|
+
const useOtp = releaseArgs.otp
|
|
411
422
|
const verbose = releaseArgs.verbose
|
|
412
423
|
|
|
413
424
|
// Read package.json and store original version for potential revert
|
|
@@ -430,6 +441,17 @@ This creates a clean, flat package structure in node_modules.
|
|
|
430
441
|
throw new Error(`Source directory "${sourceDir}" does not exist. Run "itty build" first.`)
|
|
431
442
|
}
|
|
432
443
|
|
|
444
|
+
// Verify npm auth before making any changes
|
|
445
|
+
if (!dryRun) {
|
|
446
|
+
console.log(`๐ Verifying npm auth...`)
|
|
447
|
+
try {
|
|
448
|
+
await runCommand('npm whoami --registry=https://registry.npmjs.org', rootPath, verbose)
|
|
449
|
+
} catch {
|
|
450
|
+
console.log(`โ ๏ธ npm session expired โ logging in...`)
|
|
451
|
+
await runCommand('npm login --registry=https://registry.npmjs.org', rootPath, true)
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
433
455
|
// Clean and create temp directory
|
|
434
456
|
if (verbose) console.log(`๐งน Preparing ${releaseArgs.dest}/`)
|
|
435
457
|
await fs.emptyDir(tempDir)
|
|
@@ -478,47 +500,65 @@ This creates a clean, flat package structure in node_modules.
|
|
|
478
500
|
}
|
|
479
501
|
}
|
|
480
502
|
|
|
481
|
-
// Update package.json
|
|
482
|
-
const updatedPkg =
|
|
483
|
-
? { ...originalPkg, version: newVersion } // No path transformation for root publishing
|
|
484
|
-
: transformPackageExports({ ...originalPkg, version: newVersion }, sourceDir)
|
|
503
|
+
// Update package.json with new version
|
|
504
|
+
const updatedPkg = { ...originalPkg, version: newVersion }
|
|
485
505
|
const tempPkgPath = path.join(tempDir, 'package.json')
|
|
486
506
|
|
|
487
|
-
|
|
488
|
-
if (verbose) console.log(`๐ Updating package.json to v${newVersion}${transformMessage}`)
|
|
507
|
+
if (verbose) console.log(`๐ Updating package.json to v${newVersion}`)
|
|
489
508
|
await fs.writeJSON(tempPkgPath, updatedPkg, { spaces: 2 })
|
|
490
509
|
|
|
491
|
-
// Update root package.json
|
|
510
|
+
// Update root package.json with new version
|
|
492
511
|
if (!dryRun) {
|
|
493
512
|
if (verbose) console.log(`๐ Updating root package.json`)
|
|
494
513
|
await fs.writeJSON(pkgPath, updatedPkg, { spaces: 2 })
|
|
495
514
|
}
|
|
496
515
|
|
|
497
|
-
//
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
if (verbose) console.log(`Running: git add . && git commit`)
|
|
508
|
-
await runCommand('git add .', rootPath, verbose)
|
|
509
|
-
await runCommand(`git commit -m "${commitMessage}"`, rootPath, verbose)
|
|
510
|
-
} catch (error) {
|
|
511
|
-
if (error.message.includes('cancelled')) {
|
|
512
|
-
console.log('โ Commit cancelled - reverting version and exiting')
|
|
513
|
-
// Revert the version we just updated
|
|
514
|
-
await fs.writeJSON(pkgPath, originalPkg, { spaces: 2 })
|
|
515
|
-
// Don't rethrow - exit cleanly since this is user-initiated
|
|
516
|
-
process.exit(0)
|
|
517
|
-
}
|
|
518
|
-
throw error
|
|
516
|
+
// Collect interactive inputs before publish
|
|
517
|
+
let commitMessage = `released v${newVersion}`
|
|
518
|
+
if (!noGit && !dryRun && (shouldPush || shouldTag)) {
|
|
519
|
+
try {
|
|
520
|
+
commitMessage = await getCommitMessage(newVersion, silent)
|
|
521
|
+
} catch (error) {
|
|
522
|
+
if (error.message.includes('cancelled')) {
|
|
523
|
+
console.log('โ Release cancelled - reverting version and exiting')
|
|
524
|
+
await fs.writeJSON(pkgPath, originalPkg, { spaces: 2 })
|
|
525
|
+
process.exit(0)
|
|
519
526
|
}
|
|
527
|
+
throw error
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// NPM publish (before git operations so failed publishes don't leave orphaned tags)
|
|
532
|
+
if (dryRun) {
|
|
533
|
+
console.log('๐ธ Dry run - skipping publish')
|
|
534
|
+
} else {
|
|
535
|
+
let otpCode
|
|
536
|
+
if (useOtp) {
|
|
537
|
+
otpCode = await promptOtp()
|
|
538
|
+
if (!otpCode) throw new Error('No OTP code provided')
|
|
520
539
|
}
|
|
521
540
|
|
|
541
|
+
console.log(`๐ Publishing to npm...`)
|
|
542
|
+
|
|
543
|
+
const publishCmd = [
|
|
544
|
+
'npm publish',
|
|
545
|
+
'--registry=https://registry.npmjs.org',
|
|
546
|
+
publicAccess ? '--access=public' : '',
|
|
547
|
+
SEMVER_TYPES.includes(releaseType) ? '' : `--tag=${releaseType}`,
|
|
548
|
+
otpCode ? `--otp=${otpCode}` : ''
|
|
549
|
+
].filter(Boolean).join(' ')
|
|
550
|
+
|
|
551
|
+
if (verbose) console.log(`Running: ${publishCmd}`)
|
|
552
|
+
await runCommand(publishCmd, tempDir, true)
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Git operations (only after successful publish)
|
|
556
|
+
if (!noGit && !dryRun && (shouldPush || shouldTag)) {
|
|
557
|
+
console.log(`๐ Committing changes...`)
|
|
558
|
+
if (verbose) console.log(`Running: git add . && git commit`)
|
|
559
|
+
await runCommand('git add .', rootPath, verbose)
|
|
560
|
+
await runCommand(`git commit -m "${commitMessage}"`, rootPath, verbose)
|
|
561
|
+
|
|
522
562
|
if (shouldTag) {
|
|
523
563
|
console.log(`๐ท๏ธ Creating git tag v${newVersion}`)
|
|
524
564
|
await runCommand(`git tag -a v${newVersion} -m "${commitMessage}"`, rootPath, verbose)
|
|
@@ -535,24 +575,6 @@ This creates a clean, flat package structure in node_modules.
|
|
|
535
575
|
}
|
|
536
576
|
}
|
|
537
577
|
|
|
538
|
-
// NPM publish as final step
|
|
539
|
-
if (dryRun) {
|
|
540
|
-
console.log('๐ธ Dry run - skipping publish')
|
|
541
|
-
} else {
|
|
542
|
-
// Publish from temp directory
|
|
543
|
-
console.log(`๐ Publishing to npm...`)
|
|
544
|
-
|
|
545
|
-
const publishCmd = [
|
|
546
|
-
'npm publish',
|
|
547
|
-
'--registry=https://registry.npmjs.org',
|
|
548
|
-
publicAccess ? '--access=public' : '',
|
|
549
|
-
SEMVER_TYPES.includes(releaseType) ? '' : `--tag=${releaseType}`
|
|
550
|
-
].filter(Boolean).join(' ')
|
|
551
|
-
|
|
552
|
-
if (verbose) console.log(`Running: ${publishCmd}`)
|
|
553
|
-
await runCommand(publishCmd, tempDir, verbose)
|
|
554
|
-
}
|
|
555
|
-
|
|
556
578
|
// Cleanup
|
|
557
579
|
if (!noCleanup) {
|
|
558
580
|
if (verbose) console.log(`๐งน Cleaning up ${releaseArgs.dest}/`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "itty-packager",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Universal build tool for itty libraries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"lint": "bun bin/itty.js lint",
|
|
11
11
|
"dev": "bun test --coverage --watch",
|
|
12
|
-
"release": "bun bin/itty.js release --patch --tag --push --root"
|
|
12
|
+
"release": "bun bin/itty.js release --patch --tag --push --root --otp"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"build",
|
package/test/build.spec.ts
CHANGED
|
@@ -67,6 +67,40 @@ const tests: TestTree = {
|
|
|
67
67
|
expect(result.exitCode).toBe(0)
|
|
68
68
|
await expectFile(path.join(project.dir, 'build/main.mjs')).toExist()
|
|
69
69
|
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
'export paths': {
|
|
73
|
+
'default: exports have no dist/ prefix': async () => {
|
|
74
|
+
const project = await ProjectFixture.create('exports-default', {
|
|
75
|
+
'src/index.ts': 'export const a = 1',
|
|
76
|
+
'package.json': JSON.stringify({
|
|
77
|
+
name: 'test-exports',
|
|
78
|
+
version: '1.0.0',
|
|
79
|
+
type: 'module'
|
|
80
|
+
}, null, 2)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await cli.run(['build'], { cwd: project.dir })
|
|
84
|
+
const pkg = JSON.parse(await Bun.file(path.join(project.dir, 'package.json')).text())
|
|
85
|
+
expect(pkg.exports['.'].import).toBe('./index.mjs')
|
|
86
|
+
expect(pkg.exports['.'].types).toBe('./index.d.ts')
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
'--release-from=. adds dist/ prefix': async () => {
|
|
90
|
+
const project = await ProjectFixture.create('exports-release-from', {
|
|
91
|
+
'src/index.ts': 'export const a = 1',
|
|
92
|
+
'package.json': JSON.stringify({
|
|
93
|
+
name: 'test-exports-root',
|
|
94
|
+
version: '1.0.0',
|
|
95
|
+
type: 'module'
|
|
96
|
+
}, null, 2)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
await cli.run(['build', '--release-from=.'], { cwd: project.dir })
|
|
100
|
+
const pkg = JSON.parse(await Bun.file(path.join(project.dir, 'package.json')).text())
|
|
101
|
+
expect(pkg.exports['.'].import).toBe('./dist/index.mjs')
|
|
102
|
+
expect(pkg.exports['.'].types).toBe('./dist/index.d.ts')
|
|
103
|
+
}
|
|
70
104
|
}
|
|
71
105
|
}
|
|
72
106
|
}
|
package/test/release.spec.ts
CHANGED
|
@@ -155,20 +155,20 @@ const tests: TestTree = {
|
|
|
155
155
|
}
|
|
156
156
|
},
|
|
157
157
|
|
|
158
|
-
'package structure
|
|
159
|
-
'copies and
|
|
160
|
-
const project = await ProjectFixture.create('package-
|
|
158
|
+
'package structure': {
|
|
159
|
+
'copies dist files and preserves exports': async () => {
|
|
160
|
+
const project = await ProjectFixture.create('package-structure', {
|
|
161
161
|
'dist/index.mjs': 'export const main = "test"',
|
|
162
162
|
'dist/utils.mjs': 'export const utils = "helper"',
|
|
163
163
|
'README.md': '# Test Package',
|
|
164
164
|
'LICENSE': 'MIT License',
|
|
165
165
|
'package.json': JSON.stringify({
|
|
166
|
-
name: 'test-
|
|
166
|
+
name: 'test-structure',
|
|
167
167
|
version: '1.0.0',
|
|
168
168
|
type: 'module',
|
|
169
169
|
exports: {
|
|
170
|
-
'.': './
|
|
171
|
-
'./utils': './
|
|
170
|
+
'.': './index.mjs',
|
|
171
|
+
'./utils': './utils.mjs'
|
|
172
172
|
}
|
|
173
173
|
}, null, 2)
|
|
174
174
|
})
|
|
@@ -176,14 +176,14 @@ const tests: TestTree = {
|
|
|
176
176
|
const result = await cli.run(['release', '--dry-run', '--no-git', '--no-cleanup'], { cwd: project.dir })
|
|
177
177
|
expect(result.exitCode).toBe(0)
|
|
178
178
|
|
|
179
|
-
// Check that temp directory was created with
|
|
179
|
+
// Check that temp directory was created with flat structure
|
|
180
180
|
const tempDir = path.join(project.dir, '.dist')
|
|
181
181
|
await expectFile(path.join(tempDir, 'index.mjs')).toExist()
|
|
182
182
|
await expectFile(path.join(tempDir, 'utils.mjs')).toExist()
|
|
183
183
|
await expectFile(path.join(tempDir, 'README.md')).toExist()
|
|
184
184
|
await expectFile(path.join(tempDir, 'LICENSE')).toExist()
|
|
185
185
|
|
|
186
|
-
// Check that
|
|
186
|
+
// Check that exports are preserved as-is (no transformation needed)
|
|
187
187
|
const pkgContent = fs.readFileSync(path.join(tempDir, 'package.json'), 'utf-8')
|
|
188
188
|
const pkg = JSON.parse(pkgContent)
|
|
189
189
|
expect(pkg.exports).toEqual({
|