@sebbo2002/semantic-release-jsr
Version:
Small `semantic-release` plugin, which adjusts the version in the `jsr.json` file and executes `jsr publish` to publish the module on jsr.io as well.
1 lines • 9.8 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["jsrPublish","publish","publishUtil"],"sources":["../src/utils.ts","../src/command.ts"],"sourcesContent":["import type {\n PrepareContext,\n PublishContext,\n VerifyConditionsContext,\n VerifyReleaseContext,\n} from 'semantic-release';\n\nimport SemanticReleaseError from '@semantic-release/error';\nimport { publish as jsrPublish } from 'jsr';\nimport { existsSync, mkdtempSync } from 'node:fs';\nimport { readFile, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\n\nimport type {\n NormalizedPluginConfig,\n PluginConfig,\n PublishResponse,\n PublishResponseContext,\n} from './types.ts';\n\nexport async function parseConfig(\n config: PluginConfig,\n context?: PrepareContext | PublishContext | VerifyConditionsContext,\n): Promise<NormalizedPluginConfig> {\n const cwd = config.cwd || context?.cwd || process.cwd();\n\n let pkgJsonPath: null | string =\n config.pkgJsonPath || join(cwd, 'package.json');\n if (!config.pkgJsonPath && !existsSync(pkgJsonPath)) {\n pkgJsonPath = null;\n }\n\n let name: string | undefined;\n const versionJsonPaths: string[] = [];\n const jsrJsonPath = join(cwd, 'jsr.json');\n const denoJsonPath = join(cwd, 'deno.json');\n if (existsSync(jsrJsonPath)) {\n versionJsonPaths.push(jsrJsonPath);\n }\n if (existsSync(denoJsonPath)) {\n versionJsonPaths.push(denoJsonPath);\n }\n if (pkgJsonPath) {\n versionJsonPaths.push(pkgJsonPath);\n }\n\n for (const path of versionJsonPaths) {\n const content = await readFile(path, 'utf8');\n const json = JSON.parse(content);\n if (!name && json.name) {\n name = json.name;\n }\n }\n if (!name) {\n throw new SemanticReleaseError(\n 'No name found in jsr.json or deno.json',\n 'ERR_NO_NAME',\n 'A package name is required to publish to JSR.io',\n );\n }\n\n const publishArgs = config.publishArgs?.slice(0) || [];\n if (\n (config.allowDirty === undefined || config.allowDirty) &&\n !publishArgs.includes('--allow-dirty')\n ) {\n publishArgs.push('--allow-dirty');\n }\n\n return {\n cwd,\n name,\n prepare: {\n versionJsonPaths,\n },\n publish: {\n binFolder: getTemporaryBinFolder(),\n canary: false,\n pkgJsonPath: pkgJsonPath,\n publishArgs,\n },\n };\n}\n\nlet temporaryBinFolder: string | undefined;\nexport function generatePublishResponse(\n config: NormalizedPluginConfig,\n context: PublishResponseContext,\n): PublishResponse {\n let url = `https://jsr.io/${config.name}/versions`;\n if (context.nextRelease) {\n url = `https://jsr.io/${config.name}@${context.nextRelease.version}`;\n }\n\n return {\n name: 'JSR.io',\n url,\n };\n}\n\nexport function getTemporaryBinFolder(): string {\n if (temporaryBinFolder) {\n return temporaryBinFolder;\n }\n\n const path = mkdtempSync(join(tmpdir(), 'semantic-release-jsr-'));\n temporaryBinFolder = path;\n return path;\n}\n\nexport async function publish(\n config: NormalizedPluginConfig,\n context: VerifyConditionsContext,\n): Promise<void> {\n context.logger.log(\n `Run jsr publish in ${config.cwd} with ${JSON.stringify(config.publish)}`,\n );\n\n const ms = Date.now();\n try {\n await jsrPublish(config.cwd, config.publish);\n context.logger.log(\n `jsr publish run successfully (took ${Date.now() - ms} ms)`,\n );\n } catch (error) {\n context.logger.log(`jsr publish failed after ${Date.now() - ms} ms:`);\n context.logger.error(error instanceof Error ? error.stack : error);\n throw error;\n }\n}\n\nexport async function removeTemporaryBinFolder() {\n if (temporaryBinFolder) {\n await rm(temporaryBinFolder, { force: true, recursive: true });\n temporaryBinFolder = undefined;\n }\n}\n\nexport async function updateVersionJson(\n file: string,\n context: VerifyReleaseContext,\n) {\n if (!context.nextRelease) {\n return;\n }\n\n context.logger.log(`Updating version in ${file}`);\n const nextVersion = context.nextRelease.version;\n const content = await readFile(file, 'utf8');\n const oldJson = JSON.parse(content);\n if (oldJson.version === nextVersion) {\n context.logger.log(`Skipped, ${file} is already up to date`);\n return;\n }\n\n const versionRegex = /^([\\s\\S]*\"version\"\\s*:\\s*\")([^\"]+)(\"[\\s\\S]*$)/;\n\n const updatedContent = content.replace(versionRegex, `$1${nextVersion}$3`);\n const newJson = JSON.parse(updatedContent);\n if (newJson.version !== nextVersion) {\n throw new SemanticReleaseError(\n `Failed to replace version in ${file}`,\n 'ERR_VERSION_REPLACE',\n `The version in ${file} could not be updated to ${nextVersion}. Please check if the file ` +\n `is valid JSON and contains a \"version\" field.`,\n );\n }\n\n await writeFile(file, updatedContent, 'utf8');\n context.logger.log(`Wrote new version to ${file}`);\n}\n","import type {\n FailContext,\n PrepareContext,\n PublishContext,\n SuccessContext,\n VerifyConditionsContext,\n} from 'semantic-release';\n\nimport type { PluginConfig, PublishResponse } from './types.ts';\n\nimport {\n generatePublishResponse,\n parseConfig,\n publish as publishUtil,\n removeTemporaryBinFolder,\n updateVersionJson,\n} from './utils.ts';\n\nexport async function fail(pluginConfig: PluginConfig, context: FailContext) {\n context.logger.log('Removing temporary folder');\n await removeTemporaryBinFolder();\n}\n\nexport async function prepare(\n pluginConfig: PluginConfig,\n context: PrepareContext,\n): Promise<void> {\n const config = await parseConfig(pluginConfig, context);\n\n for (const file of config.prepare.versionJsonPaths) {\n await updateVersionJson(file, context);\n }\n}\n\nexport async function publish(\n pluginConfig: PluginConfig,\n context: PublishContext,\n): Promise<boolean | PublishResponse> {\n const config = await parseConfig(pluginConfig, context);\n await publishUtil(config, context);\n return generatePublishResponse(config, context);\n}\n\nexport async function success(\n pluginConfig: PluginConfig,\n context: SuccessContext,\n) {\n context.logger.log('Removing temporary folder');\n await removeTemporaryBinFolder();\n}\n\nexport async function verifyConditions(\n pluginConfig: PluginConfig,\n context: VerifyConditionsContext,\n): Promise<void> {\n const config = await parseConfig(pluginConfig, context);\n context.logger.info('Run jsr publish --dry-run to verify configuration');\n\n await publishUtil(\n {\n ...config,\n publish: {\n ...config.publish,\n publishArgs: [...config.publish.publishArgs, '--dry-run'],\n },\n },\n context,\n );\n}\n"],"mappings":"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"}