@nan0web/release 1.0.1 → 1.0.2

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.
Files changed (108) hide show
  1. package/README.md +24 -42
  2. package/bin/nan0release.js +27 -42
  3. package/package.json +21 -14
  4. package/src/Release/Document.js +13 -19
  5. package/src/Release/MarkdownToTest.js +35 -33
  6. package/src/Release/Person.js +3 -8
  7. package/src/Release/Scanner.js +179 -0
  8. package/src/Release.js +19 -12
  9. package/src/Team.js +9 -9
  10. package/src/architecture/ProjectManagementAsCode.js +8 -8
  11. package/src/cli/index.js +9 -0
  12. package/src/co/AppCommandOptions.js +4 -6
  13. package/src/commands/CloseCommand.js +67 -0
  14. package/src/commands/Command.js +48 -0
  15. package/src/commands/DepsCommand.js +143 -0
  16. package/src/commands/InitCommand.js +48 -56
  17. package/src/commands/PublishCommand.js +80 -119
  18. package/src/commands/SpecCommand.js +41 -0
  19. package/src/commands/StatusCommand.js +26 -0
  20. package/src/db/ReleaseDB.js +5 -5
  21. package/src/index.js +18 -0
  22. package/src/ui/cli/ReleaseCLi.js +52 -0
  23. package/src/utils/runSpawn.js +0 -0
  24. package/types/Release/Document.d.ts +2 -2
  25. package/types/Release/Person.d.ts +3 -3
  26. package/types/Release/Scanner.d.ts +90 -0
  27. package/types/Release.d.ts +37 -33
  28. package/types/ReleaseCLI.d.ts +29 -28
  29. package/types/Team.d.ts +3 -3
  30. package/types/architecture/ProjectManagementAsCode.d.ts +1 -1
  31. package/types/cli/index.d.ts +2 -0
  32. package/types/co/AppCommandMessage.d.ts +10 -11
  33. package/types/co/AppCommandOptions.d.ts +1 -2
  34. package/types/commands/BaseCommand.d.ts +23 -0
  35. package/types/commands/ChatCommand.d.ts +9 -9
  36. package/types/commands/ChatMessage.d.ts +36 -0
  37. package/types/commands/CloseCommand.d.ts +25 -0
  38. package/types/commands/Command.d.ts +28 -0
  39. package/types/commands/DepsCommand.d.ts +32 -0
  40. package/types/commands/DepsMessage.d.ts +28 -0
  41. package/types/commands/HostCommand.d.ts +7 -7
  42. package/types/commands/HostMessage.d.ts +44 -0
  43. package/types/commands/InitCommand.d.ts +24 -19
  44. package/types/commands/InitMessage.d.ts +24 -0
  45. package/types/commands/ListCommand.d.ts +8 -8
  46. package/types/commands/ListMessage.d.ts +30 -0
  47. package/types/commands/PublishCommand.d.ts +36 -47
  48. package/types/commands/PublishMessage.d.ts +39 -0
  49. package/types/commands/SealCommand.d.ts +7 -7
  50. package/types/commands/SealMessage.d.ts +28 -0
  51. package/types/commands/ServeCommand.d.ts +7 -7
  52. package/types/commands/ServeMessage.d.ts +30 -0
  53. package/types/commands/ShowCommand.d.ts +7 -7
  54. package/types/commands/SpecCommand.d.ts +25 -0
  55. package/types/commands/StatusCommand.d.ts +9 -0
  56. package/types/commands/SubCommand.d.ts +9 -7
  57. package/types/commands/ValidateCommand.d.ts +7 -7
  58. package/types/commands/ValidateMessage.d.ts +20 -0
  59. package/types/db/ReleaseDB.d.ts +2 -2
  60. package/types/index.d.ts +10 -0
  61. package/types/ui/cli/ReleaseCLi.d.ts +10 -0
  62. package/types/ui/cli/index.d.ts +0 -0
  63. package/types/utils/runSpawn.d.ts +0 -0
  64. package/.datasets/README.dataset.jsonl +0 -19
  65. package/.editorconfig +0 -20
  66. package/CHANGELOG.md +0 -6
  67. package/CONTRIBUTING.md +0 -42
  68. package/bin/commands/InitCommand.js +0 -10
  69. package/bin/lib/functions.js +0 -240
  70. package/bin/lib/functions.test.js +0 -138
  71. package/bin/release.js +0 -12
  72. package/bin/release.test.js +0 -73
  73. package/bin/temp/package.json +0 -1
  74. package/docs/system.uk.md +0 -413
  75. package/docs/uk/README.md +0 -284
  76. package/legacy/PrepareCommand.js +0 -154
  77. package/legacy/PrepareCommand.test.js +0 -189
  78. package/legacy/changelog.js +0 -446
  79. package/releases/1/0/v1.0.0/models/Person.js +0 -26
  80. package/releases/1/0/v1.0.0/models/Person.test.js +0 -44
  81. package/releases/1/0/v1.0.0/models/company.js +0 -11
  82. package/releases/1/0/v1.0.0/models/members.js +0 -14
  83. package/releases/1/0/v1.0.0/models/members.test.js +0 -21
  84. package/releases/1/0/v1.0.0/models/teams/DevTeam.js +0 -6
  85. package/releases/1/0/v1.0.0/models/teams/DevTeam.test.js +0 -15
  86. package/releases/1/0/v1.0.0/models/teams/index.js +0 -5
  87. package/releases/1/0/v1.0.0/release.js +0 -12
  88. package/releases/1/0/v1.0.0/release.md +0 -121
  89. package/releases/1/0/v1.0.0/release.test.js +0 -36
  90. package/releases/1/0/v1.0.0/test/YaRaSLove/git-native.test.js +0 -14
  91. package/releases/current.js +0 -3
  92. package/releases/index.js +0 -11
  93. package/src/README.md.js +0 -468
  94. package/src/Release/MarkdownToTest.test.js +0 -60
  95. package/src/ReleaseCLI.js +0 -122
  96. package/src/architecture/ProjectManagementAsCode.test.js +0 -128
  97. package/src/co/AppCommandMessage.js +0 -22
  98. package/src/commands/ChatCommand.js +0 -56
  99. package/src/commands/HostCommand.js +0 -63
  100. package/src/commands/ListCommand.js +0 -56
  101. package/src/commands/SealCommand.js +0 -51
  102. package/src/commands/ServeCommand.js +0 -53
  103. package/src/commands/ShowCommand.js +0 -58
  104. package/src/commands/SubCommand.js +0 -21
  105. package/src/commands/ValidateCommand.js +0 -66
  106. package/system.md +0 -571
  107. package/tsconfig.json +0 -23
  108. /package/{bin/lib/temp/pnpm-lock.yaml → src/ui/cli/index.js} +0 -0
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # @nan0web/release
2
2
 
