@nan0web/release 3.1.0 → 3.1.1

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
1
  #!/usr/bin/env node
2
2
 
3
3
  import { bootstrapApp } from '@nan0web/ui-cli'
4
- import { App } from '../src/domain/App.js'
4
+ import { ReleaseApp } from '../src/domain/App.js'
5
5
 
6
- bootstrapApp(App)
6
+ bootstrapApp(ReleaseApp)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nan0web/release",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Project Management as Code, Git-Native, GPG-Signed, Test-Driven",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -10,16 +10,16 @@
10
10
  "release": "./bin/nan0release.js"
11
11
  },
12
12
  "dependencies": {
13
- "@nan0web/log": "3.1.0",
14
13
  "@nan0web/co": "3.1.0",
15
- "@nan0web/markdown": "3.1.0",
14
+ "@nan0web/log": "3.1.0",
16
15
  "@nan0web/db-fs": "3.1.0",
17
16
  "@nan0web/types": "3.1.0",
18
- "@nan0web/changelog": "3.1.0",
19
17
  "@nan0web/db": "3.1.0",
20
- "@nan0web/ui": "3.1.0",
21
- "@nan0web/logos": "3.1.0",
22
- "@nan0web/ui-cli": "3.1.0"
18
+ "@nan0web/ui": "3.1.1",
19
+ "@nan0web/markdown": "3.1.0",
20
+ "@nan0web/ui-cli": "3.1.1",
21
+ "@nan0web/changelog": "3.1.0",
22
+ "@nan0web/logos": "3.1.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^25.6.0",
package/src/README.md.js CHANGED
@@ -4,7 +4,7 @@ import { readFile } from 'node:fs/promises'
4
4
  import FS from '@nan0web/db-fs'
5
5
  import { NoConsole } from '@nan0web/log'
6
6
  import { DatasetParser, DocsParser, runSpawn } from '@nan0web/test'
7
- import { App } from './index.js'
7
+ import { ReleaseApp } from './index.js'
8
8
  import Release from './Release.js'
9
9
  import ReleaseDocument from './Release/Document.js'
10
10
  import Person from './Release/Person.js'
@@ -103,7 +103,7 @@ function testRender() {
103
103
  * nan0release init v1.0.0
104
104
  * ```
105
105
  */
106
- assert.ok(new App().constructor.command.options)
106
+ assert.ok(new ReleaseApp().constructor.command.options)
107
107
  })
108
108
 
109
109
  /**
@@ -134,7 +134,7 @@ function testRender() {
134
134
  * nan0release list [--json]
135
135
  * ```
136
136
  */
137
- assert.ok(new App().constructor.command.options)
137
+ assert.ok(new ReleaseApp().constructor.command.options)
138
138
  })
139
139
 
140
140
  /**
@@ -147,7 +147,7 @@ function testRender() {
147
147
  * nan0release chat write --user alice "Issue with the build pipeline"
148
148
  * ```
149
149
  */
150
- assert.ok(new App().constructor.command.options)
150
+ assert.ok(new ReleaseApp().constructor.command.options)
151
151
  })
152
152
 
153
153
  /**
@@ -160,7 +160,7 @@ function testRender() {
160
160
  * nan0release host [--webui] [--port 3000]
161
161
  * ```
162
162
  */
163
- assert.ok(new App().constructor.command.options)
163
+ assert.ok(new ReleaseApp().constructor.command.options)
164
164
  })
165
165
 
166
166
  /**
@@ -173,7 +173,7 @@ function testRender() {
173
173
  * nan0release serve [--port 8080]
174
174
  * ```
175
175
  */
176
- assert.ok(new App().constructor.command.options)
176
+ assert.ok(new ReleaseApp().constructor.command.options)
177
177
  })
178
178
 
179
179
  /**
@@ -204,7 +204,7 @@ function testRender() {
204
204
  * nan0release seal [--message "All core APIs are stable and tested"]
205
205
  * ```
206
206
  */
207
- assert.ok(new App().constructor.command.options)
207
+ assert.ok(new ReleaseApp().constructor.command.options)
208
208
  })
209
209
 
210
210
  /**
package/src/domain/App.js CHANGED
@@ -6,8 +6,9 @@ import DepsCommand from './DepsCommand.js'
6
6
  import PublishCommand from './PublishCommand.js'
7
7
  import SpecCommand from './SpecCommand.js'
8
8
  import StatusCommand from './StatusCommand.js'
9
+ import BumpCommand from './BumpCommand.js'
9
10
 
10
- export class App extends ModelAsApp {
11
+ export class ReleaseApp extends ModelAsApp {
11
12
  static command = {
12
13
  help: 'Subcommand to run',
13
14
  options: [
@@ -18,12 +19,14 @@ export class App extends ModelAsApp {
18
19
  PublishCommand,
19
20
  SpecCommand,
20
21
  StatusCommand,
22
+ BumpCommand,
21
23
  ],
24
+ positional: true,
22
25
  default: null,
23
26
  }
24
27
 
25
28
  /**
26
- * @param {Partial<App>} [data]
29
+ * @param {Partial<ReleaseApp>} [data]
27
30
  * @param {Partial<import('@nan0web/ui').ModelAsAppOptions>} [options]
28
31
  */
