@nan0web/release 3.3.0 → 3.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.
Files changed (73) hide show
  1. package/bin/nan0release.js +33 -2
  2. package/bin/serve.js +73 -0
  3. package/package.json +45 -17
  4. package/src/Release/Document.js +1 -0
  5. package/src/Release/Scanner.js +3 -2
  6. package/src/Release.js +7 -7
  7. package/src/domain/App.js +31 -2
  8. package/src/domain/BumpCommand.js +10 -3
  9. package/src/domain/CheckCommand.js +504 -146
  10. package/src/domain/CheckCommand.story.js +92 -0
  11. package/src/domain/CloseCommand.js +13 -9
  12. package/src/domain/Dashboard/Dashboard.story.js +155 -0
  13. package/src/domain/Dashboard/DashboardModel.js +308 -0
  14. package/src/domain/Dashboard/ReleaseDiscovery.js +132 -0
  15. package/src/domain/Dashboard/ReleaseParser.js +226 -0
  16. package/src/domain/Dashboard/index.js +19 -0
  17. package/src/domain/DepsCommand.js +5 -2
  18. package/src/domain/InitCommand.js +18 -16
  19. package/src/domain/ListCommand.js +45 -0
  20. package/src/domain/PreviewCommand.js +39 -0
  21. package/src/domain/PublishCommand.js +7 -3
  22. package/src/domain/Registry/Registry.story.js +82 -0
  23. package/src/domain/Registry/RegistryModel.js +124 -0
  24. package/src/domain/ServeCommand.js +165 -0
  25. package/src/domain/ServeCommand.story.js +88 -0
  26. package/src/domain/SpecCommand.js +3 -1
  27. package/src/domain/StatusCommand.js +249 -3
  28. package/src/domain/ViewCommand.js +99 -0
  29. package/src/domain/WebCommand.js +140 -0
  30. package/src/domain/inspect/ReleaseAuditor.js +508 -0
  31. package/src/domain/inspect/ReleaseAuditor.story.js +136 -0
  32. package/src/domain/templates/release.html +34 -0
  33. package/src/domain/templates/release.html.template.js +34 -0
  34. package/src/index.js +6 -0
  35. package/src/inspectors/inspect-js.js +32 -0
  36. package/src/releases/1/0/v1.0.3/task.test.js +1 -1
  37. package/src/utils/nodejs/GitTelemetry.js +154 -0
  38. package/types/Release/Document.d.ts +24 -27
  39. package/types/Release/MarkdownToTest.d.ts +1 -1
  40. package/types/Release/Person.d.ts +9 -7
  41. package/types/Release/Scanner.d.ts +41 -41
  42. package/types/Release.d.ts +42 -42
  43. package/types/architecture/ProjectManagementAsCode.d.ts +59 -64
  44. package/types/domain/App.d.ts +24 -7
  45. package/types/domain/BumpCommand.d.ts +11 -6
  46. package/types/domain/CheckCommand.d.ts +128 -16
  47. package/types/domain/CheckCommand.story.d.ts +1 -0
  48. package/types/domain/CloseCommand.d.ts +4 -6
  49. package/types/domain/Dashboard/Dashboard.story.d.ts +1 -0
  50. package/types/domain/Dashboard/DashboardModel.d.ts +273 -0
  51. package/types/domain/Dashboard/GitTelemetry.d.ts +23 -0
  52. package/types/domain/Dashboard/ReleaseDiscovery.d.ts +47 -0
  53. package/types/domain/Dashboard/ReleaseParser.d.ts +79 -0
  54. package/types/domain/Dashboard/index.d.ts +3 -0
  55. package/types/domain/DepsCommand.d.ts +6 -6
  56. package/types/domain/InitCommand.d.ts +4 -6
  57. package/types/domain/ListCommand.d.ts +18 -0
  58. package/types/domain/PreviewCommand.d.ts +6 -0
  59. package/types/domain/PublishCommand.d.ts +8 -6
  60. package/types/domain/Registry/Registry.story.d.ts +1 -0
  61. package/types/domain/Registry/RegistryModel.d.ts +61 -0
  62. package/types/domain/ServeCommand.d.ts +59 -0
  63. package/types/domain/ServeCommand.story.d.ts +1 -0
  64. package/types/domain/SpecCommand.d.ts +4 -6
  65. package/types/domain/StatusCommand.d.ts +38 -3
  66. package/types/domain/ViewCommand.d.ts +27 -0
  67. package/types/domain/WebCommand.d.ts +47 -0
  68. package/types/domain/inspect/ReleaseAuditor.d.ts +134 -0
  69. package/types/domain/inspect/ReleaseAuditor.story.d.ts +1 -0
  70. package/types/domain/templates/release.html.template.d.ts +2 -0
  71. package/types/index.d.ts +18 -10
  72. package/types/inspectors/inspect-js.d.ts +2 -0
  73. package/types/utils/nodejs/GitTelemetry.d.ts +23 -0
