@packtory/bootstrap-npm-package 0.0.1 → 0.0.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2023]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,69 @@
1
+ const registryUrl = 'https://registry.npmjs.org/';
2
+ const workaroundUrl = 'https://github.com/npm/cli/issues/8544';
3
+ const distTag = 'bootstrap';
4
+ const placeholderVersion = '0.0.1';
5
+ const placeholderLicense = 'MIT';
6
+ function buildManifestDescription(packageName) {
7
+ return (`Placeholder claiming the npm package name "${packageName}" so a trusted publisher ` +
8
+ `can be configured. See ${workaroundUrl}.`);
9
+ }
10
+ function buildDeprecationMessage() {
11
+ return `Placeholder published as a workaround so a Trusted Publisher could be configured. See ${workaroundUrl}.`;
12
+ }
13
+ function buildManifest(packageName) {
14
+ return {
15
+ name: packageName,
16
+ version: placeholderVersion,
17
+ description: buildManifestDescription(packageName),
18
+ license: placeholderLicense,
19
+ deprecated: buildDeprecationMessage()
20
+ };
21
+ }
22
+ function buildReadme(packageName) {
23
+ return [
24
+ `# ${packageName}`,
25
+ '',
26
+ `This version is a placeholder published only to claim the npm name \`${packageName}\` so a Trusted Publisher`,
27
+ 'can subsequently be configured for it. It contains no real package content and is published already',
28
+ 'deprecated.',
29
+ '',
30
+ `Workaround context: ${workaroundUrl}`,
31
+ ''
32
+ ].join('\n');
33
+ }
34
+ function buildTrustedPublisherUrl(packageName) {
35
+ return `https://www.npmjs.com/package/${packageName}/access`;
36
+ }
37
+ function buildAuthenticatedMessage(username) {
38
+ return username === undefined || username.length === 0
39
+ ? 'Authenticated to npm'
40
+ : `Authenticated to npm as ${username}`;
41
+ }
42
+ function buildPublishLogMessage(packageName, version) {
43
+ return `Publishing ${packageName}@${version} (already deprecated) under dist-tag ${distTag}`;
44
+ }
45
+ export function createBootstrapRunner(dependencies) {
46
+ const { placeholderTarballBuilder, webLogin, packagePublication, promptForOneTimePassword, log } = dependencies;
47
+ return {
48
+ async run(input) {
49
+ const manifest = buildManifest(input.packageName);
50
+ const readmeContent = buildReadme(input.packageName);
51
+ log(`Building placeholder tarball for ${input.packageName}@${manifest.version}`);
52
+ const tarball = await placeholderTarballBuilder.build({ manifest, readmeContent });
53
+ log('Opening browser for npm web login');
54
+ const session = await webLogin.login({ registryUrl, hostname: input.hostname });
55
+ log(buildAuthenticatedMessage(session.username));
56
+ log(buildPublishLogMessage(input.packageName, manifest.version));
57
+ await packagePublication.publish({
58
+ manifest,
59
+ tarball,
60
+ token: session.token,
61
+ registryUrl,
62
+ distTag,
63
+ promptForOneTimePassword
64
+ });
65
+ log(`Done. Configure the Trusted Publisher at ${buildTrustedPublisherUrl(input.packageName)}`);
66
+ }
67
+ };
68
+ }
69
+ //# sourceMappingURL=bootstrap-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-runner.js","sourceRoot":"","sources":["../../../../source/bootstrap-npm-package/bootstrap-runner.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,GAAG,6BAA6B,CAAC;AAClD,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAC/D,MAAM,OAAO,GAAG,WAAW,CAAC;AAC5B,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC,SAAS,wBAAwB,CAAC,WAAmB;IACjD,OAAO,CACH,8CAA8C,WAAW,2BAA2B;QACpF,0BAA0B,aAAa,GAAG,CAC7C,CAAC;AACN,CAAC;AAED,SAAS,uBAAuB;IAC5B,OAAO,yFAAyF,aAAa,GAAG,CAAC;AACrH,CAAC;AAED,SAAS,aAAa,CAAC,WAAmB;IACtC,OAAO;QACH,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,kBAAkB;QAC3B,WAAW,EAAE,wBAAwB,CAAC,WAAW,CAAC;QAClD,OAAO,EAAE,kBAAkB;QAC3B,UAAU,EAAE,uBAAuB,EAAE;KACxC,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAAC,WAAmB;IACpC,OAAO;QACH,KAAK,WAAW,EAAE;QAClB,EAAE;QACF,wEAAwE,WAAW,2BAA2B;QAC9G,qGAAqG;QACrG,aAAa;QACb,EAAE;QACF,uBAAuB,aAAa,EAAE;QACtC,EAAE;KACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,wBAAwB,CAAC,WAAmB;IACjD,OAAO,iCAAiC,WAAW,SAAS,CAAC;AACjE,CAAC;AAED,SAAS,yBAAyB,CAAC,QAA4B;IAC3D,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAClD,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,2BAA2B,QAAQ,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,sBAAsB,CAAC,WAAmB,EAAE,OAAe;IAChE,OAAO,cAAc,WAAW,IAAI,OAAO,wCAAwC,OAAO,EAAE,CAAC;AACjG,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAAmD;IACrF,MAAM,EAAE,yBAAyB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC;IAEhH,OAAO;QACH,KAAK,CAAC,GAAG,CAAC,KAAK;YACX,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAClD,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAErD,GAAG,CAAC,oCAAoC,KAAK,CAAC,WAAW,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;YACjF,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;YAEnF,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChF,GAAG,CAAC,yBAAyB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAEjD,GAAG,CAAC,sBAAsB,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YACjE,MAAM,kBAAkB,CAAC,OAAO,CAAC;gBAC7B,QAAQ;gBACR,OAAO;gBACP,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW;gBACX,OAAO;gBACP,wBAAwB;aAC3B,CAAC,CAAC;YAEH,GAAG,CAAC,4CAA4C,wBAAwB,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,42 @@
1
+ function isRecord(value) {
2
+ return value instanceof Object && !Array.isArray(value);
3
+ }
4
+ function isOneTimePasswordRequiredError(error) {
5
+ return isRecord(error) && error.code === 'EOTP';
6
+ }
7
+ function extractWebOtpUrls(error) {
8
+ const { body } = error;
9
+ if (!isRecord(body)) {
10
+ return undefined;
11
+ }
12
+ const { authUrl, doneUrl } = body;
13
+ if (typeof authUrl !== 'string' || typeof doneUrl !== 'string') {
14
+ return undefined;
15
+ }
16
+ return { authUrl, doneUrl };
17
+ }
18
+ export function createPackagePublication(dependencies) {
19
+ const { publish } = dependencies;
20
+ return {
21
+ async publish(input) {
22
+ const baseOptions = {
23
+ defaultTag: input.distTag,
24
+ access: 'public',
25
+ registry: input.registryUrl,
26
+ forceAuth: { token: input.token },
27
+ authType: 'web'
28
+ };
29
+ try {
30
+ await publish(input.manifest, input.tarball, baseOptions);
31
+ }
32
+ catch (error) {
33
+ if (!isOneTimePasswordRequiredError(error)) {
34
+ throw error;
35
+ }
36
+ const otp = await input.promptForOneTimePassword(extractWebOtpUrls(error));
37
+ await publish(input.manifest, input.tarball, { ...baseOptions, otp });
38
+ }
39
+ }
40
+ };
41
+ }
42
+ //# sourceMappingURL=package-publication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-publication.js","sourceRoot":"","sources":["../../../../source/bootstrap-npm-package/package-publication.ts"],"names":[],"mappings":"AA+CA,SAAS,QAAQ,CAAC,KAAc;IAC5B,OAAO,KAAK,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,8BAA8B,CAAC,KAAc;IAClD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;AACpD,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAkC;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAClC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7D,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,YAAsD;IAC3F,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IAEjC,OAAO;QACH,KAAK,CAAC,OAAO,CAAC,KAAK;YACf,MAAM,WAAW,GAAyB;gBACtC,UAAU,EAAE,KAAK,CAAC,OAAO;gBACzB,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,KAAK,CAAC,WAAW;gBAC3B,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;gBACjC,QAAQ,EAAE,KAAK;aAClB,CAAC;YAEF,IAAI,CAAC;gBACD,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,8BAA8B,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,KAAK,CAAC;gBAChB,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3E,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1E,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,47 @@
1
+ const staticFileModificationTimeEpochMilliseconds = 0;
2
+ const regularFileMode = 420;
3
+ const gzipHeaderOperatingSystemFieldIndex = 9;
4
+ const gzipHeaderOperatingSystemUnknown = 255;
5
+ const manifestJsonIndent = 2;
6
+ function normalizeGzipHeader(data) {
7
+ const normalized = Buffer.from(data);
8
+ normalized[gzipHeaderOperatingSystemFieldIndex] = gzipHeaderOperatingSystemUnknown;
9
+ return normalized;
10
+ }
11
+ function serializeManifest(manifest) {
12
+ return `${JSON.stringify(manifest, null, manifestJsonIndent)}\n`;
13
+ }
14
+ function appendFile(pack, name, content) {
15
+ pack.entry({
16
+ name,
17
+ size: Buffer.byteLength(content),
18
+ mtime: new Date(staticFileModificationTimeEpochMilliseconds),
19
+ mode: regularFileMode
20
+ }, content);
21
+ }
22
+ function toBuffer(chunk) {
23
+ return Buffer.from(chunk);
24
+ }
25
+ async function collectGzippedTarball(pack, createGzip) {
26
+ const tarballStream = pack.pipe(createGzip());
27
+ const chunks = [];
28
+ for await (const chunk of tarballStream) {
29
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- gzip stream yields buffers in this usage
30
+ chunks.push(toBuffer(chunk));
31
+ }
32
+ return normalizeGzipHeader(Buffer.concat(chunks));
33
+ }
34
+ export function createPlaceholderTarballBuilder(dependencies) {
35
+ const { createGzip, createPack } = dependencies;
36
+ return {
37
+ async build(input) {
38
+ const pack = createPack();
39
+ const result = collectGzippedTarball(pack, createGzip);
40
+ appendFile(pack, 'package/package.json', serializeManifest(input.manifest));
41
+ appendFile(pack, 'package/readme.md', input.readmeContent);
42
+ pack.finalize();
43
+ return result;
44
+ }
45
+ };
46
+ }
47
+ //# sourceMappingURL=placeholder-tarball.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder-tarball.js","sourceRoot":"","sources":["../../../../source/bootstrap-npm-package/placeholder-tarball.ts"],"names":[],"mappings":"AAyBA,MAAM,2CAA2C,GAAG,CAAC,CAAC;AACtD,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,mCAAmC,GAAG,CAAC,CAAC;AAC9C,MAAM,gCAAgC,GAAG,GAAG,CAAC;AAC7C,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,SAAS,mBAAmB,CAAC,IAAY;IACrC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,UAAU,CAAC,mCAAmC,CAAC,GAAG,gCAAgC,CAAC;IACnF,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,SAAS,iBAAiB,CAAC,QAA6B;IACpD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC;AACrE,CAAC;AAED,SAAS,UAAU,CAAC,IAAc,EAAE,IAAY,EAAE,OAAe;IAC7D,IAAI,CAAC,KAAK,CACN;QACI,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;QAChC,KAAK,EAAE,IAAI,IAAI,CAAC,2CAA2C,CAAC;QAC5D,IAAI,EAAE,eAAe;KACxB,EACD,OAAO,CACV,CAAC;AACN,CAAC;AAED,SAAS,QAAQ,CAAC,KAAsB;IACpC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,IAAc,EAAE,UAAkC;IACnF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,aAAuC,EAAE,CAAC;QAChE,mHAAmH;QACnH,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAwB,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC3C,YAA6D;IAE7D,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC;IAEhD,OAAO;QACH,KAAK,CAAC,KAAK,CAAC,KAAK;YACb,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,qBAAqB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACvD,UAAU,CAAC,IAAI,EAAE,sBAAsB,EAAE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5E,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;YAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO,MAAM,CAAC;QAClB,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,13 @@
1
+ export function createWebLogin(dependencies) {
2
+ const { loginWeb, openInBrowser } = dependencies;
3
+ return {
4
+ async login(input) {
5
+ return loginWeb(openInBrowser, {
6
+ registry: input.registryUrl,
7
+ hostname: input.hostname,
8
+ authType: 'web'
9
+ });
10
+ }
11
+ };
12
+ }
13
+ //# sourceMappingURL=web-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-login.js","sourceRoot":"","sources":["../../../../source/bootstrap-npm-package/web-login.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,cAAc,CAAC,YAA4C;IACvE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,YAAY,CAAC;IAEjD,OAAO;QACH,KAAK,CAAC,KAAK,CAAC,KAAK;YACb,OAAO,QAAQ,CAAC,aAAa,EAAE;gBAC3B,QAAQ,EAAE,KAAK,CAAC,WAAW;gBAC3B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,KAAK;aAClB,CAAC,CAAC;QACP,CAAC;KACJ,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,46 @@
1
1
  {
2
- "name": "@packtory/bootstrap-npm-package",
3
- "version": "0.0.1",
4
- "description": "Placeholder claiming the npm package name \"@packtory/bootstrap-npm-package\" so a trusted publisher can be configured. See https://github.com/npm/cli/issues/8544.",
5
- "license": "MIT",
6
- "deprecated": "Placeholder published as a workaround so a Trusted Publisher could be configured. See https://github.com/npm/cli/issues/8544."
7
- }
2
+ "author": "Mathias Schreck <schreck.mathias@gmail.com>",
3
+ "bin": {
4
+ "bootstrap-npm-package": "./packages/bootstrap-npm-package/bootstrap-npm-package.entry-point.js"
5
+ },
6
+ "contributors": [
7
+ "Christian Rackerseder <github@echooff.de>"
8
+ ],
9
+ "dependencies": {
10
+ "cmd-ts": "0.15.0",
11
+ "libnpmpublish": "11.2.0",
12
+ "npm-profile": "13.0.0",
13
+ "open": "11.0.0",
14
+ "tar-stream": "3.1.8"
15
+ },
16
+ "description": "Claim a brand-new npm name so a Trusted Publisher can be configured for it (workaround for npm/cli#8544).",
17
+ "engines": {
18
+ "node": "^24 || ^26"
19
+ },
20
+ "exports": {
21
+ "./package.json": "./package.json"
22
+ },
23
+ "keywords": [
24
+ "bundler",
25
+ "bundling",
26
+ "modules",
27
+ "monorepo",
28
+ "npm",
29
+ "package",
30
+ "packaging",
31
+ "publish",
32
+ "publishing",
33
+ "versioning"
34
+ ],
35
+ "license": "MIT",
36
+ "name": "@packtory/bootstrap-npm-package",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+ssh://git@github.com/enormora/packtory.git"
40
+ },
41
+ "sideEffects": [
42
+ "./packages/bootstrap-npm-package/bootstrap-npm-package.entry-point.js"
43
+ ],
44
+ "type": "module",
45
+ "version": "0.0.2"
46
+ }
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ import os from 'node:os';
3
+ import readline from 'node:readline/promises';
4
+ import zlib from 'node:zlib';
5
+ import { binary, command, positional, run, string } from 'cmd-ts';
6
+ import { publish as libnpmpublishPublish } from 'libnpmpublish';
7
+ import { loginWeb, webAuthOpener } from 'npm-profile';
8
+ import open from 'open';
9
+ import tar from 'tar-stream';
10
+ import { createBootstrapRunner } from "../../bootstrap-npm-package/bootstrap-runner.js";
11
+ import { createPackagePublication } from "../../bootstrap-npm-package/package-publication.js";
12
+ import { createPlaceholderTarballBuilder } from "../../bootstrap-npm-package/placeholder-tarball.js";
13
+ import { createWebLogin } from "../../bootstrap-npm-package/web-login.js";
14
+ const npmRegistryUrl = 'https://registry.npmjs.org/';
15
+ async function openInBrowser(loginUrl) {
16
+ await open(loginUrl, { wait: false });
17
+ }
18
+ async function promptForOneTimePasswordViaTerminal() {
19
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
20
+ throw new Error('The npm registry requested a one-time password, but stdin is not an interactive terminal');
21
+ }
22
+ const prompt = readline.createInterface({ input: process.stdin, output: process.stdout });
23
+ try {
24
+ const answer = await prompt.question('Registry one-time password: ');
25
+ const trimmed = answer.trim();
26
+ if (trimmed.length === 0) {
27
+ throw new Error('One-time password input was empty');
28
+ }
29
+ return trimmed;
30
+ }
31
+ finally {
32
+ prompt.close();
33
+ }
34
+ }
35
+ async function promptForOneTimePasswordViaBrowser(urls) {
36
+ process.stdout.write('Opening browser to authorize the publish; complete the prompt in your browser…\n');
37
+ const result = await webAuthOpener(openInBrowser, urls.authUrl, urls.doneUrl, { registry: npmRegistryUrl });
38
+ return result.token;
39
+ }
40
+ async function promptForOneTimePassword(urls) {
41
+ if (urls === undefined) {
42
+ return promptForOneTimePasswordViaTerminal();
43
+ }
44
+ return promptForOneTimePasswordViaBrowser(urls);
45
+ }
46
+ function createDependencies() {
47
+ return {
48
+ placeholderTarballBuilder: createPlaceholderTarballBuilder({
49
+ createGzip: zlib.createGzip,
50
+ createPack: tar.pack
51
+ }),
52
+ webLogin: createWebLogin({ loginWeb, openInBrowser }),
53
+ packagePublication: createPackagePublication({ publish: libnpmpublishPublish }),
54
+ promptForOneTimePassword,
55
+ log: (message) => {
56
+ process.stdout.write(`${message}\n`);
57
+ }
58
+ };
59
+ }
60
+ function createComposedRunner() {
61
+ return createBootstrapRunner(createDependencies());
62
+ }
63
+ const bootstrapCommand = command({
64
+ name: 'bootstrap-npm-package',
65
+ description: 'Publishes a deprecated placeholder version 0.0.1 of a brand-new npm package so ' +
66
+ 'a Trusted Publisher can subsequently be configured for the name.',
67
+ args: {
68
+ packageName: positional({ type: string, displayName: 'package-name' })
69
+ },
70
+ async handler(args) {
71
+ const runner = createComposedRunner();
72
+ const input = { packageName: args.packageName, hostname: os.hostname() };
73
+ await runner.run(input);
74
+ }
75
+ });
76
+ await run(binary(bootstrapCommand), process.argv);
77
+ //# sourceMappingURL=bootstrap-npm-package.entry-point.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-npm-package.entry-point.js","sourceRoot":"","sources":["../../../../../source/packages/bootstrap-npm-package/bootstrap-npm-package.entry-point.ts"],"names":[],"mappings":"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"}
package/readme.md CHANGED
@@ -1,7 +1,49 @@
1
1
  # @packtory/bootstrap-npm-package