3
- |Package name|[Status](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Documentation|Test coverage|Features|Npm version|
4
- |---|---|---|---|---|---|
5
- |[@nan0web/release](https://github.com/nan0web/release/) |🟢 `97.1%` |🧪 [English 🏴󠁧󠁢󠁥󠁮󠁧󠁿](https://github.com/nan0web/release/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/release/blob/main/docs/uk/README.md) |🟡 `84.2%` |✅ d.ts 📜 system.md 🕹️ playground |— |
3
+ <!-- %PACKAGE_STATUS% -->
6
4
 
7
5
  Project management as code, Git-native, GPG-signed, and test-driven.
8
6
 
@@ -44,7 +42,7 @@ How to initialize a new release version?
44
42
  release init v1.0.0
45
43
  ```
46
44
 
47
- const cli = new ReleaseCLI()
45
+ const cli = ReleaseCLi()
48
46
  Show release details:
49
47
 
50
48
  How to show release information?
@@ -53,8 +51,8 @@ release show [--full]
53
51
  ```
54
52
 
55
53
  const release = new Release({
56
- version: "v1.0.0",
57
- createdAt: new Date("2025-08-20")
54
+ version: 'v1.0.0',
55
+ createdAt: new Date('2025-08-20'),
58
56
  })
59
57
  console.info(release.version) // v1.0.0
60
58
  List all releases in the project:
@@ -64,7 +62,7 @@ How to list all releases?
64
62
  release list [--json]
65
63
  ```
66
64
 
67
- const cli = new ReleaseCLI()
65
+ const cli = ReleaseCLi()
68
66
  Add a chat message to the current release:
69
67
 
70
68
  How to write a release chat message?
@@ -72,7 +70,7 @@ How to write a release chat message?
72
70
  release chat write --user alice "Issue with the build pipeline"
73
71
  ```
74
72
 
75
- const cli = new ReleaseCLI()
73
+ const cli = ReleaseCLi()
76
74
  Host a static server for viewing releases:
77
75
 
78
76
  How to host release UI?
@@ -80,7 +78,7 @@ How to host release UI?
80
78
  release host [--webui] [--port 3000]
81
79
  ```
82
80
 
83
- const cli = new ReleaseCLI()
81
+ const cli = ReleaseCLi()
84
82
  Serve all release files for local inspection:
85
83
 
86
84
  How to serve release static assets?
@@ -88,7 +86,7 @@ How to serve release static assets?
88
86
  release serve [--port 8080]
89
87
  ```
90
88
 
91
- const cli = new ReleaseCLI()
89
+ const cli = ReleaseCLi()
92
90
  Validate release tasks and integrity:
93
91
 
94
92
  How to validate release tasks?
@@ -97,8 +95,8 @@ release validate [--ignore-fail]
97
95
  ```
98
96
 
99
97
  const release = new Release({
100
- version: "v1.0.0",
101
- createdAt: new Date("2025-08-20")
98
+ version: 'v1.0.0',
99
+ createdAt: new Date('2025-08-20'),
102
100
  })
103
101
  Seal the release with retro reflection:
104
102
 
@@ -107,7 +105,7 @@ How to seal a release?
107
105
  release seal [--message "All core APIs are stable and tested"]
108
106
  ```
109
107
 
110
- const cli = new ReleaseCLI()
108
+ const cli = ReleaseCLi()
111
109
  ## Core Concepts
112
110
 
113
111
  ### 1. Release as Object
@@ -123,12 +121,11 @@ How to instantiate a Release?
123
121
  ```js
124
122
  import { Release } from '@nan0web/release'
125
123
  const release = new Release({
126
- version: "v1.0.0",
127
- createdAt: "2025-08-20T10:00:00Z"
124
+ version: 'v1.0.0',
125
+ createdAt: '2025-08-20T10:00:00Z',
128
126
  })
129
127
  console.info(release.version) // ← v1.0.0
130
128
  console.info(release.createdAt instanceof Date) // ← true
131
-
132
129
  ```
133
130
  ### 2. Release Document Parsing
134
131
 
@@ -141,19 +138,15 @@ How to parse release notes markdown into structured data?
141
138
  ```js
142
139
  import { ReleaseDocument } from '@nan0web/release'
143
140
  const md = `# v1.0.0 - 2025-08-20
144
-
145
141
  ## Overview
146
142
  Release milestone includes UI polish and core API stabilization.
147
-
148
143
  ### Tasks
149
144
  ### Done **Implement core UI design** [ui.core-design]
150
145
  ### InProgress **Fix responsive issues in mobile layout** [ui.mobile-fixes]`
151
-
152
146
  const doc = ReleaseDocument.from(md)
153
147
  console.info(doc.version) // ← v1.0.0
154
148
  console.info(doc.date instanceof Date) // ← true
155
149
  console.info(doc.document.children instanceof Array) // ← true
156
-
157
150
  ```
158
151
  ### 3. Person & Team Structures
159
152
 
@@ -166,13 +159,12 @@ How to create a Person with typed properties?
166
159
  ```js
167
160
  import { Person } from '@nan0web/release'
168
161
  const person = new Person({
169
- name: ["Alice", "Developer"],
170
- gender: "female",
171
- contacts: ["mailto:alice@example.com"]
162
+ name: ['Alice', 'Developer'],
163
+ gender: 'female',
164
+ contacts: ['mailto:alice@example.com'],
172
165
  })
173
166
  console.info(person.name.firstName) // ← Alice
174
167
  console.info(person.contacts.length >= 0) // ← true
175
-
176
168
  ```
177
169
  ## Architecture: Project Management as Code
178
170
 
@@ -187,21 +179,17 @@ How to register and validate tasks as tests?
187
179
  ```js
188
180
  import { ProjectManagement } from '@nan0web/release'
189
181
  const pm = new ProjectManagement()
190
- pm.registerTask("task-1", "./tests/task1.test.js")
191
- pm.registerTask("task-2", "./tests/task2.test.js")
192
-
182
+ pm.registerTask('task-1', './tests/task1.test.js')
183
+ pm.registerTask('task-2', './tests/task2.test.js')
193
184
  const mockResults = {
194
- passed: ["task-1"],
185
+ passed: ['task-1'],
195
186
  failed: [],
196
- pending: ["task-2"]
187
+ pending: ['task-2'],
197
188
  }
198
-
199
189
  pm.validateProjectState = async () => mockResults
200
190
  const results = await pm.validateProjectState()
201
-
202
- console.info(results.passed.includes("task-1")) // ← true
203
- console.info(results.pending.includes("task-2")) // ← true
204
-
191
+ console.info(results.passed.includes('task-1')) // ← true
192
+ console.info(results.pending.includes('task-2')) // ← true
205
193
  ```
206
194
  ### Release Processing
207
195
 
@@ -216,14 +204,11 @@ How to execute a release after validation?
216
204
  import { ReleaseManager, ProjectManagement } from '@nan0web/release'
217
205
  const pm = new ProjectManagement()
218
206
  const rm = new ReleaseManager(pm)
219
-
220
- rm.calculateVersion = () => "v1.0.1"
207
+ rm.calculateVersion = () => 'v1.0.1'
221
208
  rm.publish = async () => true
222
-
223
- const result = await rm.executeRelease("patch")
209
+ const result = await rm.executeRelease('patch')
224
210
  console.info(result.version) // ← v1.0.1
225
211
  console.info(result.published) // ← true
226
-
227
212
  ```
228
213
  ### Changelog Integration
229
214
 
@@ -237,16 +222,13 @@ How to parse changelog and extract tasks?
237
222
  import { ChangelogTaskManager } from '@nan0web/release'
238
223
  const ctm = new ChangelogTaskManager()
239
224
  const changelog = `# Changelog
240
-
241
225
  ## [1.0.0] - 2025-08-20
242
226
  ### Added
243
227
  - Initial structure [core.init]
244
228
  - Release notes support [docs.release-notes]`
245
-
246
229
  const tasks = ctm.parseChangelog(changelog)
247
230
  console.info(Array.isArray(tasks)) // ← true
248
231
  console.info(tasks.length >= 0) // ← true
249
-
250
232
  ```
251
233
  ## Java•Script Features
252
234
 
@@ -1,57 +1,42 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import process from "node:process"
4
- import { Command } from "@nan0web/co"
3
+ import process from 'node:process'
4
+
5
+ import { OutputMessage } from '@nan0web/co'
5
6
  import Logger from '@nan0web/log'
6
- import PublishCommand from "../src/commands/PublishCommand.js"
7
7
 
8
- class PrefixedLogger extends Logger {
9
- static PREFIX = Logger.style("nan0release", { bgColor: "magenta", color: "white" })
10
- get PREFIX() {
11
- return /** @type {typeof PrefixedLogger} */ (this.constructor).PREFIX
12
- }
13
- info(...args) {
14
- return super.info(this.PREFIX, ...args)
15
- }
16
- error(...args) {
17
- return super.error(this.PREFIX, ...args)
18
- }
19
- warn(...args) {
20
- return super.warn(this.PREFIX, ...args)
21
- }
22
- success(...args) {
23
- return super.success(this.PREFIX, ...args)
24
- }
25
- debug(...args) {
26
- return super.debug(this.PREFIX, ...args)
8
+ import createReleaseCLI from '../src/ui/cli/ReleaseCLi.js'
9
+
10
+ class OutputLogger extends Logger {
11
+ log(first, ...args) {
12
+ if (first && first instanceof OutputMessage) {
13
+ if (OutputMessage.TYPES.ERROR === first.type) {
14
+ return this.error(first.content, ...args)
15
+ } else if (OutputMessage.TYPES.WARNING === first.type) {
16
+ return this.warn(first.content, ...args)
17
+ } else if (OutputMessage.TYPES.SUCCESS === first.type) {
18
+ return this.success(first.content, ...args)
19
+ }
20
+ return this.info(first.content, ...args)
21
+ }
22
+ return super.log(first, ...args)
27
23
  }
28
24
  }
29
25
 
30
- const logger = new PrefixedLogger(Logger.detectLevel(process.argv))
31
-
32
- const mainCommand = new Command({
33
- name: "nan0release",
34
- help: "Release utilities for nan0web packages",
35
- logger,
36
- subcommands: [
37
- new PublishCommand({ logger }),
38
- ]
39
- })
26
+ const logger = new OutputLogger(Logger.detectLevel(process.argv))
40
27
 
41
28
  async function main(argv = []) {
42
- const msg = mainCommand.parse(argv.slice(2))
43
- logger.log(Logger.style(Logger.LOGO, { color: "magenta" }))
44
-
45
- if (msg.subCommand) {
46
- const cmd = mainCommand.getCommand(msg.subCommand)
47
- await cmd.run(msg.subCommandMessage)
48
- } else {
49
- logger.info(mainCommand.runHelp())
29
+ const cli = createReleaseCLI(argv, logger)
30
+ logger.info(Logger.style(Logger.LOGO, { color: Logger.MAGENTA }))
31
+
32
+ const stream = cli.run()
33
+ for await (const entry of stream) {
34
+ logger.info(entry)
50
35
  }
51
36
  }
52
37
 
53
- main(process.argv).catch(err => {
54
- logger.error("❌ Unhandled error:", err.message || err)
38
+ main(process.argv.slice(2)).catch((err) => {
39
+ logger.error('❌ Unhandled error:', err.message || err)
55
40
  if (err.stack) logger.debug(err.stack)
56
41
  process.exit(1)
57
42
  })
package/package.json CHANGED
@@ -1,24 +1,28 @@
1
1
  {
2
2
  "name": "@nan0web/release",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
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",
7
7
  "type": "module",
8
8
  "bin": {
9
9
  "nan0release": "./bin/nan0release.js",
10
- "release": "./bin/release.js"
10
+ "release": "./bin/nan0release.js"
11
11
  },
12
12
  "scripts": {
13
13
  "build": "tsc",
14
14
  "clean": "rm -rf .cache/ && rm -rf dist/",
15
15
  "clean:modules": "rm -rf node_modules",
16
- "test": "node --test \"src/**/*.test.js\" | nan0test parse --fail",
16
+ "test": "node --test \"src/**/*.test.js\"",
17
+ "test1": "node --test \"src/**/*.test.js\" | nan0test parse --fail",
17
18
  "test:docs": "node --test \"src/README.md.js\"",
18
19
  "test:release": "node --test \"releases/**/*.test.js\"",
19
20
  "test:coverage": "node --experimental-test-coverage --test-coverage-include=\"src/**/*.js\" --test-coverage-exclude=\"src/**/*.test.js\" --test \"src/**/*.test.js\"",
20
21
  "test:coverage:collect": "nan0test coverage",
21
22
  "test:status": "nan0test status",
23
+ "test:all": "npm run test && npm run test:docs && npm run build && npm run knip",
24
+ "test:all1": "npm run test && npm run test:docs && npm run test:status && npm run build",
25
+ "knip": "knip --production",
22
26
  "release": "node ./bin/nan0release.js publish",
23
27
  "precommit": "npm test",
24
28
  "prepush": "npm test",
@@ -26,18 +30,21 @@
26
30
  "playground": "node playground/main.js"
27
31
  },
28
32
  "dependencies": {
29
- "@nan0web/changelog": "^0.1.0",
30
- "@nan0web/co": "^1.0.0",
31
- "@nan0web/db": "^1.0.0",
32
- "@nan0web/db-fs": "^1.0.0",
33
- "@nan0web/log": "^1.0.0",
34
- "@nan0web/markdown": "^1.0.0",
35
- "@nan0web/types": "^1.0.0",
36
- "@nan0web/verse": "^1.0.0",
37
- "supports-color": "^9.4.0"
33
+ "@nan0web/changelog": "*",
34
+ "@nan0web/co": "*",
35
+ "@nan0web/db": "*",
36
+ "@nan0web/db-fs": "*",
37
+ "@nan0web/log": "*",
38
+ "@nan0web/markdown": "*",
39
+ "@nan0web/types": "*",
40
+ "@nan0web/ui": "*",
41
+ "@nan0web/ui-cli": "*",
42
+ "@nan0web/verse": "*",
43
+ "supports-color": "^10.2.2"
38
44
  },
39
45
  "devDependencies": {
40
- "@nan0web/test": "workspace:*",
41
- "husky": "^9.1.7"
46
+ "@nan0web/test": "*",
47
+ "husky": "^9.1.7",
48
+ "knip": "^5.85.0"
42
49
  }
43
50
  }
@@ -1,5 +1,5 @@
1
- import Markdown, { MDElement, MDHeading1, MDHeading2, MDHeading3 } from "@nan0web/markdown"
2
- import Person from "./Person.js"
1
+ import Markdown, { MDElement, MDHeading1, MDHeading2, MDHeading3 } from '@nan0web/markdown'
2
+ import Person from './Person.js'
3
3
 
4
4
  class ReleaseDocument extends Markdown {
5
5
  /** @type {Person[]} */
@@ -20,15 +20,10 @@ class ReleaseDocument extends Markdown {
20
20
  */
21
21
  constructor(options = {}) {
22
22
  super()
23
- const {
24
- team = [],
25
- roles = new Map(),
26
- version = "",
27
- date
28
- } = options
23
+ const { team = [], roles = new Map(), version = '', date } = options
29
24
  this.version = String(version)
30
25
  this.date = date ? new Date(date) : undefined
31
- this.team = team.map(t => Person.from(t))
26
+ this.team = team.map((t) => Person.from(t))
32
27
  this.roles = new Map(roles)
33
28
  }
34
29
 
@@ -43,13 +38,13 @@ class ReleaseDocument extends Markdown {
43
38
 
44
39
  const h1s = this.document.filter((el) => el instanceof MDHeading1)
45
40
  if (h1s.length !== 1) {
46
- throw new TypeError("Release document must have exactly one H1 heading with version and date")
41
+ throw new TypeError('Release document must have exactly one H1 heading with version and date')
47
42
  }
48
43
 
49
- const h1Content = h1s[0].content ?? ""
50
- const [versionPart, ...dateParts] = h1Content.split(" - ")
44
+ const h1Content = h1s[0].content ?? ''
45
+ const [versionPart, ...dateParts] = h1Content.split(' - ')
51
46
  this.version = versionPart.trim()
52
- this.date = new Date(dateParts.join(" - ").trim())
47
+ this.date = new Date(dateParts.join(' - ').trim())
53
48
 
54
49
  const sections = []
55
50
  /** @type {{title: string, tasks: Array} | null} */
@@ -58,11 +53,10 @@ class ReleaseDocument extends Markdown {
58
53
  if (el instanceof MDHeading2) {
59
54
  currentSection = {
60
55
  title: el.content.trim(),
61
- tasks: []
56
+ tasks: [],
62
57
  }
63
58
  sections.push(currentSection)
64
- }
65
- else if (el instanceof MDHeading3 && currentSection) {
59
+ } else if (el instanceof MDHeading3 && currentSection) {
66
60
  const content = el.content.trim()
67
61
  const statusMatch = content.match(/^(\w+)\s*(.+)$/)
68
62
  const slugMatch = content.match(/\[([^\]]+)\]$/)
@@ -84,7 +78,7 @@ class ReleaseDocument extends Markdown {
84
78
  currentSection.tasks.push({
85
79
  content: taskContent,
86
80
  status: status,
87
- slug: slug
81
+ slug: slug,
88
82
  })
89
83
  }
90
84
  }
@@ -98,7 +92,7 @@ class ReleaseDocument extends Markdown {
98
92
  */
99
93
  static from(input) {
100
94
  if (input instanceof ReleaseDocument) return input
101
- if (typeof input === "string") {
95
+ if (typeof input === 'string') {
102
96
  const doc = new ReleaseDocument()
103
97
  doc.parse(input)
104
98
  return doc
@@ -107,4 +101,4 @@ class ReleaseDocument extends Markdown {
107
101
  }
108
102
  }
109
103
 
110
- export default ReleaseDocument
104
+ export default ReleaseDocument
@@ -11,22 +11,22 @@ class MarkdownToTest {
11
11
  generateTests(markdown) {
12
12
  const lines = markdown.split('\n')
13
13
  const versionMatch = markdown.match(/^#\s+(v[\d.]+)\s*-\s*(\d{4}-\d{2}-\d{2})/)
14
-
14
+
15
15
  if (!versionMatch) {
16
16
  throw new Error('Markdown must start with version header: # vX.Y.Z - YYYY-MM-DD')
17
17
  }
18
-
18
+
19
19
  const [, version, date] = versionMatch
20
20
  let testCode = this.generateImports()
21
21
  testCode += this.generateDescribeHeader(version, date)
22
-
22
+
23
23
  const sections = this.extractSections(lines)
24
24
  testCode += this.generateSectionTests(sections)
25
-
25
+
26
26
  testCode += '})\n'
27
27
  return testCode
28
28
  }
29
-
29
+
30
30
  /**
31
31
  * Generate import statements for node:test
32
32
  * @returns {string} Import code
@@ -37,7 +37,7 @@ import { ok, strictEqual } from "node:assert"
37
37
 
38
38
  `
39
39
  }
40
-
40
+
41
41
  /**
42
42
  * Generate main describe block header
43
43
  * @param {string} version - Release version
@@ -48,7 +48,7 @@ import { ok, strictEqual } from "node:assert"
48
48
  return `describe("${version} - ${date}", () => {
49
49
  `
50
50
  }
51
-
51
+
52
52
  /**
53
53
  * Extract sections from markdown lines
54
54
  * @param {string[]} lines - Markdown lines
@@ -59,20 +59,20 @@ import { ok, strictEqual } from "node:assert"
59
59
  const sections = []
60
60
  /** @type {{title: string, tasks: Array<{content: string, status: string, slug: string}>} | null} */
61
61
  let currentSection = null
62
-
62
+
63
63
  for (let i = 0; i < lines.length; i++) {
64
64
  const line = lines[i]
65
-
65
+
66
66
  // H2 section
67
67
  if (line.startsWith('## ')) {
68
68
  currentSection = {
69
69
  title: line.slice(3).trim(),
70
- tasks: /** @type {Array<{content: string, status: string, slug: string}>} */([])
70
+ tasks: /** @type {Array<{content: string, status: string, slug: string}>} */ ([]),
71
71
  }
72
72
  sections.push(currentSection)
73
73
  continue
74
74
  }
75
-
75
+
76
76
  // H3 task
77
77
  if (line.startsWith('###') && currentSection) {
78
78
  const statusMatch = line.match(/^###( Draft| InProgress)? \*\*(.+)\*\* \[(.+)\]$/)
@@ -81,16 +81,16 @@ import { ok, strictEqual } from "node:assert"
81
81
  currentSection.tasks.push({
82
82
  content,
83
83
  status: status ? status.trim() : 'Done',
84
- slug
84
+ slug,
85
85
  })
86
86
  }
87
87
  continue
88
88
  }
89
89
  }
90
-
90
+
91
91
  return sections
92
92
  }