@@ -0,0 +1,34 @@
1
+ export default `<!DOCTYPE html>
2
+ <html lang="uk" data-bs-theme="dark">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Releases Catalog — NaN•Web</title>
7
+ <style>
8
+ :root {
9
+ --bg: #0f172a;
10
+ --surface: #1e293b;
11
+ --accent: #38bdf8;
12
+ --text: #f8fafc;
13
+ --text-dim: #94a3b8;
14
+ --border: #334155;
15
+ }
16
+ body { font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 2.5rem 1.5rem; display: flex; justify-content: center; line-height: 1.6; }
17
+ .container { max-width: 880px; width: 100%; }
18
+ h1, h2, h3 { color: #fff; font-weight: 700; margin-top: 1.5rem; }
19
+ h1 { font-size: 2rem; border-bottom: 1px solid var(--border); padding-bottom: 0.8rem; }
20
+ a { color: var(--accent); text-decoration: none; }
21
+ a:hover { text-decoration: underline; }
22
+ table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; background: var(--surface); border-radius: 8px; overflow: hidden; }
23
+ th, td { padding: 0.85rem 1rem; text-align: left; border-bottom: 1px solid var(--border); }
24
+ th { background: rgba(0,0,0,0.2); font-weight: 600; color: var(--accent); }
25
+ pre { background: var(--surface); padding: 1rem; border-radius: 8px; border: 1px solid var(--border); overflow-x: auto; color: #a5b4fc; font-family: monospace; }
26
+ blockquote { border-left: 4px solid var(--accent); margin: 1rem 0; padding: 0.5rem 1rem; background: var(--surface); border-radius: 0 8px 8px 0; }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <div class="container">
31
+ {{CONTENT}}
32
+ </div>
33
+ </body>
34
+ </html>`
package/src/index.js CHANGED
@@ -30,3 +30,9 @@ export { default as DepsCommand } from './domain/DepsCommand.js'
30
30
  export { default as PublishCommand } from './domain/PublishCommand.js'
31
31
  export { default as SpecCommand } from './domain/SpecCommand.js'
32
32
  export { default as StatusCommand } from './domain/StatusCommand.js'
33
+ export { default as WebCommand } from './domain/WebCommand.js'
34
+ export { default as PreviewCommand } from './domain/PreviewCommand.js'
35
+ export { RegistryModel } from './domain/Registry/RegistryModel.js'
36
+ export { DashboardModel } from './domain/Dashboard/DashboardModel.js'
37
+ export { ReleaseAuditor } from './domain/inspect/ReleaseAuditor.js'
38
+
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ // Inspector: checks JavaScript/TypeScript files for syntax errors using `node --check`.
3
+ // Uses git to obtain list of changed files in the current HEAD.
4
+ const { execSync } = require('child_process');
5
+
6
+ function getChangedFiles() {
7
+ try {
8
+ const output = execSync('git diff --name-only --diff-filter=ACM HEAD', { encoding: 'utf8' });
9
+ return output.split(/\n/).filter(f => f.match(/\.(js|ts)$/));
10
+ } catch (e) {
11
+ console.error('Failed to obtain changed files:', e.message);
12
+ process.exit(1);
13
+ }
14
+ }
15
+
16
+ function checkFile(file) {
17
+ console.log(`🔎 Checking ${file}`);
18
+ try {
19
+ execSync(`node --check ${file}`, { stdio: 'inherit' });
20
+ } catch (e) {
21
+ console.error(`❌ Syntax error in ${file}`);
22
+ process.exit(1);
23
+ }
24
+ }
25
+
26
+ const files = getChangedFiles();
27
+ if (files.length === 0) {
28
+ console.log('✅ No JavaScript/TypeScript files changed.');
29
+ process.exit(0);
30
+ }
31
+ files.forEach(checkFile);
32
+ process.exit(0);
@@ -9,7 +9,7 @@ describe('Release v3.0.0 - Dependency Alignment', () => {
9
9
  const pkgPath = join(process.cwd(), 'package.json')
10
10
  const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
11
11
 
12
- assert.ok(/^3\.1\.\d+$/.test(pkg.version), 'Version should start with 3.1')
12
+ assert.ok(/^3\.\d+\.\d+$/.test(pkg.version), 'Version should start with 3.x')
13
13
  assert.ok(/^(\^1\.8\.0|workspace:\*)$/.test(pkg.dependencies['@nan0web/ui']), '@nan0web/ui should be ^1.8.0 or workspace:*')
14
14
  assert.ok(/^(\^2\.9\.0|workspace:\*)$/.test(pkg.dependencies['@nan0web/ui-cli']), '@nan0web/ui-cli should be ^2.9.0 or workspace:*')
15
15
  })