2
2
 
3
- This version is a placeholder published only to claim the npm name `@packtory/bootstrap-npm-package` so a Trusted Publisher
4
- can subsequently be configured for it. It contains no real package content and is published already
5
- deprecated.
3
+ **Claim a brand-new npm package name so a Trusted Publisher can be configured for it**
6
4
 
7
- Workaround context: https://github.com/npm/cli/issues/8544
5
+ npm's Trusted Publisher configuration UI is reachable only on the per-package settings page, which means a Trusted Publisher cannot be configured before the package exists on the registry. See [`npm/cli#8544`](https://github.com/npm/cli/issues/8544) for tracking.
6
+
7
+ This tool publishes a placeholder `0.0.1` for a brand-new npm name on `registry.npmjs.org` so the per-package settings page becomes reachable. The placeholder is marked deprecated in the manifest and shipped under the `bootstrap` dist-tag, so `latest` stays empty until the first real release. After running it, configure the Trusted Publisher in the npm UI and proceed with normal OIDC-backed publishes for `0.0.2` and later.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install -g @packtory/bootstrap-npm-package
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ bootstrap-npm-package <package-name>
19
+ ```
20
+
21
+ Example for a brand-new scoped package:
22
+
23
+ ```bash
24
+ bootstrap-npm-package @your-scope/new-package
25
+ ```
26
+
27
+ The tool will:
28
+
29
+ 1. Build a placeholder tarball containing only a minimal `package.json` and `readme.md` that explains the workaround.
30
+ 2. Open your browser for the standard npm web login flow and wait for you to complete it (2FA included).
31
+ 3. Publish version `0.0.1` against `registry.npmjs.org` under the `bootstrap` dist-tag so it never sits on `latest`. The manifest carries the deprecation message in the same write, so a separate `npm deprecate` is not needed.
32
+ 4. Print the URL for the new package's Trusted Publisher settings page.
33
+
34
+ After the tool exits, configure the Trusted Publisher in the npm UI, then publish `0.0.2` (and later) from CI via OIDC with full provenance.
35
+
36
+ ## Argument
37
+
38
+ - `<package-name>`: required. The npm name to claim, scoped (e.g. `@scope/foo`) or unscoped.
39
+
40
+ The registry, the workaround URL embedded in the placeholder, and the placeholder's dist-tag are intentionally not configurable — the tool is single-purpose and targets `registry.npmjs.org`, the `npm/cli#8544` tracking issue, and the `bootstrap` dist-tag.
41
+
42
+ ## What gets published
43
+
44
+ The tarball contains exactly two files:
45
+
46
+ - `package/package.json` with the minimal fields `name`, `version`, `description`, `license`, `deprecated`.
47
+ - `package/readme.md` explaining that the version is a placeholder and pointing at the workaround context.
48
+
49
+ The published version has no provenance attestation, no SBOM, and no runtime content. The `deprecated` field is set on publish so consumers see the warning even if they attempt to install it explicitly.
package/sbom.cdx.json ADDED
@@ -0,0 +1,118 @@
1
+ {
2
+ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
3
+ "bomFormat": "CycloneDX",
4
+ "specVersion": "1.6",
5
+ "version": 1,
6
+ "metadata": {
7
+ "tools": {
8
+ "components": [
9
+ {
10
+ "type": "application",
11
+ "name": "packtory",
12
+ "version": "0.0.29"
13
+ }
14
+ ]
15
+ },
16
+ "component": {
17
+ "type": "library",
18
+ "name": "@packtory/bootstrap-npm-package",
19
+ "version": "0.0.2",
20
+ "bom-ref": "pkg:npm/@packtory/bootstrap-npm-package@0.0.2",
21
+ "purl": "pkg:npm/@packtory/bootstrap-npm-package@0.0.2"
22
+ }
23
+ },
24
+ "components": [
25
+ {
26
+ "type": "library",
27
+ "name": "cmd-ts",
28
+ "version": "0.15.0",
29
+ "bom-ref": "pkg:npm/cmd-ts@0.15.0",
30
+ "scope": "required",
31
+ "licenses": [
32
+ {
33
+ "expression": "MIT"
34
+ }
35
+ ],
36
+ "purl": "pkg:npm/cmd-ts@0.15.0"
37
+ },
38
+ {
39
+ "type": "library",
40
+ "name": "libnpmpublish",
41
+ "version": "11.2.0",
42
+ "bom-ref": "pkg:npm/libnpmpublish@11.2.0",
43
+ "scope": "required",
44
+ "licenses": [
45
+ {
46
+ "expression": "ISC"
47
+ }
48
+ ],
49
+ "purl": "pkg:npm/libnpmpublish@11.2.0"
50
+ },
51
+ {
52
+ "type": "library",
53
+ "name": "npm-profile",
54
+ "version": "13.0.0",
55
+ "bom-ref": "pkg:npm/npm-profile@13.0.0",
56
+ "scope": "required",
57
+ "licenses": [
58
+ {
59
+ "expression": "ISC"
60
+ }
61
+ ],
62
+ "purl": "pkg:npm/npm-profile@13.0.0"
63
+ },
64
+ {
65
+ "type": "library",
66
+ "name": "open",
67
+ "version": "11.0.0",
68
+ "bom-ref": "pkg:npm/open@11.0.0",
69
+ "scope": "required",
70
+ "licenses": [
71
+ {
72
+ "expression": "MIT"
73
+ }
74
+ ],
75
+ "purl": "pkg:npm/open@11.0.0"
76
+ },
77
+ {
78
+ "type": "library",
79
+ "name": "tar-stream",
80
+ "version": "3.1.8",
81
+ "bom-ref": "pkg:npm/tar-stream@3.1.8",
82
+ "scope": "required",
83
+ "licenses": [
84
+ {
85
+ "expression": "MIT"
86
+ }
87
+ ],
88
+ "purl": "pkg:npm/tar-stream@3.1.8"
89
+ }
90
+ ],
91
+ "dependencies": [
92
+ {
93
+ "ref": "pkg:npm/@packtory/bootstrap-npm-package@0.0.2",
94
+ "dependsOn": [
95
+ "pkg:npm/cmd-ts@0.15.0",
96
+ "pkg:npm/libnpmpublish@11.2.0",
97
+ "pkg:npm/npm-profile@13.0.0",
98
+ "pkg:npm/open@11.0.0",
99
+ "pkg:npm/tar-stream@3.1.8"
100
+ ]
101
+ },
102
+ {
103
+ "ref": "pkg:npm/cmd-ts@0.15.0"
104
+ },
105
+ {
106
+ "ref": "pkg:npm/libnpmpublish@11.2.0"
107
+ },
108
+ {
109
+ "ref": "pkg:npm/npm-profile@13.0.0"
110
+ },
111
+ {
112
+ "ref": "pkg:npm/open@11.0.0"
113
+ },
114
+ {
115
+ "ref": "pkg:npm/tar-stream@3.1.8"
116
+ }
117
+ ]
118
+ }