@jsenv/package-publish 1.5.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.
@@ -1,6 +1,6 @@
1
+ import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
1
2
  import { createLogger } from "@jsenv/logger"
2
- import { createCancellationTokenForProcess, executeAsyncFunction } from "@jsenv/cancellation"
3
- import { assertAndNormalizeDirectoryUrl } from "@jsenv/util"
3
+
4
4
  import { fetchLatestInRegistry } from "./internal/fetchLatestInRegistry.js"
5
5
  import { publish } from "./internal/publish.js"
6
6
  import { readProjectPackage } from "./internal/readProjectPackage.js"
@@ -14,180 +14,186 @@ import {
14
14
  } from "../src/internal/needsPublish.js"
15
15
 
16
16
  export const publishPackage = async ({
17
- cancellationToken = createCancellationTokenForProcess(),
18
17
  logLevel,
19
18
  projectDirectoryUrl,
20
19
  registriesConfig,
21
20
  logNpmPublishOutput = true,
22
21
  updateProcessExitCode = true,
23
22
  } = {}) => {
24
- return executeAsyncFunction(
25
- async () => {
26
- const logger = createLogger({ logLevel })
27
- logger.debug(
28
- `publishPackage(${JSON.stringify(
29
- { projectDirectoryUrl, logLevel, registriesConfig },
30
- null,
31
- " ",
32
- )})`,
33
- )
34
- projectDirectoryUrl = assertAndNormalizeDirectoryUrl(projectDirectoryUrl)
35
- assertRegistriesConfig(registriesConfig)
36
-
37
- logger.debug(`reading project package.json`)
38
- const packageInProject = await readProjectPackage({
39
- projectDirectoryUrl,
40
- })
41
- const { name: packageName, version: packageVersion } = packageInProject
42
- logger.info(`${packageName}@${packageVersion} found in package.json`)
43
-
44
- const report = {}
45
- await Promise.all(
46
- Object.keys(registriesConfig).map(async (registryUrl) => {
47
- const registryReport = {
48
- packageName,
49
- packageVersion,
50
- registryLatestVersion: undefined,
51
- action: undefined,
52
- actionReason: undefined,
53
- actionResult: undefined,
54
- }
55
- report[registryUrl] = registryReport
56
-
57
- logger.debug(`check latest version for ${packageName} in ${registryUrl}`)
58
- const registryConfig = registriesConfig[registryUrl]
59
-
60
- try {
61
- const latestPackageInRegistry = await fetchLatestInRegistry({
62
- registryUrl,
63
- packageName,
64
- ...registryConfig,
65
- })
66
- const registryLatestVersion =
67
- latestPackageInRegistry === null ? null : latestPackageInRegistry.version
68
- registryReport.registryLatestVersion = registryLatestVersion
69
-
70
- const needs = needsPublish({ packageVersion, registryLatestVersion })
71
- registryReport.action =
72
- needs === PUBLISH_BECAUSE_NEVER_PUBLISHED ||
73
- needs === PUBLISH_BECAUSE_LATEST_LOWER ||
74
- needs === PUBLISH_BECAUSE_TAG_DIFFERS
75
- ? "publish"
76
- : "nothing"
77
- registryReport.actionReason = needs
78
- } catch (e) {
79
- registryReport.action = "nothing"
80
- registryReport.actionReason = e
81
- if (updateProcessExitCode) {
82
- process.exitCode = 1
83
- }
84
- }
85
-
86
- cancellationToken.throwIfRequested()
87
- }),
88
- )
23
+ const logger = createLogger({ logLevel })
24
+ logger.debug(
25
+ `publishPackage(${JSON.stringify(
26
+ { projectDirectoryUrl, logLevel, registriesConfig },
27
+ null,
28
+ " ",
29
+ )})`,
30
+ )
31
+ projectDirectoryUrl = assertAndNormalizeDirectoryUrl(projectDirectoryUrl)
32
+ assertRegistriesConfig(registriesConfig)
89
33
 
90
- // we have to publish in serie because we don't fully control
91
- // npm publish, we have to enforce where the package gets published
92
- await Object.keys(report).reduce(async (previous, registryUrl) => {
93
- await previous
94
- cancellationToken.throwIfRequested()
95
-
96
- const registryReport = report[registryUrl]
97
- const { action, actionReason, registryLatestVersion } = registryReport
98
-
99
- if (action === "nothing") {
100
- if (actionReason === NOTHING_BECAUSE_ALREADY_PUBLISHED) {
101
- logger.info(
102
- `skip ${packageName}@${packageVersion} publish on ${registryUrl} because already published`,
103
- )
104
- } else if (actionReason === NOTHING_BECAUSE_LATEST_HIGHER) {
105
- logger.info(
106
- `skip ${packageName}@${packageVersion} publish on ${registryUrl} because latest version is higher (${registryLatestVersion})`,
107
- )
108
- } else {
109
- logger.error(`skip ${packageName}@${packageVersion} publish on ${registryUrl} due to error while fetching latest version.
34
+ logger.debug(`reading project package.json`)
35
+ const packageInProject = await readProjectPackage({
36
+ projectDirectoryUrl,
37
+ })
38
+
39
+ const { name: packageName, version: packageVersion } = packageInProject
40
+ logger.info(`${packageName}@${packageVersion} found in package.json`)
41
+
42
+ const report = {}
43
+ await Promise.all(
44
+ Object.keys(registriesConfig).map(async (registryUrl) => {
45
+ const registryReport = {
46
+ packageName,
47
+ packageVersion,
48
+ registryLatestVersion: undefined,
49
+ action: undefined,
50
+ actionReason: undefined,
51
+ actionResult: undefined,
52
+ }
53
+ report[registryUrl] = registryReport
54
+
55
+ if (packageInProject.private) {
56
+ registryReport.action = "nothing"
57
+ registryReport.actionReason = "package is private"
58
+ return
59
+ }
60
+
61
+ logger.debug(`check latest version for ${packageName} in ${registryUrl}`)
62
+ const registryConfig = registriesConfig[registryUrl]
63
+
64
+ try {
65
+ const latestPackageInRegistry = await fetchLatestInRegistry({
66
+ registryUrl,
67
+ packageName,
68
+ ...registryConfig,
69
+ })
70
+ const registryLatestVersion =
71
+ latestPackageInRegistry === null
72
+ ? null
73
+ : latestPackageInRegistry.version
74
+ registryReport.registryLatestVersion = registryLatestVersion
75
+
76
+ const needs = needsPublish({ packageVersion, registryLatestVersion })
77
+ registryReport.action =
78
+ needs === PUBLISH_BECAUSE_NEVER_PUBLISHED ||
79
+ needs === PUBLISH_BECAUSE_LATEST_LOWER ||
80
+ needs === PUBLISH_BECAUSE_TAG_DIFFERS
81
+ ? "publish"
82
+ : "nothing"
83
+ registryReport.actionReason = needs
84
+ } catch (e) {
85
+ registryReport.action = "nothing"
86
+ registryReport.actionReason = e
87
+ if (updateProcessExitCode) {
88
+ process.exitCode = 1
89
+ }
90
+ }
91
+ }),
92
+ )
93
+
94
+ // we have to publish in serie because we don't fully control
95
+ // npm publish, we have to enforce where the package gets published
96
+ await Object.keys(report).reduce(async (previous, registryUrl) => {
97
+ await previous
98
+
99
+ const registryReport = report[registryUrl]
100
+ const { action, actionReason, registryLatestVersion } = registryReport
101
+
102
+ if (action === "nothing") {
103
+ if (actionReason === NOTHING_BECAUSE_ALREADY_PUBLISHED) {
104
+ logger.info(
105
+ `skip ${packageName}@${packageVersion} publish on ${registryUrl} because already published`,
106
+ )
107
+ } else if (actionReason === NOTHING_BECAUSE_LATEST_HIGHER) {
108
+ logger.info(
109
+ `skip ${packageName}@${packageVersion} publish on ${registryUrl} because latest version is higher (${registryLatestVersion})`,
110
+ )
111
+ } else if (actionReason === "package is private") {
112
+ logger.info(
113
+ `skip ${packageName}@${packageVersion} publish on ${registryUrl} because found private: true in package.json`,
114
+ )
115
+ } else {
116
+ logger.error(`skip ${packageName}@${packageVersion} publish on ${registryUrl} due to error while fetching latest version.
110
117
  --- error stack ---
111
118
  ${actionReason.stack}`)
112
- }
119
+ }
113
120
 
114
- registryReport.actionResult = { success: true, reason: "nothing-to-do" }
115
- return
116
- }
121
+ registryReport.actionResult = { success: true, reason: "nothing-to-do" }
122
+ return
123
+ }
117
124
 
118
- if (actionReason === PUBLISH_BECAUSE_NEVER_PUBLISHED) {
119
- logger.info(
120
- `publish ${packageName}@${packageVersion} on ${registryUrl} because it was never published`,
121
- )
122
- } else if (actionReason === PUBLISH_BECAUSE_LATEST_LOWER) {
123
- logger.info(
124
- `publish ${packageName}@${packageVersion} on ${registryUrl} because latest version is lower (${registryLatestVersion})`,
125
- )
126
- } else if (actionReason === PUBLISH_BECAUSE_TAG_DIFFERS) {
127
- logger.info(
128
- `publish ${packageName}@${packageVersion} on ${registryUrl} because latest tag differs (${registryLatestVersion})`,
129
- )
130
- }
125
+ if (actionReason === PUBLISH_BECAUSE_NEVER_PUBLISHED) {
126
+ logger.info(
127
+ `publish ${packageName}@${packageVersion} on ${registryUrl} because it was never published`,
128
+ )
129
+ } else if (actionReason === PUBLISH_BECAUSE_LATEST_LOWER) {
130
+ logger.info(
131
+ `publish ${packageName}@${packageVersion} on ${registryUrl} because latest version is lower (${registryLatestVersion})`,
132
+ )
133
+ } else if (actionReason === PUBLISH_BECAUSE_TAG_DIFFERS) {
134
+ logger.info(
135
+ `publish ${packageName}@${packageVersion} on ${registryUrl} because latest tag differs (${registryLatestVersion})`,
136
+ )
137
+ }
131
138
 
132
- const { success, reason } = await publish({
133
- logger,
134
- logNpmPublishOutput,
135
- projectDirectoryUrl,
136
- registryUrl,
137
- ...registriesConfig[registryUrl],
138
- })
139
- registryReport.actionResult = { success, reason }
140
- if (success) {
141
- if (reason === "already-published") {
142
- logger.info(`${packageName}@${packageVersion} was already published on ${registryUrl}`)
143
- } else {
144
- logger.info(`${packageName}@${packageVersion} published on ${registryUrl}`)
145
- }
146
- } else {
147
- logger.error(`error when publishing ${packageName}@${packageVersion} in ${registryUrl}
139
+ const { success, reason } = await publish({
140
+ logger,
141
+ logNpmPublishOutput,
142
+ projectDirectoryUrl,
143
+ registryUrl,
144
+ ...registriesConfig[registryUrl],
145
+ })
146
+ registryReport.actionResult = { success, reason }
147
+ if (success) {
148
+ if (reason === "already-published") {
149
+ logger.info(
150
+ `${packageName}@${packageVersion} was already published on ${registryUrl}`,
151
+ )
152
+ } else {
153
+ logger.info(
154
+ `${packageName}@${packageVersion} published on ${registryUrl}`,
155
+ )
156
+ }
157
+ } else {
158
+ logger.error(`error when publishing ${packageName}@${packageVersion} in ${registryUrl}
148
159
  --- error stack ---
149
160
  ${reason.stack}`)
150
- if (updateProcessExitCode) {
151
- process.exitCode = 1
152
- }
153
- }
154
- }, Promise.resolve())
161
+ if (updateProcessExitCode) {
162
+ process.exitCode = 1
163
+ }
164
+ }
165
+ }, Promise.resolve())
155
166
 
156
- return report
157
- },
158
- { catchCancellation: true, considerUnhandledRejectionsAsExceptions: true },
159
- )
167
+ return report
160
168
  }
