🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@publint/pack

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@publint/pack - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+1
-1
LICENSE
MIT License
Copyright (c) 2025 Bjorn Lu
Copyright (c) 2025 Bjorn Lu and publint contributors

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"name": "@publint/pack",
"version": "0.1.0",
"version": "0.1.1",
"description": "Utilities for packing and unpacking npm packages",

@@ -22,7 +22,7 @@ "type": "module",

"type": "git",
"url": "git+https://github.com/bluwy/publint.git",
"url": "git+https://github.com/publint/publint.git",
"directory": "packages/pack"
},
"bugs": {
"url": "https://github.com/bluwy/publint/issues"
"url": "https://github.com/publint/publint/issues"
},

@@ -37,3 +37,3 @@ "keywords": [

"fs-fixture": "^2.6.0",
"vitest": "^3.0.0-beta.3"
"vitest": "^3.0.0-beta.4"
},

@@ -40,0 +40,0 @@ "scripts": {

@@ -12,2 +12,4 @@ # @publint/pack

NOTE: All `pack*` APIs support passing `opts.packageManager` to specify the package manager to use for packing, and `opts.ignoreScripts` to skip running lifecycle scripts.
### `pack()`

@@ -17,3 +19,3 @@

Packs the given directory and returns the packed tarball path. Pass `opts.packageManager` to specify the package manager to use for packing.
Packs the given directory and returns the packed tarball path. Pass `opts.destination` to change the output directory of the tarball.

@@ -32,3 +34,3 @@ ```js

Packs the given directory and returns a list of relative file paths that were packed. Pass `opts.packageManager` to specify the package manager to use for packing.
Packs the given directory and returns a list of relative file paths that were packed.

@@ -52,3 +54,3 @@ > [!NOTE]

Packs the given directory with the `--json` flag and returns its stdout as JSON. You can run the `<pm> pack --json` command manually to inspect the output shape. Pass `opts.packageManager` to specify the package manager to use for packing.
Packs the given directory with the `--json` flag and returns its stdout as JSON. You can run the `<pm> pack --json` command manually to inspect the output shape.

@@ -78,3 +80,3 @@ > [!NOTE]

const response = await fetch(
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz'
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz',
)

@@ -81,0 +83,0 @@ if (!response.body) throw new Error('Failed to fetch tarball')

import {
arrayBufferToReadableStream,
readableStreamToArrayBuffer
readableStreamToArrayBuffer,
} from '../shared/buffer-stream.js'

@@ -14,3 +14,3 @@ import { getFilesRootDir, parseTar } from '../shared/parse-tar.js'

const buffer = await readableStreamToArrayBuffer(
stream.pipeThrough(new DecompressionStream('gzip'))
stream.pipeThrough(new DecompressionStream('gzip')),
)

@@ -17,0 +17,0 @@ const files = parseTar(buffer)

@@ -8,2 +8,9 @@ interface SharedPackOptions {

packageManager?: 'npm' | 'yarn' | 'pnpm' | 'bun'
/**
* Whether to ignore lifecycle scripts during packing, i.e. `prepare`, `prepack`,
* and `postpack`. (Does not work with yarn as it does not support ignoring scripts)
*
* @default false
*/
ignoreScripts?: boolean
}

@@ -28,3 +35,3 @@

dir: string,
opts?: PackAsListOptions
opts?: PackAsListOptions,
): Promise<string[]>

@@ -69,3 +76,3 @@

export function unpack(
tarball: ArrayBuffer | ReadableStream<Uint8Array>
tarball: ArrayBuffer | ReadableStream<Uint8Array>,
): Promise<UnpackResult>

@@ -15,2 +15,4 @@ import cp from 'node:child_process'

// Handle tarball output. Try `--dry-run` if possible to not output any tarball,
// otherwise pack to a temporary directory and delete it later
const supportsDryRun = packageManager === 'npm' || packageManager === 'yarn'

@@ -22,4 +24,2 @@ /** @type {string | undefined} */

} else {
// For package managers that don't support `--dry-run`, we need to pack to a temporary directory
// and delete it later
packDestination = await getTempPackDir()

@@ -29,8 +29,27 @@ command += ` --pack-destination ${packDestination}`

const { stdout } = await util.promisify(cp.exec)(command, { cwd: dir })
// Handle ignore-scripts
if (opts?.ignoreScripts) {
switch (packageManager) {
case 'pnpm':
command += ' --config.ignore-scripts=true'
break
case 'yarn':
// yarn does not support ignoring scripts
break
default:
command += ' --ignore-scripts'
break
}
}
let { stdout } = await util.promisify(cp.exec)(command, { cwd: dir })
try {
return JSON.parse(
packageManager === 'yarn' ? fixYarnStdout(stdout) : stdout
)
stdout = stdout.trim()
if (packageManager === 'pnpm') {
stdout = fixPnpmStdout(stdout)
} else if (packageManager === 'yarn') {
stdout = fixYarnStdout(stdout)
}
return JSON.parse(stdout)
} finally {

@@ -43,2 +62,22 @@ if (!supportsDryRun && packDestination) {

// pnpm outputs lifecycle script logs if not ignoring scripts
/**
* @param {string} stdout
*/
function fixPnpmStdout(stdout) {
// If starts with `{`, it's likely a valid JSON
if (stdout.startsWith('{')) return stdout
// Otherwise try to find its usual output format, `{\n "name": ...`
const usualStartIndex = /\{\s*"name"/.exec(stdout)?.index
if (usualStartIndex != null) return stdout.slice(usualStartIndex)
// Otherwise, simply try to find the first `{` character
const firstBraceIndex = stdout.indexOf('{')
if (firstBraceIndex !== -1) return stdout.slice(firstBraceIndex)
// If all fails, return the original stdout
return stdout
}
// yarn outputs invalid json for some reason

@@ -45,0 +84,0 @@ /**

@@ -13,5 +13,5 @@ import fs from 'node:fs/promises'

try {
return await packAsListWithJson(dir, packageManager)
return await packAsListWithJson(dir, packageManager, opts?.ignoreScripts)
} catch {
return await packAsListWithPack(dir, packageManager)
return await packAsListWithPack(dir, packageManager, opts?.ignoreScripts)
}

@@ -25,6 +25,7 @@ }

* @param {NonNullable<import('../index.d.ts').PackAsListOptions['packageManager']>} packageManager
* @param {import('../index.d.ts').PackAsListOptions['ignoreScripts']} ignoreScripts
* @returns {Promise<string[]>}
*/
export async function packAsListWithJson(dir, packageManager) {
const stdoutJson = await packAsJson(dir, { packageManager })
export async function packAsListWithJson(dir, packageManager, ignoreScripts) {
const stdoutJson = await packAsJson(dir, { packageManager, ignoreScripts })
switch (packageManager) {

@@ -47,7 +48,12 @@ case 'npm':

* @param {NonNullable<import('../index.d.ts').PackAsListOptions['packageManager']>} packageManager
* @param {import('../index.d.ts').PackAsListOptions['ignoreScripts']} ignoreScripts
* @returns {Promise<string[]>}
*/
export async function packAsListWithPack(dir, packageManager) {
export async function packAsListWithPack(dir, packageManager, ignoreScripts) {
const destination = await getTempPackDir()
const tarballPath = await pack(dir, { packageManager, destination })
const tarballPath = await pack(dir, {
packageManager,
ignoreScripts,
destination,
})

@@ -54,0 +60,0 @@ try {

@@ -15,2 +15,3 @@ import cp from 'node:child_process'

// Handle tarball output
const packDestination = opts?.destination ?? dir

@@ -31,2 +32,17 @@ if (opts?.destination) {

// Handle ignore-scripts
if (opts?.ignoreScripts) {
switch (packageManager) {
case 'pnpm':
command += ' --config.ignore-scripts=true'
break
case 'yarn':
// yarn does not support ignoring scripts
break
default:
command += ' --ignore-scripts'
break
}
}
const output = await util.promisify(cp.exec)(command, { cwd: dir })

@@ -39,3 +55,3 @@

return files.find(
(file) => file.endsWith('.tgz') && output.stdout.includes(file)
(file) => file.endsWith('.tgz') && output.stdout.includes(file),
)

@@ -45,3 +61,3 @@ })

throw new Error(
`Failed to find packed tarball file in ${packDestination}. Command output:\n${JSON.stringify(output, null, 2)}`
`Failed to find packed tarball file in ${packDestination}. Command output:\n${JSON.stringify(output, null, 2)}`,
)

@@ -48,0 +64,0 @@ }

@@ -12,3 +12,3 @@ import util from 'node:util'

buffer = await readableStreamToArrayBuffer(
tarball.pipeThrough(new DecompressionStream('gzip'))
tarball.pipeThrough(new DecompressionStream('gzip')),
)

@@ -15,0 +15,0 @@ } else {

@@ -12,3 +12,3 @@ // Utilities between ArrayBuffer and ReadableStream

controller.close()
}
},
})

@@ -15,0 +15,0 @@ }