@jsenv/package-publish 1.6.2 → 1.7.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.
File without changes
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Package publish [![npm package](https://img.shields.io/npm/v/@jsenv/package-publish.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/package-publish) [![github main](https://github.com/jsenv/package-publish/workflows/main/badge.svg)](https://github.com/jsenv/package-publish/actions?workflow=main) [![codecov coverage](https://codecov.io/gh/jsenv/package-publish/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/package-publish)
2
+
3
+ Publish package to one or many registry.
4
+
5
+ # Presentation
6
+
7
+ - Can be used to automate "npm publish" during a workflow
8
+ - Allows to publish on many registries: both npm and github registries for instance.
9
+
10
+ You can use it inside a GitHub workflow or inside any other continuous environment like Travis or Jenkins.
11
+
12
+ Screenshot taken inside a github workflow when the package.json version is already published: ![already published github workflow screenshot](./docs/already-published-github-workflow-screenshot.png)
13
+
14
+ Screenshot taken inside a github workflow when the package.json version is not published: ![publishing github workflow screenshot](./docs/publishing-github-workflow-screenshot.png)
15
+
16
+ This package is using itself to be published on NPM. It is done during ["publish package" step](https://github.com/jsenv/package-publish/blob/0170a5c859c4732203ff2f3e70b85e705396ccc7/.github/workflows/main.yml#L70-L74) in GitHub worflow.
17
+
18
+ # Installation
19
+
20
+ ```console
21
+ npm install --save-dev @jsenv/package-publish
22
+ ```
23
+
24
+ # Documentation
25
+
26
+ The api consist into one function called _publishPackage_.
27
+
28
+ _publishPackage_ is an async function publishing a package on one or many registries.
29
+
30
+ ```js
31
+ import { publishPackage } from "@jsenv/package-publish"
32
+
33
+ const publishReport = await publishPackage({
34
+ projectDirectoryUrl: new URL('./', import.meta.url)
35
+ registriesConfig: {
36
+ "https://registry.npmjs.org": {
37
+ token: process.env.NPM_TOKEN,
38
+ },
39
+ "https://npm.pkg.github.com": {
40
+ token: process.env.GITHUB_TOKEN,
41
+ },
42
+ },
43
+ })
44
+ ```
45
+
46
+ ## projectDirectoryUrl
47
+
48
+ _projectDirectoryUrl_ parameter is a string leading to a directory containing the package.json.
49
+
50
+ This parameter is **required**.
51
+
52
+ ## registriesConfig
53
+
54
+ _registriesConfig_ parameter is an object configuring on which registries you want to publish your package.
55
+
56
+ This parameter is **required**.
57
+
58
+ ## logLevel
59
+
60
+ _logLevel_ parameter is a string controlling verbosity of logs during the function execution.
61
+
62
+ This parameter is optional.
63
+
64
+ — see also https://github.com/jsenv/jsenv-logger#loglevel
package/main.js ADDED
@@ -0,0 +1,8 @@
1
+ /*
2
+ * This file is the entry point of this codebase
3
+ * - It is responsible to export the documented API
4
+ * - It should be kept simple (just re-export) to help reader to
5
+ * discover codebase progressively
6
+ */
7
+
8
+ export { publishPackage } from "./src/publishPackage.js"
package/package.json CHANGED
@@ -1,64 +1,58 @@
1
1
  {
2
2
  "name": "@jsenv/package-publish",
3
- "version": "1.6.2",
3
+ "version": "1.7.0",
4
4
  "description": "Publish package to one or many registry.",
5
5
  "license": "MIT",
6
+ "author": {
7
+ "name": "dmail",
8
+ "email": "dmaillard06@gmail.com",
9
+ "url": "https://twitter.com/damienmaillard"
10
+ },
6
11
  "repository": {
7
12
  "type": "git",
8
- "url": "https://github.com/jsenv/jsenv-package-publish"
13
+ "url": "https://github.com/jsenv/package-publish"
9
14
  },
10
15
  "engines": {
11
- "node": ">=14.17.0"
16
+ "node": ">=16.13.0"
12
17
  },
13
18
  "publishConfig": {
14
- "access": "public"
19
+ "access": "public",
20
+ "registry": "https://registry.npmjs.org"
15
21
  },
16
22
  "type": "module",
17
23
  "exports": {
18
24
  ".": {
19
- "import": "./index.js",
20
- "require": "./dist/commonjs/jsenv_package_publish.cjs"
25
+ "import": "./main.js"
21
26
  },
22
27
  "./*": "./*"
23
28
  },
24
- "main": "dist/commonjs/jsenv_package_publish.cjs",
29
+ "main": "./main.js",
25
30
  "files": [
26
- "/dist/",
27
31
  "/src/",
28
- "/index.js"
32
+ "/main.js"
29
33
  ],
30
34
  "scripts": {
31
- "eslint-check": "node ./node_modules/eslint/bin/eslint.js .",
32
- "test": "node ./script/test/test.js",
35
+ "eslint": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
36
+ "importmap": "node ./script/importmap/importmap.mjs",
37
+ "test": "node --experimental-json-modules ./script/test/test.mjs",
33
38
  "test-with-coverage": "npm run test -- --coverage",
34
- "generate-import-map": "node ./script/generate-import-map/generate-import-map.js",
35
- "dist": "npm run build",
36
- "prettier-format": "node ./script/prettier-format/prettier-format.js",
37
- "prettier-format-stage": "npm run prettier-format -- --staged",
38
- "prettier-check": "npm run prettier-format -- --dry-run",
39
- "upload-coverage": "node ./script/upload-coverage/upload-coverage.js",
40
- "build": "node --experimental-import-meta-resolve ./script/build/build.js",
41
- "prepublishOnly": "node ./script/transform-package/remove-postinstall.js && npm run dist",
42
- "postpublish": "node ./script/transform-package/restore-postinstall.js"
39
+ "prettier": "prettier --write ."
43
40
  },
44
41
  "dependencies": {
45
- "@jsenv/cancellation": "2.0.4",
42
+ "@jsenv/filesystem": "2.7.1",
46
43
  "@jsenv/logger": "4.0.1",
47
- "@jsenv/server": "6.0.3",
48
- "@jsenv/util": "4.1.1",
44
+ "@jsenv/server": "12.4.0",
49
45
  "semver": "7.3.5"
50
46
  },
51
47
  "devDependencies": {
52
- "@jsenv/assert": "2.2.5",
53
- "@jsenv/codecov-upload": "3.4.3",
54
- "@jsenv/core": "18.1.6",
55
- "@jsenv/eslint-config": "15.0.1",
56
- "@jsenv/github-release-package": "1.2.3",
57
- "@jsenv/importmap-eslint-resolver": "5.0.0",
58
- "@jsenv/node-module-import-map": "13.4.3",
59
- "@jsenv/prettier-check-project": "5.6.1",
60
- "eslint": "7.26.0",
61
- "eslint-plugin-import": "2.23.2",
62
- "prettier": "2.3.0"
48
+ "@jsenv/assert": "2.4.1",
49
+ "@jsenv/core": "25.3.0",
50
+ "@jsenv/eslint-config": "16.0.9",
51
+ "@jsenv/github-release-package": "1.3.0",
52
+ "@jsenv/importmap-eslint-resolver": "5.2.5",
53
+ "@jsenv/importmap-node-module": "5.1.0",
54
+ "eslint": "8.7.0",
55
+ "eslint-plugin-import": "2.25.4",
56
+ "prettier": "2.5.1"
63
57
  }
64
58
  }
@@ -4,23 +4,25 @@
4
4
 
5
5
  import { fetchUrl } from "@jsenv/server"
6
6
 
7
- export const fetchLatestInRegistry = async ({ registryUrl, packageName, token }) => {
7
+ export const fetchLatestInRegistry = async ({
8
+ registryUrl,
9
+ packageName,
10
+ token,
11
+ }) => {
8
12
  const requestUrl = `${registryUrl}/${packageName}`
9
13
  const response = await fetchUrl(requestUrl, {
10
14
  method: "GET",
11
15
  headers: {
12
16
  // "user-agent": "jsenv",
13
- accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
17
+ accept:
18
+ "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
14
19
  ...(token ? { authorization: `token ${token}` } : {}),
15
20
  },
16
21
  })
17
-
18
22
  const responseStatus = response.status
19
-
20
23
  if (responseStatus === 404) {
21
24
  return null
22
25
  }
23
-
24
26
  if (responseStatus !== 200) {
25
27
  throw new Error(
26
28
  writeUnexpectedResponseStatus({
@@ -30,7 +32,6 @@ export const fetchLatestInRegistry = async ({ registryUrl, packageName, token })
30
32
  }),
31
33
  )
32
34
  }
33
-
34
35
  const packageObject = await response.json()
35
36
  return packageObject.versions[packageObject["dist-tags"].latest]
36
37
  }
@@ -1,8 +1,11 @@
1
- import { createRequire } from "module"
1
+ import { createRequire } from "node:module"
2
2
 
3
3
  const require = createRequire(import.meta.url)
4
4
  // https://github.com/npm/node-semver#readme
5
- const { gt: versionGreaterThan, prerelease: versionToPrerelease } = require("semver")
5
+ const {
6
+ gt: versionGreaterThan,
7
+ prerelease: versionToPrerelease,
8
+ } = require("semver")
6
9
 
7
10
  export const PUBLISH_BECAUSE_NEVER_PUBLISHED = "never-published"
8
11
  export const PUBLISH_BECAUSE_LATEST_LOWER = "latest-lower"
@@ -15,43 +18,45 @@ export const needsPublish = ({ registryLatestVersion, packageVersion }) => {
15
18
  if (registryLatestVersion === null) {
16
19
  return PUBLISH_BECAUSE_NEVER_PUBLISHED
17
20
  }
18
-
19
21
  if (registryLatestVersion === packageVersion) {
20
22
  return NOTHING_BECAUSE_ALREADY_PUBLISHED
21
23
  }
22
-
23
24
  if (versionGreaterThan(registryLatestVersion, packageVersion)) {
24
25
  return NOTHING_BECAUSE_LATEST_HIGHER
25
26
  }
26
-
27
- const registryLatestVersionPrerelease = versionToPrerelease(registryLatestVersion)
27
+ const registryLatestVersionPrerelease = versionToPrerelease(
28
+ registryLatestVersion,
29
+ )
28
30
  const packageVersionPrerelease = versionToPrerelease(packageVersion)
29
- if (registryLatestVersionPrerelease === null && packageVersionPrerelease === null) {
31
+ if (
32
+ registryLatestVersionPrerelease === null &&
33
+ packageVersionPrerelease === null
34
+ ) {
30
35
  return PUBLISH_BECAUSE_LATEST_LOWER
31
36
  }
32
-
33
- if (registryLatestVersionPrerelease === null && packageVersionPrerelease !== null) {
37
+ if (
38
+ registryLatestVersionPrerelease === null &&
39
+ packageVersionPrerelease !== null
40
+ ) {
34
41
  return PUBLISH_BECAUSE_LATEST_LOWER
35
42
  }
36
-
37
- if (registryLatestVersionPrerelease !== null && packageVersionPrerelease === null) {
43
+ if (
44
+ registryLatestVersionPrerelease !== null &&
45
+ packageVersionPrerelease === null
46
+ ) {
38
47
  return PUBLISH_BECAUSE_LATEST_LOWER
39
48
  }
40
-
41
- const [registryReleaseTag, registryPrereleaseVersion] = registryLatestVersionPrerelease
49
+ const [registryReleaseTag, registryPrereleaseVersion] =
50
+ registryLatestVersionPrerelease
42
51
  const [packageReleaseTag, packagePreReleaseVersion] = packageVersionPrerelease
43
-
44
52
  if (registryReleaseTag !== packageReleaseTag) {
45
53
  return PUBLISH_BECAUSE_TAG_DIFFERS
46
54
  }
47
-
48
55
  if (registryPrereleaseVersion === packagePreReleaseVersion) {
49
56
  return NOTHING_BECAUSE_ALREADY_PUBLISHED
50
57
  }
51
-
52
58
  if (registryPrereleaseVersion > packagePreReleaseVersion) {
53
59
  return NOTHING_BECAUSE_LATEST_HIGHER
54
60
  }
55
-
56
61
  return PUBLISH_BECAUSE_LATEST_LOWER
57
62
  }
@@ -1,6 +1,10 @@
1
- import { exec } from "child_process"
2
-
3
- import { resolveUrl, urlToFileSystemPath, readFile, writeFile } from "@jsenv/util"
1
+ import { exec } from "node:child_process"
2
+ import {
3
+ resolveUrl,
4
+ urlToFileSystemPath,
5
+ readFile,
6
+ writeFile,
7
+ } from "@jsenv/filesystem"
4
8
 
5
9
  import { setNpmConfig } from "./setNpmConfig.js"
6
10
 
@@ -13,23 +17,28 @@ export const publish = async ({
13
17
  }) => {
14
18
  try {
15
19
  const promises = []
16
-
17
20
  const previousValue = process.env.NODE_AUTH_TOKEN
18
21
  const restoreProcessEnv = () => {
19
22
  process.env.NODE_AUTH_TOKEN = previousValue
20
23
  }
21
24
  process.env.NODE_AUTH_TOKEN = token
22
-
23
- const projectPackageFileUrl = resolveUrl("./package.json", projectDirectoryUrl)
25
+ const projectPackageFileUrl = resolveUrl(
26
+ "./package.json",
27
+ projectDirectoryUrl,
28
+ )
24
29
  const projectPackageString = await readFile(projectPackageFileUrl)
25
- const restoreProjectPackageFile = () => writeFile(projectPackageFileUrl, projectPackageString)
30
+ const restoreProjectPackageFile = () =>
31
+ writeFile(projectPackageFileUrl, projectPackageString)
26
32
  const projectPackageObject = JSON.parse(projectPackageString)
27
- projectPackageObject.publishConfig = projectPackageObject.publishConfig || {}
33
+ projectPackageObject.publishConfig =
34
+ projectPackageObject.publishConfig || {}
28
35
  projectPackageObject.publishConfig.registry = registryUrl
29
36
  promises.push(
30
- writeFile(projectPackageFileUrl, JSON.stringify(projectPackageObject, null, " ")),
37
+ writeFile(
38
+ projectPackageFileUrl,
39
+ JSON.stringify(projectPackageObject, null, " "),
40
+ ),
31
41
  )
32
-
33
42
  const projectNpmConfigFileUrl = resolveUrl("./.npmrc", projectDirectoryUrl)
34
43
  let projectNpmConfigString
35
44
  try {
@@ -52,9 +61,7 @@ export const publish = async ({
52
61
  }),
53
62
  ),
54
63
  )
55
-
56
64
  await Promise.all(promises)
57
-
58
65
  try {
59
66
  return await new Promise((resolve, reject) => {
60
67
  const command = exec(
@@ -81,13 +88,17 @@ export const publish = async ({
81
88
  success: true,
82
89
  reason: "already-published",
83
90
  })
84
- } else if (error.message.includes("Cannot publish over existing version")) {
91
+ } else if (
92
+ error.message.includes("Cannot publish over existing version")
93
+ ) {
85
94
  resolve({
86
95
  success: true,
87
96
  reason: "already-published",
88
97
  })
89
98
  } else if (
90
- error.message.includes("You cannot publish over the previously published versions")
99
+ error.message.includes(
100
+ "You cannot publish over the previously published versions",
101
+ )
91
102
  ) {
92
103
  resolve({
93
104
  success: true,
@@ -95,7 +106,11 @@ export const publish = async ({
95
106
  })
96
107
  }
97
108
  // github publish conflict
98
- else if (error.message.includes("ambiguous package version in package.json")) {
109
+ else if (
110
+ error.message.includes(
111
+ "ambiguous package version in package.json",
112
+ )
113
+ ) {
99
114
  resolve({
100
115
  success: true,
101
116
  reason: "already-published",
@@ -147,7 +162,9 @@ const computeRegistryTokenKey = (registryUrl) => {
147
162
  if (registryUrl.startsWith("//")) {
148
163
  return `${registryUrl}/:_authToken`
149
164
  }
150
- throw new Error(`registryUrl must start with http or https, got ${registryUrl}`)
165
+ throw new Error(
166
+ `registryUrl must start with http or https, got ${registryUrl}`,
167
+ )
151
168
  }
152
169
 
153
170
  const computeRegistryKey = (packageName) => {
@@ -1,8 +1,7 @@
1
- import { resolveUrl, urlToFileSystemPath, readFile } from "@jsenv/util"
1
+ import { resolveUrl, urlToFileSystemPath, readFile } from "@jsenv/filesystem"
2
2
 
3
3
  export const readProjectPackage = async ({ projectDirectoryUrl }) => {
4
4
  const packageFileUrl = resolveUrl("./package.json", projectDirectoryUrl)
5
-
6
5
  let packageObject
7
6
  try {
8
7
  const packageString = await readFile(packageFileUrl)
@@ -28,6 +27,5 @@ ${urlToFileSystemPath(packageFileUrl)}`,
28
27
  }
29
28
  throw e
30
29
  }
31
-
32
30
  return packageObject
33
31
  }