@jsenv/monorepo 0.3.17 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/monorepo",
3
- "version": "0.3.17",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Helpers to manage packages in a monorepo",
6
6
  "repository": {
@@ -6,8 +6,17 @@ import {
6
6
  VERSION_COMPARE_RESULTS,
7
7
  } from "./internal/compare_two_package_versions.js";
8
8
  import { fetchWorkspaceLatests } from "./internal/fetch_workspace_latests.js";
9
+ import { syncPackagesVersions } from "./sync_packages_versions.js";
10
+
11
+ export const publishPackages = async ({ directoryUrl, packagesRelations }) => {
12
+ const versionsInSync = await ensureVersionsAreInSync({
13
+ directoryUrl,
14
+ packagesRelations,
15
+ });
16
+ if (!versionsInSync) {
17
+ return;
18
+ }
9
19
 
10
- export const publishPackages = async ({ directoryUrl }) => {
11
20
  const workspacePackages = await collectWorkspacePackages({ directoryUrl });
12
21
  const registryLatestVersions = await fetchWorkspaceLatests(workspacePackages);
13
22
  const toPublishPackageNames = Object.keys(workspacePackages).filter(
@@ -58,3 +67,69 @@ export const publishPackages = async ({ directoryUrl }) => {
58
67
  Promise.resolve(),
59
68
  );
60
69
  };
70
+
71
+ /*
72
+ * Publishing while package.json files are not in sync would put on the registry
73
+ * packages depending on versions that do not exist (or are outdated).
74
+ * When versions are not in sync we ask permission to sync them before publishing.
75
+ */
76
+ const ensureVersionsAreInSync = async ({ directoryUrl, packagesRelations }) => {
77
+ const { outdatedPackageNames, versionUpdates, dependencyUpdates } =
78
+ await syncPackagesVersions({
79
+ logs: false,
80
+ dryRun: true,
81
+ directoryUrl,
82
+ packagesRelations,
83
+ });
84
+ if (outdatedPackageNames.length) {
85
+ console.warn(
86
+ `${UNICODE.FAILURE} ${outdatedPackageNames.length} packages have a version older than the one published on registry
87
+ - ${outdatedPackageNames.join(`
88
+ - `)}
89
+ Run "npm run monorepo:sync_versions" and review the changes before publishing`,
90
+ );
91
+ return false;
92
+ }
93
+ const outOfSyncCount = versionUpdates.length + dependencyUpdates.length;
94
+ if (outOfSyncCount === 0) {
95
+ return true;
96
+ }
97
+ console.warn(`${UNICODE.WARNING} versions are not in sync, ${outOfSyncCount} things must be updated in package.json files
98
+ - ${[
99
+ ...versionUpdates.map(
100
+ ({ packageName, from, to }) => `${packageName}: ${from} -> ${to}`,
101
+ ),
102
+ ...dependencyUpdates.map(
103
+ ({ packageName, dependencyName, from, to }) =>
104
+ `${packageName} -> ${dependencyName}: ${from} -> ${to}`,
105
+ ),
106
+ ].join(`
107
+ - `)}`);
108
+ const confirmed = await confirm(`Sync versions and publish?`);
109
+ if (!confirmed) {
110
+ console.log(`${UNICODE.INFO} publish aborted, versions are not in sync`);
111
+ return false;
112
+ }
113
+ await syncPackagesVersions({ directoryUrl, packagesRelations });
114
+ return true;
115
+ };
116
+
117
+ const confirm = async (question) => {
118
+ if (!process.stdin.isTTY) {
119
+ console.warn(
120
+ `${UNICODE.FAILURE} cannot ask confirmation (stdin is not a TTY)`,
121
+ );
122
+ return false;
123
+ }
124
+ const { createInterface } = await import("node:readline/promises");
125
+ const readlineInterface = createInterface({
126
+ input: process.stdin,
127
+ output: process.stdout,
128
+ });
129
+ try {
130
+ const answer = await readlineInterface.question(`${question} (y/N) `);
131
+ return answer.trim().toLowerCase() === "y";
132
+ } finally {
133
+ readlineInterface.close();
134
+ }
135
+ };
@@ -14,6 +14,7 @@ import { shouldUpdateVersion } from "./internal/should_update_version.js";
14
14
 
15
15
  export const syncPackagesVersions = async ({
16
16
  logs = true,
17
+ dryRun = false,
17
18
  directoryUrl,
18
19
  packagesRelations = {},
19
20
  }) => {
@@ -50,35 +51,28 @@ export const syncPackagesVersions = async ({
50
51
  const versionUpdates = [];
51
52
  const dependencyUpdates = [];
52
53
  if (outdatedPackageNames.length) {
53
- outdatedPackageNames.forEach((outdatedPackageName) => {
54
- const workspacePackage = workspacePackages[outdatedPackageName];
55
- workspacePackage.packageObject.version =
56
- registryLatestVersions[outdatedPackageName];
57
- workspacePackage.updateFile(workspacePackage.packageObject);
58
- });
59
- console.warn(
60
- `${UNICODE.WARNING} ${outdatedPackageNames.length} packages modified because they where outdated.
54
+ if (!dryRun) {
55
+ outdatedPackageNames.forEach((outdatedPackageName) => {
56
+ const workspacePackage = workspacePackages[outdatedPackageName];
57
+ workspacePackage.packageObject.version =
58
+ registryLatestVersions[outdatedPackageName];
59
+ workspacePackage.updateFile(workspacePackage.packageObject);
60
+ });
61
+ }
62
+ if (logs) {
63
+ console.warn(
64
+ `${UNICODE.WARNING} ${outdatedPackageNames.length} packages ${
65
+ dryRun ? "are outdated" : "modified because they where outdated"
66
+ }.
61
67
  Use a tool like "git diff" to see the new versions and ensure this is what you want`,
62
- );
68
+ );
69
+ }
63
70
  return {
71
+ outdatedPackageNames,
64
72
  versionUpdates,
65
73
  dependencyUpdates,
66
74
  };
67
75
  }
68
- if (toPublishPackageNames.length === 0) {
69
- console.log(`${UNICODE.OK} packages are published on registry`);
70
- } else {
71
- console.log(
72
- `${UNICODE.INFO} ${
73
- toPublishPackageNames.length
74
- } packages could be published
75
- - ${toPublishPackageNames.map(
76
- (name) => `${name}@${workspacePackages[name].packageObject.version}`,
77
- ).join(`
78
- - `)}`,
79
- );
80
- }
81
-
82
76
  const packageFilesToUpdate = {};
83
77
  const updateDependencyVersion = ({
84
78
  packageName,
@@ -204,13 +198,33 @@ Use a tool like "git diff" to see the new versions and ensure this is what you w
204
198
  packageInfo.packageUrl,
205
199
  ),
206
200
  });
201
+ if (!toPublishPackageNames.includes(packageName)) {
202
+ toPublishPackageNames.push(packageName);
203
+ }
207
204
  }
208
205
  });
209
206
  }
210
- Object.keys(packageFilesToUpdate).forEach((packageName) => {
211
- const workspacePackage = workspacePackages[packageName];
212
- workspacePackage.updateFile(workspacePackage.packageObject);
213
- });
207
+ if (logs) {
208
+ if (toPublishPackageNames.length === 0) {
209
+ console.log(`${UNICODE.OK} packages are published on registry`);
210
+ } else {
211
+ console.log(
212
+ `${UNICODE.INFO} ${
213
+ toPublishPackageNames.length
214
+ } packages could be published
215
+ - ${toPublishPackageNames.map(
216
+ (name) => `${name}@${workspacePackages[name].packageObject.version}`,
217
+ ).join(`
218
+ - `)}`,
219
+ );
220
+ }
221
+ }
222
+ if (!dryRun) {
223
+ Object.keys(packageFilesToUpdate).forEach((packageName) => {
224
+ const workspacePackage = workspacePackages[packageName];
225
+ workspacePackage.updateFile(workspacePackage.packageObject);
226
+ });
227
+ }
214
228
  const updateCount = versionUpdates.length + dependencyUpdates.length;
215
229
  if (logs) {
216
230
  if (updateCount === 0) {
@@ -226,6 +240,7 @@ Use a tool like "git diff" to see the new versions and ensure this is what you w
226
240
  }
227
241
 
228
242
  return {
243
+ outdatedPackageNames,
229
244
  versionUpdates,
230
245
  dependencyUpdates,
231
246
  };