29
32
  constructor(data = {}, options = {}) {
@@ -0,0 +1,137 @@
1
+ import { ModelAsApp, result, show } from '@nan0web/ui'
2
+ import { runSpawn } from '@nan0web/test'
3
+
4
+ /**
5
+ * Command to bump the version of changed packages in the monorepo.
6
+ */
7
+ export default class BumpCommand extends ModelAsApp {
8
+ static version = {
9
+ help: 'Target version to set',
10
+ default: '3.1.1',
11
+ positional: true,
12
+ }
13
+ static since = {
14
+ help: 'Git reference to diff against',
15
+ default: 'v3.1.0',
16
+ positional: true,
17
+ }
18
+ static dryRun = {
19
+ alias: 'dry-run',
20
+ default: false,
21
+ help: 'Run the command without making any changes',
22
+ }
23
+ static UI = {
24
+ title: 'bump',
25
+ help: 'Bump version of changed packages in the monorepo',
26
+ bumping: 'Bumping {name} version: {oldVersion} -> {targetVersion} ({dir})',
27
+ skippingAlreadyAtVersion: 'Skipping the same version in {name} version: {version} ({dir})',
28
+ foundChangedPackages: 'Found {count} changed packages:',
29
+ detectingChangedPackages:
30
+ 'Detecting changed packages since {sinceRef} for bumping to {targetVersion}...',
31
+ noChangesDetected: 'No package changes detected.',
32
+ errorDb: 'Database not initialized',
33
+ }
34
+
35
+ /**
36
+ * @param {Partial<BumpCommand>} [data]
37
+ * @param {Partial<import('@nan0web/ui').ModelAsAppOptions>} [options]
38
+ */
39
+ constructor(data = {}, options = {}) {
40
+ super(data, options)
41
+ /** @type {string} Target version */ this.version
42
+ /** @type {string} Since reference */ this.since
43
+ /** @type {boolean} Dry run */ this.dryRun
44
+ }
45
+
46
+ /**
47
+ * @returns {AsyncGenerator<import('@nan0web/ui').Intent, import('@nan0web/ui').ResultIntent, any>}
48
+ */
49
+ async *run() {
50
+ const { db, t } = this._
51
+ if (!db) {
52
+ throw new Error(BumpCommand.UI.errorDb)
53
+ }
54
+
55
+ if (this.help) {
56
+ return yield* super.run()
57
+ }
58
+
59
+ const targetVersion = this.version || '3.1.1'
60
+ const sinceRef = this.since || 'v3.1.0'
61
+
62
+ yield show(
63
+ t(BumpCommand.UI.detectingChangedPackages, {
64
+ sinceRef,
65
+ targetVersion,
66
+ }),
67
+ )
68
+
69
+ const allFiles = new Set()
70
+
71
+ const addFilesFromCommand = async (cmd, args) => {
72
+ const res = await runSpawn(cmd, args)
73
+ if (res.code === 0) {
74
+ res.text
75
+ .split('\n')
76
+ .map((f) => f.trim())
77
+ .filter(Boolean)
78
+ .forEach((f) => allFiles.add(f))
79
+ }
80
+ }
81
+
82
+ // 1. Files modified since the release tag
83
+ await addFilesFromCommand('git', ['diff', '--name-only', sinceRef])
84
+ // 2. Unstaged changes in the working tree
85
+ await addFilesFromCommand('git', ['diff', '--name-only'])
86
+ // 3. Staged changes
87
+ await addFilesFromCommand('git', ['diff', '--cached', '--name-only'])
88
+
89
+ const changedPackages = new Set()
90
+ for (const file of allFiles) {
91
+ const parts = file.split('/')
92
+ if (parts.length >= 2 && (parts[0] === 'packages' || parts[0] === 'apps')) {
93
+ changedPackages.add(`${parts[0]}/${parts[1]}`)
94
+ }
95
+ }
96
+
97
+ if (changedPackages.size === 0) {
98
+ yield show(t(BumpCommand.UI.noChangesDetected), 'warn')
99
+ return result({})
100
+ }
101
+
102
+ yield show(t(BumpCommand.UI.foundChangedPackages, { count: changedPackages.size }))
103
+
104
+ for (const pkgDir of changedPackages) {
105
+ const pkgJsonPath = `@app/${pkgDir}/package.json`
106
+ const pkg = await db.loadDocument(pkgJsonPath, null)
107
+ if (pkg) {
108
+ const oldVersion = pkg.version
109
+ if (oldVersion === targetVersion) {
110
+ yield show(
111
+ t(BumpCommand.UI.skippingAlreadyAtVersion, {
112
+ name: pkg.name,
113
+ version: targetVersion,
114
+ dir: pkgDir,
115
+ }),
116
+ 'info',
117
+ )
118
+ continue
119
+ }
120
+ pkg.version = targetVersion
121
+ if (!this.dryRun) {
122
+ await db.saveDocument(pkgJsonPath, pkg)
123
+ }
124
+ yield show(
125
+ t(BumpCommand.UI.bumping, {
126
+ name: pkg.name,
127
+ oldVersion,
128
+ targetVersion,
129
+ dir: pkgDir,
130
+ }),
131
+ this.dryRun ? 'warn' : 'success',
132
+ )
133
+ }
134
+ }
135
+ return result({ success: true })
136
+ }
137
+ }
package/src/index.js CHANGED
@@ -3,7 +3,12 @@ import ReleaseDocument from './Release/Document.js'
3
3
  import Person from './Release/Person.js'
4
4
  import Scanner from './Release/Scanner.js'
5
5
  import MarkdownToTest from './Release/MarkdownToTest.js'
6
- import { ProjectManagement, ReleaseManager, TaskTestSuite, ChangelogTaskManager } from './architecture/ProjectManagementAsCode.js'
6
+ import {
7
+ ProjectManagement,
8
+ ReleaseManager,
9
+ TaskTestSuite,
10
+ ChangelogTaskManager,
11
+ } from './architecture/ProjectManagementAsCode.js'
7
12
 
8
13
  export {
9
14
  Release,
@@ -14,10 +19,10 @@ export {
14
19
  ProjectManagement,
15
20
  ReleaseManager,
16
21
  TaskTestSuite,
17
- ChangelogTaskManager
22
+ ChangelogTaskManager,
18
23
  }
19
24
 
20
- export { App } from './domain/App.js'
25
+ export { ReleaseApp } from './domain/App.js'
21
26
  export { default as InitCommand } from './domain/InitCommand.js'
22
27
  export { default as CheckCommand } from './domain/CheckCommand.js'
23
28
  export { default as CloseCommand } from './domain/CloseCommand.js'
@@ -1,14 +1,15 @@
1
- export class App extends ModelAsApp {
1
+ export class ReleaseApp extends ModelAsApp {
2
2
  static command: {
3
3
  help: string;
4
4
  options: (typeof CheckCommand | typeof StatusCommand)[];
5
+ positional: boolean;
5
6
  default: null;
6
7
  };
7
8
  /**
8
- * @param {Partial<App>} [data]
9
+ * @param {Partial<ReleaseApp>} [data]
9
10
  * @param {Partial<import('@nan0web/ui').ModelAsAppOptions>} [options]
10
11
  */
11
- constructor(data?: Partial<App>, options?: Partial<import("@nan0web/ui").ModelAsAppOptions>);
12
+ constructor(data?: Partial<ReleaseApp>, options?: Partial<import("@nan0web/ui").ModelAsAppOptions>);
12
13
  /** @type {ModelAsApp} Subcommand to run */ command: ModelAsApp;
13
14
  }
14
15
  import { ModelAsApp } from "@nan0web/ui";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Command to bump the version of changed packages in the monorepo.
3
+ */
4
+ export default class BumpCommand extends ModelAsApp {
5
+ static version: {
6
+ help: string;
7
+ default: string;
8
+ positional: boolean;
9
+ };
10
+ static since: {
11
+ help: string;
12
+ default: string;
13
+ positional: boolean;
14
+ };
15
+ static UI: {
16
+ title: string;
17
+ help: string;
18
+ bumping: string;
19
+ foundChangedPackages: string;
20
+ detectingChangedPackages: string;
21
+ noChangesDetected: string;
22
+ errorDb: string;
23
+ };
24
+ /**
25
+ * @param {Partial<BumpCommand>} [data]
26
+ * @param {Partial<import('@nan0web/ui').ModelAsAppOptions>} [options]
27
+ */
28
+ constructor(data?: Partial<BumpCommand>, options?: Partial<import("@nan0web/ui").ModelAsAppOptions>);
29
+ /** @type {string} Target version */ version: string;
30
+ /** @type {string} Since reference */ since: string;
31
+ }
32
+ import { ModelAsApp } from '@nan0web/ui';
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { App } from "./domain/App.js";
1
+ export { ReleaseApp } from "./domain/App.js";
2
2
  export { default as InitCommand } from "./domain/InitCommand.js";
3
3
  export { default as CheckCommand } from "./domain/CheckCommand.js";
4
4
  export { default as CloseCommand } from "./domain/CloseCommand.js";