93
-
93
+
94
94
  /**
95
95
  * Generate test code for sections and their tasks
96
96
  * @param {Array<{title: string, tasks: Array}>} sections - Sections with tasks
@@ -98,40 +98,42 @@ import { ok, strictEqual } from "node:assert"
98
98
  */
99
99
  generateSectionTests(sections) {
100
100
  let code = ''
101
-
102
- sections.forEach(section => {
101
+
102
+ sections.forEach((section) => {
103
103
  code += ` describe("${section.title}", () => {
104
104
  `
105
-
106
- section.tasks.forEach(/** @param {{status: string, content: string}} task */task => {
107
- switch (task.status) {
108
- case 'Draft':
109
- code += ` it.todo("${task.content}", () => {
105
+
106
+ section.tasks.forEach(
107
+ /** @param {{status: string, content: string}} task */ (task) => {
108
+ switch (task.status) {
109
+ case 'Draft':
110
+ code += ` it.todo("${task.content}", () => {
110
111
  ok(false, "Draft task - not yet implemented")
111
112
  })
112
113
  `
113
- break
114
- case 'InProgress':
115
- code += ` it.skip("${task.content}", () => {
114
+ break
115
+ case 'InProgress':
116
+ code += ` it.skip("${task.content}", () => {
116
117
  ok(false, "In progress task - not yet completed")
117
118
  })
118
119
  `
119
- break
120
- default: // Done
121
- code += ` it("${task.content}", () => {
120
+ break
121
+ default: // Done
122
+ code += ` it("${task.content}", () => {
122
123
  ok(true, "Task completed successfully")
123
124
  })
124
125
  `
125
- break
126
- }
127
- })
128
-
126
+ break
127
+ }
128
+ },
129
+ )
130
+
129
131
  code += ` })
130
132
  `
131
133
  })
132
-
134
+
133
135
  return code
134
136
  }
135
137
  }
136
138
 
137
- export default MarkdownToTest
139
+ export default MarkdownToTest
@@ -1,4 +1,4 @@
1
- import { HumanName, HumanContact, HumanGender } from "@nan0web/verse"
1
+ import { HumanName, HumanContact, HumanGender } from '@nan0web/verse'
2
2
 
3
3
  export default class Person {
4
4
  /** @type {HumanName} */
@@ -8,14 +8,10 @@ export default class Person {
8
8
  /** @type {HumanContact[]} */
9
9
  contacts
10
10
  constructor(input = {}) {
11
- const {
12
- name = new HumanName([]),
13
- gender = new HumanGender(-1),
14
- contacts = []
15
- } = input
11
+ const { name = new HumanName([]), gender = new HumanGender(-1), contacts = [] } = input
16
12
  this.name = HumanName.from(name)
17
13
  this.gender = HumanGender.from(gender)
18
- this.contacts = contacts.map(c => HumanContact.from(c))
14
+ this.contacts = contacts.map((c) => HumanContact.from(c))
19
15
  }
20
16
  /**
21
17
  * @param {*} input
@@ -26,4 +22,3 @@ export default class Person {
26
22
  return new Person(input)
27
23
  }
28
24
  }
29
-