@gluhar/cli 6.0.0-next.8 → 6.0.0-next.9

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": "@gluhar/cli",
3
- "version": "6.0.0-next.8",
3
+ "version": "6.0.0-next.9",
4
4
  "description": "Gluhar cli commands and scripts",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,7 +2,8 @@ export declare const generateTypes: readonly ["project", "package", "command"];
2
2
  export type GenerateType = (typeof generateTypes)[number];
3
3
  export interface GenerateOptions {
4
4
  starter?: string;
5
- noRepo?: boolean;
5
+ /** `--no-repo` sets this to false (commander's negatable option); default true. */
6
+ repo?: boolean;
6
7
  keepHistory?: boolean;
7
8
  yes: boolean;
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GenerateOptions.d.ts","sourceRoot":"","sources":["../../../../src/commands/generate/GenerateOptions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,4CAA6C,CAAC;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;CACd"}
1
+ {"version":3,"file":"GenerateOptions.d.ts","sourceRoot":"","sources":["../../../../src/commands/generate/GenerateOptions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,4CAA6C,CAAC;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;CACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"generateProject.d.ts","sourceRoot":"","sources":["../../../../src/commands/generate/generateProject.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,KAAK,MAAM,EACX,SAAS,eAAe,kBAwGzB,CAAC"}
1
+ {"version":3,"file":"generateProject.d.ts","sourceRoot":"","sources":["../../../../src/commands/generate/generateProject.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,KAAK,MAAM,EACX,SAAS,eAAe,kBA0GzB,CAAC"}
@@ -9,7 +9,9 @@ const cmd_1 = require("../../scripts/cmd");
9
9
  const utils_1 = require("../../utils");
10
10
  const generateProject = async (name, cwd, options) => {
11
11
  // `dev` is the starters' main branch; others (e.g. `mobile`) are variants.
12
- const { starter = "dev", noRepo, keepHistory, yes } = options;
12
+ const { starter = "dev", repo = true, keepHistory, yes } = options;
13
+ // `--no-repo` arrives as `repo: false`; there is no `noRepo` key
14
+ const noRepo = !repo;
13
15
  log_1.log.verbose("Check if project name is valid");
14
16
  if (!name.match(/^[a-z0-9-]+$/)) {
15
17
  log_1.log.error("Project name must be lowercase, alphanumeric, and contain hyphens only.");
@@ -1,5 +1,7 @@
1
1
  export interface UpgradeOptions {
2
2
  /** npm dist-tag or version to install, e.g. `latest`, `next`, `6`. */
3
3
  tag: string;
4
+ /** Print the planned package.json changes without writing or installing. */
5
+ dryRun?: boolean;
4
6
  }
5
7
  //# sourceMappingURL=UpgradeOptions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UpgradeOptions.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/UpgradeOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;CACb"}
1
+ {"version":3,"file":"UpgradeOptions.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/UpgradeOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;;AAGpC,wBAMmB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;;AAGpC,wBAUmB"}
@@ -6,4 +6,5 @@ exports.default = new commander_1.Command()
6
6
  .name("upgrade")
7
7
  .description("Upgrade all @gluhar/* dependencies in a project, across major versions.")
8
8
  .option("-t, --tag <tag>", "npm dist-tag or version to install.", "latest")
9
+ .option("-d, --dry-run", "Print the planned package.json changes without writing or installing.")
9
10
  .action(upgrade_1.upgrade);
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/upgrade.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,SAiB9C,CAAC"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../../../src/commands/upgrade/upgrade.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAyClD,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,SAyE9C,CAAC"}
@@ -3,20 +3,91 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.upgrade = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
+ const semver_1 = require("semver");
6
7
  const cmd_1 = require("../../scripts/cmd");
7
8
  const log_1 = require("./log");
9
+ const fields = ["dependencies", "devDependencies"];
10
+ /** The version a tag or range resolves to on npm, with that version's peers. */
11
+ const resolve = (name, tag) => {
12
+ const output = JSON.parse((0, cmd_1.getCmdOutput)(`npm view ${name}@${tag} version peerDependencies --json`));
13
+ // A single field comes back as a bare string; a range (`6`) as an array
14
+ // of matches, oldest first
15
+ const latest = Array.isArray(output) ? output[output.length - 1] : output;
16
+ return typeof latest === "string" ? { version: latest } : latest;
17
+ };
18
+ /** The version npm installed, else the lowest the range in package.json allows. */
19
+ const currentVersion = (cwd, name, range) => {
20
+ const installed = (0, path_1.join)(cwd, "node_modules", name, "package.json");
21
+ if (!(0, fs_1.existsSync)(installed))
22
+ return (0, semver_1.minVersion)(range)?.version;
23
+ const { version } = JSON.parse((0, fs_1.readFileSync)(installed).toString());
24
+ return version;
25
+ };
26
+ /** Of several ranges, the one whose lowest version is highest. */
27
+ const strictest = (ranges) => ranges.reduce((a, b) => {
28
+ const [minA, minB] = [(0, semver_1.minVersion)(a), (0, semver_1.minVersion)(b)];
29
+ return minA && minB && minB.compare(minA) > 0 ? b : a;
30
+ });
8
31
  const upgrade = (options) => {
9
- const { tag } = options;
10
- log_1.log.info(`Upgrading gluhar dependencies to "${tag}".`);
11
- const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), "package.json")).toString());
12
- const names = Object.keys({
13
- ...pkg.dependencies,
14
- ...pkg.devDependencies,
15
- }).filter((name) => name.startsWith("@gluhar/"));
32
+ const { tag, dryRun } = options;
33
+ const cwd = process.cwd();
34
+ const pkgPath = (0, path_1.join)(cwd, "package.json");
35
+ const source = (0, fs_1.readFileSync)(pkgPath).toString();
36
+ const pkg = JSON.parse(source);
37
+ // The dependency map that lists `name` (dependencies or devDependencies)
38
+ const depsOf = (name) => fields
39
+ .map((field) => pkg[field])
40
+ .find((deps) => deps?.[name] !== undefined);
41
+ const names = fields
42
+ .flatMap((field) => Object.keys(pkg[field] ?? {}))
43
+ .filter((name) => name.startsWith("@gluhar/"));
16
44
  if (!names.length)
17
45
  return log_1.log.info("No @gluhar/* dependencies found.");
18
- // `npm install pkg@tag`, not `npm update`: update stays inside the semver
19
- // range already in package.json, so it can never cross a major version.
20
- (0, cmd_1.executeCmd)(`npm install ${names.map((name) => `${name}@${tag}`).join(" ")}`);
46
+ log_1.log.info(`Upgrading gluhar dependencies to "${tag}".`);
47
+ const changes = new Map();
48
+ const peerRanges = new Map();
49
+ for (const name of names) {
50
+ const { version, peerDependencies = {} } = resolve(name, tag);
51
+ changes.set(name, `^${version}`);
52
+ for (const [peer, range] of Object.entries(peerDependencies))
53
+ peerRanges.set(peer, [...(peerRanges.get(peer) ?? []), range]);
54
+ }
55
+ // A peer the project depends on directly (in practice `nuxt`) has to move in
56
+ // the same install. `npm install @gluhar/*@<tag>` alone fails with ERESOLVE:
57
+ // the old nuxt pins its own @nuxt/vite-builder exactly, so npm won't replace
58
+ // nuxt unless package.json already asks for the new range.
59
+ for (const [peer, ranges] of peerRanges) {
60
+ const deps = depsOf(peer);
61
+ if (!deps || peer.startsWith("@gluhar/"))
62
+ continue;
63
+ const current = currentVersion(cwd, peer, deps[peer]);
64
+ const opts = { includePrerelease: true };
65
+ if (current && ranges.every((range) => (0, semver_1.satisfies)(current, range, opts)))
66
+ continue;
67
+ changes.set(peer, strictest(ranges));
68
+ }
69
+ for (const [name, range] of changes) {
70
+ const deps = depsOf(name);
71
+ if (!deps || deps[name] === range)
72
+ continue;
73
+ const note = name.startsWith("@gluhar/") ? "" : " (peer of @gluhar/*)";
74
+ log_1.log.info(`${name}: ${deps[name]} -> ${range}${note}`);
75
+ deps[name] = range;
76
+ }
77
+ if (dryRun)
78
+ return log_1.log.info("Dry run: package.json not written.");
79
+ const indent = source.match(/^[ \t]+/m)?.[0] ?? " ";
80
+ (0, fs_1.writeFileSync)(pkgPath, `${JSON.stringify(pkg, null, indent)}\n`);
81
+ // A plain install with the existing lockfile: npm re-resolves only what the
82
+ // new ranges require
83
+ const result = (0, cmd_1.executeCmd)("npm install");
84
+ if (result.status !== 0) {
85
+ log_1.log.error("npm install failed. package.json already has the new ranges; if it is still ERESOLVE, delete package-lock.json and node_modules and run npm install.");
86
+ process.exit(result.status || 1);
87
+ }
88
+ const studioPkg = (0, path_1.join)(cwd, "sanity", "package.json");
89
+ if ((0, fs_1.existsSync)(studioPkg) &&
90
+ (0, fs_1.readFileSync)(studioPkg).toString().includes('"@gluhar/'))
91
+ log_1.log.info("The Studio in sanity/ has its own @gluhar/* dependencies: run `gluhar upgrade` there too.");
21
92
  };
22
93
  exports.upgrade = upgrade;