Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"node": "^22 || ^24"
},
"bin": {
"github-delivery": "./scripts/github-delivery-cli.mjs"
"github-delivery": "scripts/github-delivery-cli.mjs"
},
"files": [
"scripts/github-delivery-cli.mjs",
Expand All @@ -26,7 +26,7 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Wibias/github-delivery.git"
"url": "git+https://github.com/Wibias/github-delivery.git"
},
"publishConfig": {
"access": "public",
Expand Down
24 changes: 24 additions & 0 deletions scripts/lib/npm-pack-json.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export function parseNpmPackJson(stdout) {
const text = String(stdout || "").trim();
if (!text) throw new Error("npm_pack_json_missing");

let parsed;
try {
parsed = JSON.parse(text);
} catch (error) {
throw new Error(`npm_pack_json_invalid:${error?.message || String(error)}`);
}

if (Array.isArray(parsed)) return parsed;

if (parsed && typeof parsed === "object") {
if (Array.isArray(parsed.files)) return [parsed];

const packs = Object.values(parsed).filter(
(value) => value && typeof value === "object" && Array.isArray(value.files),
);
if (packs.length > 0) return packs;
}

throw new Error("npm_pack_json_shape_invalid");
}
18 changes: 5 additions & 13 deletions scripts/validate-npm-package.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { resolve } from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";

import { parseNpmPackJson } from "./lib/npm-pack-json.mjs";

const ROOT = resolve(fileURLToPath(new URL("..", import.meta.url)));
const NPM = process.platform === "win32" ? "npm.cmd" : "npm";

Expand All @@ -31,16 +33,6 @@ function fail(message) {
process.exit(1);
}

function parsePackJson(stdout) {
const text = String(stdout || "").trim();
const first = text.indexOf("[");
const last = text.lastIndexOf("]");
if (first === -1 || last === -1 || last < first) {
throw new Error("npm_pack_json_missing");
}
return JSON.parse(text.slice(first, last + 1));
}

function sameStrings(actual, expected) {
return actual.length === expected.length
&& actual.every((value, index) => value === expected[index]);
Expand All @@ -51,12 +43,12 @@ try {
assert.equal(pkg.name, "github-delivery");
assert.equal(pkg.private, undefined);
assert.deepEqual(pkg.bin, {
"github-delivery": "./scripts/github-delivery-cli.mjs",
"github-delivery": "scripts/github-delivery-cli.mjs",
});
assert.equal(pkg.license, "MIT");
assert.deepEqual(pkg.repository, {
type: "git",
url: "https://github.com/Wibias/github-delivery.git",
url: "git+https://github.com/Wibias/github-delivery.git",
});
assert.equal(pkg.publishConfig?.access, "public");
assert.equal(pkg.publishConfig?.registry, "https://registry.npmjs.org/");
Expand All @@ -83,7 +75,7 @@ try {
},
});
assert.equal(packResult.status, 0, packResult.stderr || packResult.stdout);
const [pack] = parsePackJson(packResult.stdout);
const [pack] = parseNpmPackJson(packResult.stdout);
assert(pack, "npm pack returned no package metadata");

const actual = pack.files.map((entry) => entry.path).sort();
Expand Down
30 changes: 16 additions & 14 deletions tests/unit/npm-package.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { join, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import test from "node:test";

import { parseNpmPackJson } from "../../scripts/lib/npm-pack-json.mjs";

const ROOT = resolve(import.meta.dirname, "../..");
const NPM = process.platform === "win32" ? "npm.cmd" : "npm";

Expand Down Expand Up @@ -43,36 +45,36 @@ function runNpm(args, cwd = ROOT) {
});
}

function parsePackJson(stdout) {
const text = String(stdout || "").trim();
const first = text.indexOf("[");
const last = text.lastIndexOf("]");
if (first === -1 || last === -1 || last < first) {
throw new Error(`npm_pack_json_missing:${text.slice(0, 400)}`);
}
return JSON.parse(text.slice(first, last + 1));
}

function dryRunPack() {
const result = runNpm(["pack", "--dry-run", "--json", "--ignore-scripts"]);
assert.equal(result.status, 0, result.stderr || result.stdout);
const [pack] = parsePackJson(result.stdout);
const [pack] = parseNpmPackJson(result.stdout);
assert(pack, "npm pack returned no package metadata");
return pack;
}

test("npm pack parser accepts npm 11 array and npm 12 keyed-object output", () => {
const pack = {
name: "github-delivery",
version: "0.5.0",
files: [{ path: "package.json" }],
};
assert.deepEqual(parseNpmPackJson(JSON.stringify([pack])), [pack]);
assert.deepEqual(parseNpmPackJson(JSON.stringify({ "github-delivery": pack })), [pack]);
});

test("package metadata exposes only the supported public npx bootstrap", () => {
const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));

assert.equal(pkg.name, "github-delivery");
assert.equal(pkg.private, undefined);
assert.deepEqual(pkg.bin, {
"github-delivery": "./scripts/github-delivery-cli.mjs",
"github-delivery": "scripts/github-delivery-cli.mjs",
});
assert.equal(pkg.license, "MIT");
assert.deepEqual(pkg.repository, {
type: "git",
url: "https://github.com/Wibias/github-delivery.git",
url: "git+https://github.com/Wibias/github-delivery.git",
});
assert.equal(pkg.publishConfig?.access, "public");
assert.equal(pkg.publishConfig?.registry, "https://registry.npmjs.org/");
Expand Down Expand Up @@ -123,7 +125,7 @@ test("a real packed tarball runs --help after an offline local install", () => {
packDir,
]);
assert.equal(packResult.status, 0, packResult.stderr || packResult.stdout);
const [pack] = parsePackJson(packResult.stdout);
const [pack] = parseNpmPackJson(packResult.stdout);
const tarball = join(packDir, pack.filename);

const installResult = runNpm([
Expand Down