@bonvoy/plugin-npm 0.2.0 → 0.3.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/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -65,21 +65,23 @@ var NpmPlugin = class {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
async publishPackages(context) {
|
|
68
|
-
const { packages, logger } = context;
|
|
68
|
+
const { packages, logger, preid } = context;
|
|
69
69
|
for (const pkg of packages) {
|
|
70
70
|
if (this.config.skipExisting && await this.isAlreadyPublished(pkg)) {
|
|
71
71
|
logger.info(`Skipping ${pkg.name}@${pkg.version} - already published`);
|
|
72
72
|
continue;
|
|
73
73
|
}
|
|
74
|
-
await this.publishPackage(pkg, logger);
|
|
74
|
+
await this.publishPackage(pkg, logger, preid);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
async publishPackage(pkg, logger) {
|
|
77
|
+
async publishPackage(pkg, logger, preid) {
|
|
78
78
|
const args = [];
|
|
79
79
|
if (this.config.dryRun) args.push("--dry-run");
|
|
80
80
|
args.push("--access", this.config.access);
|
|
81
81
|
if (this.config.provenance) args.push("--provenance");
|
|
82
82
|
if (this.config.registry !== "https://registry.npmjs.org") args.push("--registry", this.config.registry);
|
|
83
|
+
if (preid) args.push("--tag", preid);
|
|
84
|
+
else if (pkg.version.includes("-")) args.push("--tag", "next");
|
|
83
85
|
logger.info(`Publishing ${pkg.name}@${pkg.version}...`);
|
|
84
86
|
await this.ops.publish(args, pkg.path);
|
|
85
87
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/operations.ts","../src/npm.ts"],"sourcesContent":["import { execa } from 'execa';\n\nexport interface NpmOperations {\n publish(args: string[], cwd: string): Promise<void>;\n view(pkg: string, version: string): Promise<string | null>;\n packageExists(pkg: string): Promise<boolean>;\n hasToken(): Promise<boolean>;\n}\n\nexport const defaultNpmOperations: NpmOperations = {\n async publish(args, cwd) {\n await execa('npm', ['publish', ...args], { cwd, stdio: 'inherit' });\n },\n\n async view(pkg, version) {\n try {\n const result = await execa('npm', ['view', `${pkg}@${version}`, 'version'], {\n stdio: 'pipe',\n });\n return result.stdout.trim() || null;\n } catch {\n return null;\n }\n },\n\n /* c8 ignore start - real npm operations */\n async packageExists(pkg) {\n try {\n await execa('npm', ['view', pkg, 'name'], { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n },\n\n async hasToken() {\n return !!process.env.NPM_TOKEN || !!process.env.NODE_AUTH_TOKEN;\n },\n /* c8 ignore stop */\n};\n","import type { BonvoyPlugin, Context, PublishContext } from '@bonvoy/core';\n\nimport { defaultNpmOperations, type NpmOperations } from './operations.js';\n\nexport interface NpmPluginConfig {\n registry?: string;\n access?: 'public' | 'restricted';\n dryRun?: boolean;\n skipExisting?: boolean;\n provenance?: boolean;\n}\n\nexport default class NpmPlugin implements BonvoyPlugin {\n name = 'npm';\n\n private config: Required<NpmPluginConfig>;\n private ops: NpmOperations;\n\n constructor(config: NpmPluginConfig = {}, ops?: NpmOperations) {\n this.config = {\n registry: config.registry ?? 'https://registry.npmjs.org',\n access: config.access ?? 'public',\n dryRun: config.dryRun ?? false,\n skipExisting: config.skipExisting ?? true,\n provenance: config.provenance ?? true,\n };\n this.ops = ops ?? defaultNpmOperations;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Hook types are complex and vary by implementation\n apply(bonvoy: { hooks: { validateRepo: any; publish: any } }): void {\n bonvoy.hooks.validateRepo.tapPromise(this.name, async (context: Context) => {\n await this.validatePackages(context);\n });\n\n bonvoy.hooks.publish.tapPromise(this.name, async (context: PublishContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would publish packages to npm');\n return;\n }\n await this.publishPackages(context);\n });\n }\n\n private async publishPackages(context: PublishContext): Promise<void> {\n const { packages, logger } = context;\n\n for (const pkg of packages) {\n if (this.config.skipExisting && (await this.isAlreadyPublished(pkg))) {\n logger.info(`Skipping ${pkg.name}@${pkg.version} - already published`);\n continue;\n }\n\n await this.publishPackage(pkg, logger);\n }\n }\n\n private async publishPackage(\n pkg: { name: string; version: string; path: string },\n logger: PublishContext['logger'],\n ): Promise<void> {\n const args: string[] = [];\n\n if (this.config.dryRun) {\n args.push('--dry-run');\n }\n\n args.push('--access', this.config.access);\n\n if (this.config.provenance) {\n args.push('--provenance');\n }\n\n if (this.config.registry !== 'https://registry.npmjs.org') {\n args.push('--registry', this.config.registry);\n }\n\n logger.info(`Publishing ${pkg.name}@${pkg.version}...`);\n\n await this.ops.publish(args, pkg.path);\n }\n\n private async isAlreadyPublished(pkg: { name: string; version: string }): Promise<boolean> {\n const version = await this.ops.view(pkg.name, pkg.version);\n return version === pkg.version;\n }\n\n private async validatePackages(context: Context): Promise<void> {\n const { changedPackages, versions, logger } = context;\n if (!versions) return;\n\n const alreadyPublished: string[] = [];\n const needsToken: string[] = [];\n const hasToken = await this.ops.hasToken();\n\n for (const pkg of changedPackages) {\n const version = versions[pkg.name];\n if (!version) continue;\n\n // Check if version already exists\n const existingVersion = await this.ops.view(pkg.name, version);\n if (existingVersion === version) {\n alreadyPublished.push(`${pkg.name}@${version}`);\n continue;\n }\n\n // Check if package exists (for OIDC)\n if (!hasToken && this.config.provenance) {\n const exists = await this.ops.packageExists(pkg.name);\n if (!exists) {\n needsToken.push(pkg.name);\n }\n }\n }\n\n if (alreadyPublished.length > 0) {\n logger.error(`❌ npm versions already published: ${alreadyPublished.join(', ')}`);\n throw new Error(\n `Cannot release: npm versions already exist (${alreadyPublished.join(', ')}). Bump to a new version.`,\n );\n }\n\n if (needsToken.length > 0) {\n logger.error(`❌ First publish requires NPM_TOKEN: ${needsToken.join(', ')}`);\n throw new Error(\n `Cannot release with OIDC: packages don't exist on npm yet (${needsToken.join(', ')}). First publish requires NPM_TOKEN. Run: node scripts/publish-dummy-packages.mjs`,\n );\n }\n }\n}\n\nexport { defaultNpmOperations, type NpmOperations } from './operations.js';\n"],"mappings":";;;AASA,MAAa,uBAAsC;CACjD,MAAM,QAAQ,MAAM,KAAK;AACvB,QAAM,MAAM,OAAO,CAAC,WAAW,GAAG,KAAK,EAAE;GAAE;GAAK,OAAO;GAAW,CAAC;;CAGrE,MAAM,KAAK,KAAK,SAAS;AACvB,MAAI;AAIF,WAHe,MAAM,MAAM,OAAO;IAAC;IAAQ,GAAG,IAAI,GAAG;IAAW;IAAU,EAAE,EAC1E,OAAO,QACR,CAAC,EACY,OAAO,MAAM,IAAI;UACzB;AACN,UAAO;;;CAKX,MAAM,cAAc,KAAK;AACvB,MAAI;AACF,SAAM,MAAM,OAAO;IAAC;IAAQ;IAAK;IAAO,EAAE,EAAE,OAAO,QAAQ,CAAC;AAC5D,UAAO;UACD;AACN,UAAO;;;CAIX,MAAM,WAAW;AACf,SAAO,CAAC,CAAC,QAAQ,IAAI,aAAa,CAAC,CAAC,QAAQ,IAAI;;CAGnD;;;;AC3BD,IAAqB,YAArB,MAAuD;CACrD,OAAO;CAEP,AAAQ;CACR,AAAQ;CAER,YAAY,SAA0B,EAAE,EAAE,KAAqB;AAC7D,OAAK,SAAS;GACZ,UAAU,OAAO,YAAY;GAC7B,QAAQ,OAAO,UAAU;GACzB,QAAQ,OAAO,UAAU;GACzB,cAAc,OAAO,gBAAgB;GACrC,YAAY,OAAO,cAAc;GAClC;AACD,OAAK,MAAM,OAAO;;CAIpB,MAAM,QAA8D;AAClE,SAAO,MAAM,aAAa,WAAW,KAAK,MAAM,OAAO,YAAqB;AAC1E,SAAM,KAAK,iBAAiB,QAAQ;IACpC;AAEF,SAAO,MAAM,QAAQ,WAAW,KAAK,MAAM,OAAO,YAA4B;AAC5E,OAAI,QAAQ,UAAU;AACpB,YAAQ,OAAO,KAAK,6CAA6C;AACjE;;AAEF,SAAM,KAAK,gBAAgB,QAAQ;IACnC;;CAGJ,MAAc,gBAAgB,SAAwC;EACpE,MAAM,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/operations.ts","../src/npm.ts"],"sourcesContent":["import { execa } from 'execa';\n\nexport interface NpmOperations {\n publish(args: string[], cwd: string): Promise<void>;\n view(pkg: string, version: string): Promise<string | null>;\n packageExists(pkg: string): Promise<boolean>;\n hasToken(): Promise<boolean>;\n}\n\nexport const defaultNpmOperations: NpmOperations = {\n async publish(args, cwd) {\n await execa('npm', ['publish', ...args], { cwd, stdio: 'inherit' });\n },\n\n async view(pkg, version) {\n try {\n const result = await execa('npm', ['view', `${pkg}@${version}`, 'version'], {\n stdio: 'pipe',\n });\n return result.stdout.trim() || null;\n } catch {\n return null;\n }\n },\n\n /* c8 ignore start - real npm operations */\n async packageExists(pkg) {\n try {\n await execa('npm', ['view', pkg, 'name'], { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n },\n\n async hasToken() {\n return !!process.env.NPM_TOKEN || !!process.env.NODE_AUTH_TOKEN;\n },\n /* c8 ignore stop */\n};\n","import type { BonvoyPlugin, Context, PublishContext } from '@bonvoy/core';\n\nimport { defaultNpmOperations, type NpmOperations } from './operations.js';\n\nexport interface NpmPluginConfig {\n registry?: string;\n access?: 'public' | 'restricted';\n dryRun?: boolean;\n skipExisting?: boolean;\n provenance?: boolean;\n}\n\nexport default class NpmPlugin implements BonvoyPlugin {\n name = 'npm';\n\n private config: Required<NpmPluginConfig>;\n private ops: NpmOperations;\n\n constructor(config: NpmPluginConfig = {}, ops?: NpmOperations) {\n this.config = {\n registry: config.registry ?? 'https://registry.npmjs.org',\n access: config.access ?? 'public',\n dryRun: config.dryRun ?? false,\n skipExisting: config.skipExisting ?? true,\n provenance: config.provenance ?? true,\n };\n this.ops = ops ?? defaultNpmOperations;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Hook types are complex and vary by implementation\n apply(bonvoy: { hooks: { validateRepo: any; publish: any } }): void {\n bonvoy.hooks.validateRepo.tapPromise(this.name, async (context: Context) => {\n await this.validatePackages(context);\n });\n\n bonvoy.hooks.publish.tapPromise(this.name, async (context: PublishContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would publish packages to npm');\n return;\n }\n await this.publishPackages(context);\n });\n }\n\n private async publishPackages(context: PublishContext): Promise<void> {\n const { packages, logger, preid } = context;\n\n for (const pkg of packages) {\n if (this.config.skipExisting && (await this.isAlreadyPublished(pkg))) {\n logger.info(`Skipping ${pkg.name}@${pkg.version} - already published`);\n continue;\n }\n\n await this.publishPackage(pkg, logger, preid);\n }\n }\n\n private async publishPackage(\n pkg: { name: string; version: string; path: string },\n logger: PublishContext['logger'],\n preid?: string,\n ): Promise<void> {\n const args: string[] = [];\n\n if (this.config.dryRun) {\n args.push('--dry-run');\n }\n\n args.push('--access', this.config.access);\n\n if (this.config.provenance) {\n args.push('--provenance');\n }\n\n if (this.config.registry !== 'https://registry.npmjs.org') {\n args.push('--registry', this.config.registry);\n }\n\n // Use preid as npm tag for prereleases, fallback to 'next' if version contains '-'\n if (preid) {\n args.push('--tag', preid);\n } else if (pkg.version.includes('-')) {\n args.push('--tag', 'next');\n }\n\n logger.info(`Publishing ${pkg.name}@${pkg.version}...`);\n\n await this.ops.publish(args, pkg.path);\n }\n\n private async isAlreadyPublished(pkg: { name: string; version: string }): Promise<boolean> {\n const version = await this.ops.view(pkg.name, pkg.version);\n return version === pkg.version;\n }\n\n private async validatePackages(context: Context): Promise<void> {\n const { changedPackages, versions, logger } = context;\n if (!versions) return;\n\n const alreadyPublished: string[] = [];\n const needsToken: string[] = [];\n const hasToken = await this.ops.hasToken();\n\n for (const pkg of changedPackages) {\n const version = versions[pkg.name];\n if (!version) continue;\n\n // Check if version already exists\n const existingVersion = await this.ops.view(pkg.name, version);\n if (existingVersion === version) {\n alreadyPublished.push(`${pkg.name}@${version}`);\n continue;\n }\n\n // Check if package exists (for OIDC)\n if (!hasToken && this.config.provenance) {\n const exists = await this.ops.packageExists(pkg.name);\n if (!exists) {\n needsToken.push(pkg.name);\n }\n }\n }\n\n if (alreadyPublished.length > 0) {\n logger.error(`❌ npm versions already published: ${alreadyPublished.join(', ')}`);\n throw new Error(\n `Cannot release: npm versions already exist (${alreadyPublished.join(', ')}). Bump to a new version.`,\n );\n }\n\n if (needsToken.length > 0) {\n logger.error(`❌ First publish requires NPM_TOKEN: ${needsToken.join(', ')}`);\n throw new Error(\n `Cannot release with OIDC: packages don't exist on npm yet (${needsToken.join(', ')}). First publish requires NPM_TOKEN. Run: node scripts/publish-dummy-packages.mjs`,\n );\n }\n }\n}\n\nexport { defaultNpmOperations, type NpmOperations } from './operations.js';\n"],"mappings":";;;AASA,MAAa,uBAAsC;CACjD,MAAM,QAAQ,MAAM,KAAK;AACvB,QAAM,MAAM,OAAO,CAAC,WAAW,GAAG,KAAK,EAAE;GAAE;GAAK,OAAO;GAAW,CAAC;;CAGrE,MAAM,KAAK,KAAK,SAAS;AACvB,MAAI;AAIF,WAHe,MAAM,MAAM,OAAO;IAAC;IAAQ,GAAG,IAAI,GAAG;IAAW;IAAU,EAAE,EAC1E,OAAO,QACR,CAAC,EACY,OAAO,MAAM,IAAI;UACzB;AACN,UAAO;;;CAKX,MAAM,cAAc,KAAK;AACvB,MAAI;AACF,SAAM,MAAM,OAAO;IAAC;IAAQ;IAAK;IAAO,EAAE,EAAE,OAAO,QAAQ,CAAC;AAC5D,UAAO;UACD;AACN,UAAO;;;CAIX,MAAM,WAAW;AACf,SAAO,CAAC,CAAC,QAAQ,IAAI,aAAa,CAAC,CAAC,QAAQ,IAAI;;CAGnD;;;;AC3BD,IAAqB,YAArB,MAAuD;CACrD,OAAO;CAEP,AAAQ;CACR,AAAQ;CAER,YAAY,SAA0B,EAAE,EAAE,KAAqB;AAC7D,OAAK,SAAS;GACZ,UAAU,OAAO,YAAY;GAC7B,QAAQ,OAAO,UAAU;GACzB,QAAQ,OAAO,UAAU;GACzB,cAAc,OAAO,gBAAgB;GACrC,YAAY,OAAO,cAAc;GAClC;AACD,OAAK,MAAM,OAAO;;CAIpB,MAAM,QAA8D;AAClE,SAAO,MAAM,aAAa,WAAW,KAAK,MAAM,OAAO,YAAqB;AAC1E,SAAM,KAAK,iBAAiB,QAAQ;IACpC;AAEF,SAAO,MAAM,QAAQ,WAAW,KAAK,MAAM,OAAO,YAA4B;AAC5E,OAAI,QAAQ,UAAU;AACpB,YAAQ,OAAO,KAAK,6CAA6C;AACjE;;AAEF,SAAM,KAAK,gBAAgB,QAAQ;IACnC;;CAGJ,MAAc,gBAAgB,SAAwC;EACpE,MAAM,EAAE,UAAU,QAAQ,UAAU;AAEpC,OAAK,MAAM,OAAO,UAAU;AAC1B,OAAI,KAAK,OAAO,gBAAiB,MAAM,KAAK,mBAAmB,IAAI,EAAG;AACpE,WAAO,KAAK,YAAY,IAAI,KAAK,GAAG,IAAI,QAAQ,sBAAsB;AACtE;;AAGF,SAAM,KAAK,eAAe,KAAK,QAAQ,MAAM;;;CAIjD,MAAc,eACZ,KACA,QACA,OACe;EACf,MAAM,OAAiB,EAAE;AAEzB,MAAI,KAAK,OAAO,OACd,MAAK,KAAK,YAAY;AAGxB,OAAK,KAAK,YAAY,KAAK,OAAO,OAAO;AAEzC,MAAI,KAAK,OAAO,WACd,MAAK,KAAK,eAAe;AAG3B,MAAI,KAAK,OAAO,aAAa,6BAC3B,MAAK,KAAK,cAAc,KAAK,OAAO,SAAS;AAI/C,MAAI,MACF,MAAK,KAAK,SAAS,MAAM;WAChB,IAAI,QAAQ,SAAS,IAAI,CAClC,MAAK,KAAK,SAAS,OAAO;AAG5B,SAAO,KAAK,cAAc,IAAI,KAAK,GAAG,IAAI,QAAQ,KAAK;AAEvD,QAAM,KAAK,IAAI,QAAQ,MAAM,IAAI,KAAK;;CAGxC,MAAc,mBAAmB,KAA0D;AAEzF,SADgB,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,QAAQ,KACvC,IAAI;;CAGzB,MAAc,iBAAiB,SAAiC;EAC9D,MAAM,EAAE,iBAAiB,UAAU,WAAW;AAC9C,MAAI,CAAC,SAAU;EAEf,MAAM,mBAA6B,EAAE;EACrC,MAAM,aAAuB,EAAE;EAC/B,MAAM,WAAW,MAAM,KAAK,IAAI,UAAU;AAE1C,OAAK,MAAM,OAAO,iBAAiB;GACjC,MAAM,UAAU,SAAS,IAAI;AAC7B,OAAI,CAAC,QAAS;AAId,OADwB,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM,QAAQ,KACtC,SAAS;AAC/B,qBAAiB,KAAK,GAAG,IAAI,KAAK,GAAG,UAAU;AAC/C;;AAIF,OAAI,CAAC,YAAY,KAAK,OAAO,YAE3B;QAAI,CADW,MAAM,KAAK,IAAI,cAAc,IAAI,KAAK,CAEnD,YAAW,KAAK,IAAI,KAAK;;;AAK/B,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAO,MAAM,qCAAqC,iBAAiB,KAAK,KAAK,GAAG;AAChF,SAAM,IAAI,MACR,+CAA+C,iBAAiB,KAAK,KAAK,CAAC,2BAC5E;;AAGH,MAAI,WAAW,SAAS,GAAG;AACzB,UAAO,MAAM,uCAAuC,WAAW,KAAK,KAAK,GAAG;AAC5E,SAAM,IAAI,MACR,8DAA8D,WAAW,KAAK,KAAK,CAAC,mFACrF"}
|