161
169
 
162
170
  const assertRegistriesConfig = (value) => {
163
- if (typeof value !== "object") {
164
- throw new TypeError(`registriesConfig must be an object.
165
- --- registryMap ---
166
- ${value}`)
171
+ if (typeof value !== "object" || value === null) {
172
+ throw new TypeError(`registriesConfig must be an object, got ${value}`)
167
173
  }
168
174
 
169
175
  Object.keys(value).forEach((registryUrl) => {
170
176
  const registryMapValue = value[registryUrl]
171
- if (typeof registryMapValue !== "object") {
172
- throw new TypeError(`found unexpected registryMap value: it must be an object.
173
- --- registryMap value ---
174
- ${registryMapValue}
175
- --- registryMap key ---
176
- ${registryUrl}`)
177
+ if (typeof registryMapValue !== "object" || value === null) {
178
+ throw new TypeError(
179
+ `Unexpected value in registriesConfig for ${registryUrl}. It must be an object, got ${registryMapValue}`,
180
+ )
177
181
  }
178
182
 
179
- if (`token` in registryMapValue === false) {
180
- throw new TypeError(`missing token in registryMap.
181
- --- registryMap key ---
182
- ${registryUrl}`)
183
+ if (
184
+ `token` in registryMapValue === false ||
185
+ registryMapValue.token === ""
186
+ ) {
187
+ throw new TypeError(
188
+ `Missing token in registriesConfig for ${registryUrl}.`,
189
+ )
183
190
  }
184
191
 
185
- if (typeof registryMapValue.token !== "string") {
186
- throw new TypeError(`unexpected token found in registryMap: it must be a string.
187
- --- token ---
188
- ${registryMapValue.token}
189
- --- registryMap key ---
190
- ${registryUrl}`)
192
+ const { token } = registryMapValue
193
+ if (typeof token !== "string") {
194
+ throw new TypeError(
195
+ `Unexpected token in registriesConfig for ${registryUrl}. It must be a string, got ${token}.`,
196
+ )
191
197
  }
192
198
  })
193
199
  }