@@ -0,0 +1,154 @@
1
+ import fs from 'node:fs'
2
+ import { execSync } from 'node:child_process'
3
+
4
+ let rootGitStatusCache = null
5
+ let rootGitBranchCache = null
6
+ const gitInfoCache = new Map()
7
+ const gitTelemetryCache = new Map()
8
+
9
+ /**
10
+ * Reset internal Git caches (useful for testing or cache invalidation)
11
+ */
12
+ export function resetGitCache() {
13
+ rootGitStatusCache = null
14
+ rootGitBranchCache = null
15
+ gitInfoCache.clear()
16
+ gitTelemetryCache.clear()
17
+ }
18
+
19
+ /**
20
+ * Retrieve git branch and workspace status (clean / dirty)
21
+ * @param {string} [projectDir]
22
+ * @returns {{ branch: string, gitStatus: 'clean' | 'dirty' }}
23
+ */
24
+ export function getGitInfo(projectDir) {
25
+ const key = projectDir || process.cwd()
26
+ const isMonorepoInternal =
27
+ !projectDir ||
28
+ projectDir === '.' ||
29
+ (!projectDir.startsWith('../') && !projectDir.startsWith('/'))
30
+
31
+ if (isMonorepoInternal) {
32
+ if (rootGitStatusCache === null) {
33
+ try {
34
+ rootGitBranchCache =
35
+ execSync('git rev-parse --abbrev-ref HEAD', {
36
+ cwd: process.cwd(),
37
+ stdio: ['ignore', 'pipe', 'ignore'],
38
+ encoding: 'utf8',
39
+ }).trim() || 'main'
40
+ rootGitStatusCache = execSync('git status --porcelain', {
41
+ cwd: process.cwd(),
42
+ stdio: ['ignore', 'pipe', 'ignore'],
43
+ encoding: 'utf8',
44
+ }).trim()
45
+ } catch {
46
+ rootGitBranchCache = 'main'
47
+ rootGitStatusCache = ''
48
+ }
49
+ }
50
+ const normPrefix =
51
+ projectDir && projectDir !== '.'
52
+ ? `${projectDir.replace(/\/+$/, '')}/`
53
+ : ''
54
+ const isDirty = normPrefix
55
+ ? rootGitStatusCache
56
+ .split('\n')
57
+ .some((line) => line.slice(3).trim().startsWith(normPrefix))
58
+ : rootGitStatusCache.length > 0
59
+
60
+ return {
61
+ branch: rootGitBranchCache,
62
+ gitStatus: isDirty ? 'dirty' : 'clean',
63
+ }
64
+ }
65
+
66
+ if (gitInfoCache.has(key)) return gitInfoCache.get(key)
67
+ if (fs.existsSync && !fs.existsSync(key)) {
68
+ const res = { branch: 'main', gitStatus: 'clean' }
69
+ gitInfoCache.set(key, res)
70
+ return res
71
+ }
72
+
73
+ try {
74
+ const branch = execSync('git rev-parse --abbrev-ref HEAD', {
75
+ cwd: key,
76
+ stdio: ['ignore', 'pipe', 'ignore'],
77
+ encoding: 'utf8',
78
+ }).trim()
79
+ const statusOutput = execSync('git status --porcelain', {
80
+ cwd: key,
81
+ stdio: ['ignore', 'pipe', 'ignore'],
82
+ encoding: 'utf8',
83
+ }).trim()
84
+ const res = {
85
+ branch: branch || 'main',
86
+ gitStatus: statusOutput.length > 0 ? 'dirty' : 'clean',
87
+ }
88
+ gitInfoCache.set(key, res)
89
+ return res
90
+ } catch {
91
+ const res = { branch: 'main', gitStatus: 'clean' }
92
+ gitInfoCache.set(key, res)
93
+ return res
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Retrieve development hours and iterations from git commit log
99
+ * @param {string} [projectDir]
100
+ * @param {string} [releasePath]
101
+ * @returns {{ hours: number, iterations: number }}
102
+ */
103
+ export function getGitCommitTelemetry(projectDir, releasePath) {
104
+ const targetDir = releasePath || projectDir
105
+ if (!targetDir) return { hours: 0, iterations: 0 }
106
+ if (gitTelemetryCache.has(targetDir)) return gitTelemetryCache.get(targetDir)
107
+ if (fs.existsSync && !fs.existsSync(targetDir)) {
108
+ const res = { hours: 0, iterations: 0 }
109
+ gitTelemetryCache.set(targetDir, res)
110
+ return res
111
+ }
112
+
113
+ try {
114
+ const logOutput = execSync(
115
+ `git log --format="%at" -n 50 -- "${targetDir}"`,
116
+ {
117
+ cwd: process.cwd(),
118
+ stdio: ['ignore', 'pipe', 'ignore'],
119
+ encoding: 'utf8',
120
+ }
121
+ ).trim()
122
+
123
+ if (!logOutput) {
124
+ const res = { hours: 0, iterations: 0 }
125
+ gitTelemetryCache.set(targetDir, res)
126
+ return res
127
+ }
128
+
129
+ const timestamps = logOutput
130
+ .split('\n')
131
+ .map((t) => parseInt(t.trim(), 10))
132
+ .filter((t) => !isNaN(t))
133
+
134
+ if (timestamps.length < 2) {
135
+ const res = { hours: 0.5, iterations: timestamps.length }
136
+ gitTelemetryCache.set(targetDir, res)
137
+ return res
138
+ }
139
+
140
+ const minT = Math.min(...timestamps)
141
+ const maxT = Math.max(...timestamps)
142
+ const diffHours = Math.round(((maxT - minT) / 3600) * 10) / 10
143
+ const hours = diffHours > 0 ? diffHours : 0.5
144
+ const iterations = timestamps.length
145
+
146
+ const res = { hours, iterations }
147
+ gitTelemetryCache.set(targetDir, res)
148
+ return res
149
+ } catch {
150
+ const res = { hours: 0, iterations: 0 }
151
+ gitTelemetryCache.set(targetDir, res)
152
+ return res
153
+ }
154
+ }
@@ -1,14 +1,10 @@
1
- import Markdown, { MDElement } from '@nan0web/markdown';
2
- import Person from './Person.js';
1
+ export default ReleaseDocument;
3
2
  declare class ReleaseDocument extends Markdown {
4
- /** @type {Person[]} */
5
- team: Person[];
6
- /** @type {Map<string, Person[]>} */
7
- roles: Map<string, Person[]>;
8
- /** @type {string} */
9
- version: string;
10
- /** @type {Date | undefined} */
11
- date: Date | undefined;
3
+ /**
4
+ * @param {*} input
5
+ * @returns {ReleaseDocument}
6
+ */
7
+ static from(input: any): ReleaseDocument;
12
8
  /**
13
9
  * @param {Object} options
14
10
  * @param {Array} [options.team] - Release team members
@@ -17,22 +13,23 @@ declare class ReleaseDocument extends Markdown {
17
13
  * @param {string} [options.date] - Release date
18
14
  */
19
15
  constructor(options?: {
20
- team?: any[];
21
- roles?: Map<any, any> | any[];
22
- version?: string;
23
- date?: string;
16
+ team?: any[] | undefined;
17
+ roles?: any[] | Map<any, any> | undefined;
18
+ version?: string | undefined;
19
+ date?: string | undefined;
24
20
  });
25
- /**
26
- * Parse release document content
27
- * Extracts version and date from H1 heading
28
- * @param {string} input - Markdown content
29
- * @returns {MDElement[]}
30
- */
31
- parse(input: string): MDElement[];
32
- /**
33
- * @param {*} input
34
- * @returns {ReleaseDocument}
35
- */
36
- static from(input: any): ReleaseDocument;
21
+ /** @type {Person[]} */
22
+ team: Person[];
23
+ /** @type {Map<string, Person[]>} */
24
+ roles: Map<string, Person[]>;
25
+ /** @type {string} */
26
+ version: string;
27
+ /** @type {Date | undefined} */
28
+ date: Date | undefined;
29
+ sections: {
30
+ title: string;
31
+ tasks: any[];
32
+ }[] | undefined;
37
33
  }
38
- export default ReleaseDocument;
34
+ import Markdown from '@nan0web/markdown';
35
+ import Person from './Person.js';
@@ -1,3 +1,4 @@
1
+ export default MarkdownToTest;
1
2
  /**
2
3
  * MarkdownToTest - generates node:test code from markdown release notes
3
4
  * Enables writing release notes first, then generating executable tests
@@ -44,4 +45,3 @@ declare class MarkdownToTest {
44
45
  tasks: any[];
45
46
  }>): string;
46
47
  }
47
- export default MarkdownToTest;
@@ -1,15 +1,17 @@
1
- import { HumanName, HumanContact, HumanGender } from '@nan0web/logos';
2
1
  export default class Person {
2
+ /**
3
+ * @param {*} input
4
+ * @returns {Person}
5
+ */
6
+ static from(input: any): Person;
7
+ constructor(input?: {});
3
8
  /** @type {HumanName} */
4
9
  name: HumanName;
5
10
  /** @type {HumanGender} */
6
11
  gender: HumanGender;
7
12
  /** @type {HumanContact[]} */
8
13
  contacts: HumanContact[];
9
- constructor(input?: {});
10
- /**
11
- * @param {*} input
12
- * @returns {Person}
13
- */
14
- static from(input: any): Person;
15
14
  }
15
+ import { HumanName } from '@nan0web/logos';
16
+ import { HumanGender } from '@nan0web/logos';
17
+ import { HumanContact } from '@nan0web/logos';
@@ -1,39 +1,3 @@
1
- export type ContractEntry = {
2
- /**
3
- * - Release version (e.g. "v1.0.0")
4
- */
5
- version: string;
6
- /**
7
- * - Absolute path to the contract file
8
- */
9
- path: string;
10
- /**
11
- * - "spec" or "test"
12
- */
13
- type: string;
14
- /**
15
- * - Directory containing the contract
16
- */
17
- dir: string;
18
- };
19
- export type VersionStatus = {
20
- /**
21
- * - Release version
22
- */
23
- version: string;
24
- /**
25
- * - Version state
26
- */
27
- state: 'wip' | 'closed' | 'mixed';
28
- /**
29
- * - Paths to spec files
30
- */
31
- specs: string[];
32
- /**
33
- * - Paths to test files
34
- */
35
- tests: string[];
36
- };
37
1
  /**
38
2
  * @typedef {Object} ContractEntry
39
3
  * @property {string} version - Release version (e.g. "v1.0.0")
@@ -54,13 +18,12 @@ export type VersionStatus = {
54
18
  * та плоску: releases/v{version}/
55
19
  */
56
20
  export default class Scanner {
57
- #private;
58
- /** @type {string} */
59
- root: string;
60
21
  /**
61
- * @param {string} root - Root directory of the project
22
+ * @param {string} [root] - Root directory of the project
62
23
  */
63
- constructor(root: string);
24
+ constructor(root?: string);
25
+ /** @type {string} */
26
+ root: string;
64
27
  /**
65
28
  * Find all .spec.js files (WIP contracts)
66
29
  * @param {string} [version] - Optional version filter
@@ -87,4 +50,41 @@ export default class Scanner {
87
50
  closed: number;
88
51
  files: string[];
89
52
  };
53
+ #private;
90
54
  }
55
+ export type ContractEntry = {
56
+ /**
57
+ * - Release version (e.g. "v1.0.0")
58
+ */
59
+ version: string;
60
+ /**
61
+ * - Absolute path to the contract file
62
+ */
63
+ path: string;
64
+ /**
65
+ * - "spec" or "test"
66
+ */
67
+ type: string;
68
+ /**
69
+ * - Directory containing the contract
70
+ */
71
+ dir: string;
72
+ };
73
+ export type VersionStatus = {
74
+ /**
75
+ * - Release version
76
+ */
77
+ version: string;
78
+ /**
79
+ * - Version state
80
+ */
81
+ state: "wip" | "closed" | "mixed";
82
+ /**
83
+ * - Paths to spec files
84
+ */
85
+ specs: string[];
86
+ /**
87
+ * - Paths to test files
88
+ */
89
+ tests: string[];
90
+ };
@@ -1,39 +1,3 @@
1
- import ReleaseDocument from './Release/Document.js';
2
- import Logger from '@nan0web/log';
3
- export type ReleaseConfig = {
4
- /**
5
- * - Release version
6
- */
7
- version?: string;
8
- /**
9
- * -
10
- */
11
- createdAt?: string | number | Date | undefined;
12
- /**
13
- * - Alias for createdAt
14
- */
15
- date?: string | number | Date | undefined;
16
- /**
17
- * -
18
- */
19
- startAt?: string | number | Date | undefined;
20
- /**
21
- * -
22
- */
23
- planAt?: string | number | Date | undefined;
24
- /**
25
- * -
26
- */
27
- completeAt?: string | number | Date | undefined;
28
- /**
29
- * -
30
- */
31
- document?: string | ReleaseDocument;
32
- /**
33
- * - Task map with test functions
34
- */
35
- tasks?: Map<string, Function>;
36
- };
37
1
  /**
38
2
  * @typedef {Object} ReleaseConfig
39
3
  * @property {string} [version] - Release version
@@ -49,6 +13,11 @@ export type ReleaseConfig = {
49
13
  * Release management class that coordinates task validation and release execution
50
14
  */
51
15
  export default class Release {
16
+ /**
17
+ * Creates a Release instance
18
+ * @param {ReleaseConfig} config - Release configuration
19
+ */
20
+ constructor(config?: ReleaseConfig);
52
21
  /** @type {string} */
53
22
  version: string;
54
23
  /** @type {Date} */
@@ -65,11 +34,6 @@ export default class Release {
65
34
  document: ReleaseDocument;
66
35
  /** @type {Logger} */
67
36
  logger: Logger;
68
- /**
69
- * Creates a Release instance
70
- * @param {ReleaseConfig} config - Release configuration
71
- */
72
- constructor(config?: ReleaseConfig);
73
37
  get path(): string;
74
38
  /**
75
39
  * Validate release by running all task tests
@@ -83,7 +47,7 @@ export default class Release {
83
47
  * @returns {Promise<boolean>} Release success status
84
48
  */
85
49
  execute(options?: {
86
- ignoreFailTests?: boolean;
50
+ ignoreFailTests?: boolean | undefined;
87
51
  }): Promise<boolean>;
88
52
  /**
89
53
  * Get release progress statistics
@@ -91,3 +55,39 @@ export default class Release {
91
55
  */
92
56
  getProgress(): Promise<any>;
93
57
  }
58
+ export type ReleaseConfig = {
59
+ /**
60
+ * - Release version
61
+ */
62
+ version?: string | undefined;
63
+ /**
64
+ * -
65
+ */
66
+ createdAt?: string | number | Date | undefined;
67
+ /**
68
+ * - Alias for createdAt
69
+ */
70
+ date?: string | number | Date | undefined;
71
+ /**
72
+ * -
73
+ */
74
+ startAt?: string | number | Date | undefined;
75
+ /**
76
+ * -
77
+ */
78
+ planAt?: string | number | Date | undefined;
79
+ /**
80
+ * -
81
+ */
82
+ completeAt?: string | number | Date | undefined;
83
+ /**
84
+ * -
85
+ */
86
+ document?: string | ReleaseDocument | undefined;
87
+ /**
88
+ * - Task map with test functions
89
+ */
90
+ tasks?: Map<string, Function> | undefined;
91
+ };
92
+ import ReleaseDocument from './Release/Document.js';
93
+ import Logger from '@nan0web/log';