@nu-art/build-and-install 0.401.0 → 0.401.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.
Files changed (155) hide show
  1. package/BuildAndInstall.d.ts +40 -0
  2. package/BuildAndInstall.js +155 -0
  3. package/build-and-install-v3.d.ts +1 -44
  4. package/build-and-install-v3.js +1 -157
  5. package/build-and-install.js +11 -11
  6. package/config/consts.d.ts +43 -0
  7. package/config/consts.js +42 -0
  8. package/{core → config}/package/consts.d.ts +1 -1
  9. package/{core → config}/types/project-config.d.ts +3 -0
  10. package/core/FilesCache.d.ts +50 -0
  11. package/core/FilesCache.js +76 -0
  12. package/core/Unit_HelpPrinter.d.ts +16 -0
  13. package/core/Unit_HelpPrinter.js +47 -0
  14. package/core/params/params.d.ts +1 -41
  15. package/core/params/params.js +1 -332
  16. package/core/params.d.ts +50 -0
  17. package/core/params.js +441 -0
  18. package/{v3/core → core}/types.d.ts +1 -1
  19. package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.d.ts +21 -1
  20. package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.js +26 -3
  21. package/dependencies/types.d.ts +1 -0
  22. package/dependencies/types.js +1 -0
  23. package/exceptions/PhaseAggregatedException.d.ts +34 -0
  24. package/{core/exceptions → exceptions}/PhaseAggregatedException.js +26 -0
  25. package/exceptions/UnitPhaseException.d.ts +20 -0
  26. package/exceptions/UnitPhaseException.js +21 -0
  27. package/exports/ExportIndexCache.d.ts +25 -0
  28. package/exports/ExportIndexCache.js +115 -0
  29. package/exports/ExportMapper.d.ts +43 -0
  30. package/exports/ExportMapper.js +519 -0
  31. package/exports/IndicesMcpServer.d.ts +22 -0
  32. package/exports/IndicesMcpServer.js +220 -0
  33. package/exports/types.js +3 -0
  34. package/package.json +20 -9
  35. package/phases/PhaseManager.d.ts +130 -0
  36. package/{v3 → phases}/PhaseManager.js +99 -2
  37. package/{v3/phase → phases/definitions}/consts.d.ts +36 -0
  38. package/{v3/phase → phases/definitions}/consts.js +44 -2
  39. package/phases/definitions/types.d.ts +40 -0
  40. package/phases/index.d.ts +2 -0
  41. package/phases/index.js +2 -0
  42. package/run.js +10 -0
  43. package/runtime/RunningStatusHandler.d.ts +104 -0
  44. package/runtime/RunningStatusHandler.js +153 -0
  45. package/runtime/types.d.ts +1 -0
  46. package/runtime/types.js +2 -0
  47. package/{defaults → templates}/consts.d.ts +9 -0
  48. package/{defaults → templates}/consts.js +12 -2
  49. package/templates/firebase/functions/cloudbuild.yaml +17 -0
  50. package/templates/firebase/functions/dockerfile +19 -0
  51. package/templates/firebase/functions/service.yaml +49 -0
  52. package/{v3/units → units/base}/BaseUnit.d.ts +34 -4
  53. package/{v3/units → units/base}/BaseUnit.js +22 -2
  54. package/units/base/ProjectUnit.d.ts +32 -0
  55. package/units/base/ProjectUnit.js +25 -0
  56. package/units/base/types.js +1 -0
  57. package/units/discovery/UnitsMapper.d.ts +69 -0
  58. package/{v3/UnitsMapper → units/discovery}/UnitsMapper.js +50 -2
  59. package/units/discovery/resolvers/UnitMapper_Base.d.ts +65 -0
  60. package/units/discovery/resolvers/UnitMapper_Base.js +46 -0
  61. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseFunction.d.ts +5 -3
  62. package/units/discovery/resolvers/UnitMapper_FirebaseFunction.js +105 -0
  63. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.d.ts +3 -2
  64. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.js +14 -10
  65. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.d.ts +1 -1
  66. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.js +2 -2
  67. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.d.ts +24 -1
  68. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.js +24 -1
  69. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.d.ts +22 -1
  70. package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.js +22 -1
  71. package/units/discovery/types.js +1 -0
  72. package/units/implementations/Unit_NodeProject.d.ts +59 -0
  73. package/{v3/units → units/implementations}/Unit_NodeProject.js +65 -5
  74. package/units/implementations/Unit_PackageJson.d.ts +56 -0
  75. package/{v3/units → units/implementations}/Unit_PackageJson.js +39 -3
  76. package/{v3/units → units/implementations}/Unit_TypescriptLib.d.ts +40 -4
  77. package/{v3/units → units/implementations}/Unit_TypescriptLib.js +167 -17
  78. package/units/implementations/firebase/Unit_FirebaseFunctionsApp.d.ts +233 -0
  79. package/units/implementations/firebase/Unit_FirebaseFunctionsApp.js +804 -0
  80. package/units/implementations/firebase/Unit_FirebaseHostingApp.d.ts +113 -0
  81. package/units/implementations/firebase/Unit_FirebaseHostingApp.js +320 -0
  82. package/units/implementations/firebase/common.d.ts +26 -0
  83. package/units/implementations/firebase/common.js +65 -0
  84. package/units/index.d.ts +6 -0
  85. package/units/index.js +6 -0
  86. package/v3/core/Unit_HelpPrinter.d.ts +1 -16
  87. package/v3/core/Unit_HelpPrinter.js +1 -47
  88. package/{v3 → workspace}/Workspace.d.ts +30 -15
  89. package/{v3 → workspace}/Workspace.js +48 -35
  90. package/core/consts.d.ts +0 -13
  91. package/core/consts.js +0 -12
  92. package/core/exceptions/PhaseAggregatedException.d.ts +0 -8
  93. package/core/exceptions/UnitPhaseException.d.ts +0 -5
  94. package/core/exceptions/UnitPhaseException.js +0 -6
  95. package/old/PhaseRunnerDispatcher.d.ts +0 -24
  96. package/old/PhaseRunnerDispatcher.js +0 -32
  97. package/old/runner-dispatchers.d.ts +0 -10
  98. package/old/runner-dispatchers.js +0 -3
  99. package/v3/PhaseManager.d.ts +0 -27
  100. package/v3/RunningStatusHandler.d.ts +0 -18
  101. package/v3/RunningStatusHandler.js +0 -67
  102. package/v3/UnitsMapper/UnitsMapper.d.ts +0 -21
  103. package/v3/UnitsMapper/resolvers/UnitMapper_Base.d.ts +0 -23
  104. package/v3/UnitsMapper/resolvers/UnitMapper_Base.js +0 -16
  105. package/v3/UnitsMapper/resolvers/UnitMapper_FirebaseFunction.js +0 -66
  106. package/v3/core/FilesCache.d.ts +0 -7
  107. package/v3/core/FilesCache.js +0 -33
  108. package/v3/phase/types.d.ts +0 -10
  109. package/v3/units/ProjectUnit.d.ts +0 -18
  110. package/v3/units/ProjectUnit.js +0 -11
  111. package/v3/units/Unit_NodeProject.d.ts +0 -30
  112. package/v3/units/Unit_PackageJson.d.ts +0 -17
  113. package/v3/units/firebase/Unit_FirebaseFunctionsApp.d.ts +0 -64
  114. package/v3/units/firebase/Unit_FirebaseFunctionsApp.js +0 -306
  115. package/v3/units/firebase/Unit_FirebaseHostingApp.d.ts +0 -49
  116. package/v3/units/firebase/Unit_FirebaseHostingApp.js +0 -118
  117. package/v3/units/firebase/common.d.ts +0 -3
  118. package/v3/units/firebase/common.js +0 -13
  119. package/v3/units/index.d.ts +0 -6
  120. package/v3/units/index.js +0 -6
  121. /package/{core → config}/package/consts.js +0 -0
  122. /package/{core → config}/types/configs/firebasejson.d.ts +0 -0
  123. /package/{core → config}/types/configs/firebasejson.js +0 -0
  124. /package/{core → config}/types/configs/firebaserc.d.ts +0 -0
  125. /package/{core → config}/types/configs/firebaserc.js +0 -0
  126. /package/{core → config}/types/configs/index.d.ts +0 -0
  127. /package/{core → config}/types/configs/index.js +0 -0
  128. /package/{core → config}/types/configs/package-json.d.ts +0 -0
  129. /package/{core → config}/types/configs/package-json.js +0 -0
  130. /package/{core → config}/types/core.d.ts +0 -0
  131. /package/{core → config}/types/core.js +0 -0
  132. /package/{core → config}/types/index.d.ts +0 -0
  133. /package/{core → config}/types/index.js +0 -0
  134. /package/{core → config}/types/package/index.d.ts +0 -0
  135. /package/{core → config}/types/package/index.js +0 -0
  136. /package/{core → config}/types/package/package.d.ts +0 -0
  137. /package/{core → config}/types/package/package.js +0 -0
  138. /package/{core → config}/types/package/runtime-package.d.ts +0 -0
  139. /package/{core → config}/types/package/runtime-package.js +0 -0
  140. /package/{core → config}/types/project-config.js +0 -0
  141. /package/{v3/core → core}/types.js +0 -0
  142. /package/{v3/UnitsMapper/types.js → exports/types.d.ts} +0 -0
  143. /package/{v3/phase → phases/definitions}/index.d.ts +0 -0
  144. /package/{v3/phase → phases/definitions}/index.js +0 -0
  145. /package/{v3/phase → phases/definitions}/types.js +0 -0
  146. /package/{v3/units/types.js → run.d.ts} +0 -0
  147. /package/{defaults/backend-proxy → templates/backend/proxy}/proxy._ts +0 -0
  148. /package/{defaults/.firebase_config → templates/firebase/config}/database.rules.json +0 -0
  149. /package/{defaults/.firebase_config → templates/firebase/config}/firestore.indexes.json +0 -0
  150. /package/{defaults/.firebase_config → templates/firebase/config}/firestore.rules +0 -0
  151. /package/{defaults/.firebase_config → templates/firebase/config}/storage.rules +0 -0
  152. /package/{v3/units → units/base}/types.d.ts +0 -0
  153. /package/{v3/UnitsMapper → units/discovery}/resolvers/index.d.ts +0 -0
  154. /package/{v3/UnitsMapper → units/discovery}/resolvers/index.js +0 -0
  155. /package/{v3/UnitsMapper → units/discovery}/types.d.ts +0 -0
@@ -0,0 +1,22 @@
1
+ import { ProjectUnit } from '../units/base/ProjectUnit.js';
2
+ import { Logger } from '@nu-art/ts-common';
3
+ export declare class IndicesMcpServer extends Logger {
4
+ private server?;
5
+ private port;
6
+ private projectRoot;
7
+ private packages;
8
+ constructor(port: number, projectRoot: string, packages: ProjectUnit[]);
9
+ start(): Promise<void>;
10
+ stop(): Promise<void>;
11
+ private handleRequest;
12
+ private handleHealth;
13
+ private handlePackages;
14
+ private handlePackageRoutes;
15
+ private handleGetAllExports;
16
+ private handleGetByName;
17
+ private handleGetByFile;
18
+ private handleGetByType;
19
+ private handleStale;
20
+ private sendJson;
21
+ private sendError;
22
+ }
@@ -0,0 +1,220 @@
1
+ import { createServer } from 'http';
2
+ import { URL } from 'url';
3
+ import { ExportIndexCache } from './ExportIndexCache.js';
4
+ import { Unit_TypescriptLib } from '../units/implementations/Unit_TypescriptLib.js';
5
+ import { Logger } from '@nu-art/ts-common';
6
+ export class IndicesMcpServer extends Logger {
7
+ server;
8
+ port;
9
+ projectRoot;
10
+ packages;
11
+ constructor(port, projectRoot, packages) {
12
+ super();
13
+ this.port = port;
14
+ this.projectRoot = projectRoot;
15
+ this.packages = packages;
16
+ }
17
+ async start() {
18
+ return new Promise((resolve, reject) => {
19
+ this.server = createServer((req, res) => this.handleRequest(req, res));
20
+ this.server.listen(this.port, () => {
21
+ this.logInfo(`Export Indices MCP Server started on port ${this.port}`);
22
+ this.logInfo(`Available packages: ${this.packages.map(p => p.config.key).join(', ')}`);
23
+ resolve();
24
+ });
25
+ this.server.on('error', (error) => {
26
+ if (error.code === 'EADDRINUSE') {
27
+ this.logError(`Port ${this.port} is already in use`);
28
+ reject(new Error(`Port ${this.port} is already in use`));
29
+ }
30
+ else {
31
+ this.logError('Server error:', error);
32
+ reject(error);
33
+ }
34
+ });
35
+ });
36
+ }
37
+ async stop() {
38
+ return new Promise((resolve) => {
39
+ if (!this.server) {
40
+ resolve();
41
+ return;
42
+ }
43
+ this.server.close(() => {
44
+ this.logInfo('Export Indices MCP Server stopped');
45
+ resolve();
46
+ });
47
+ });
48
+ }
49
+ async handleRequest(req, res) {
50
+ try {
51
+ const url = new URL(req.url || '/', `http://${req.headers.host}`);
52
+ const path = url.pathname;
53
+ const method = req.method;
54
+ // Set CORS headers
55
+ res.setHeader('Access-Control-Allow-Origin', '*');
56
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
57
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
58
+ res.setHeader('Content-Type', 'application/json');
59
+ if (method === 'OPTIONS') {
60
+ res.writeHead(200);
61
+ res.end();
62
+ return;
63
+ }
64
+ if (method !== 'GET') {
65
+ this.sendError(res, 405, 'Method not allowed');
66
+ return;
67
+ }
68
+ // Route handling
69
+ if (path === '/health') {
70
+ this.handleHealth(res);
71
+ }
72
+ else if (path === '/packages') {
73
+ await this.handlePackages(res);
74
+ }
75
+ else if (path.startsWith('/packages/')) {
76
+ await this.handlePackageRoutes(path, res);
77
+ }
78
+ else {
79
+ this.sendError(res, 404, 'Not found');
80
+ }
81
+ }
82
+ catch (error) {
83
+ this.logError('Request handling error:', error);
84
+ this.sendError(res, 500, error.message || 'Internal server error');
85
+ }
86
+ }
87
+ handleHealth(res) {
88
+ this.sendJson(res, { status: 'ok', service: 'Export Indices MCP Server' });
89
+ }
90
+ async handlePackages(res) {
91
+ const packages = this.packages
92
+ .filter(unit => unit.isInstanceOf(Unit_TypescriptLib))
93
+ .map(unit => ({
94
+ name: unit.config.key,
95
+ root: unit.config.fullPath
96
+ }));
97
+ this.sendJson(res, { packages });
98
+ }
99
+ async handlePackageRoutes(path, res) {
100
+ // Extract package name and remaining path
101
+ // Path format: /packages/:packageName/...
102
+ const pathParts = path.split('/').filter(p => p);
103
+ if (pathParts.length < 2 || pathParts[0] !== 'packages') {
104
+ this.sendError(res, 404, 'Invalid path');
105
+ return;
106
+ }
107
+ const packageName = decodeURIComponent(pathParts[1]);
108
+ const packageUnit = this.packages.find(p => p.config.key === packageName);
109
+ if (!packageUnit || !packageUnit.isInstanceOf(Unit_TypescriptLib)) {
110
+ this.sendError(res, 404, `Package '${packageName}' not found`);
111
+ return;
112
+ }
113
+ const packageRoot = packageUnit.config.fullPath;
114
+ const remainingPath = pathParts.slice(2).join('/');
115
+ if (remainingPath === 'exports') {
116
+ await this.handleGetAllExports(packageName, packageRoot, res);
117
+ }
118
+ else if (remainingPath.startsWith('exports/by-name/')) {
119
+ const symbolName = decodeURIComponent(remainingPath.replace('exports/by-name/', ''));
120
+ await this.handleGetByName(packageName, packageRoot, symbolName, res);
121
+ }
122
+ else if (remainingPath.startsWith('exports/by-file/')) {
123
+ const filePath = decodeURIComponent(remainingPath.replace('exports/by-file/', ''));
124
+ await this.handleGetByFile(packageName, packageRoot, filePath, res);
125
+ }
126
+ else if (remainingPath.startsWith('exports/by-type/')) {
127
+ const symbolType = decodeURIComponent(remainingPath.replace('exports/by-type/', ''));
128
+ await this.handleGetByType(packageName, packageRoot, symbolType, res);
129
+ }
130
+ else if (remainingPath === 'stale') {
131
+ await this.handleStale(packageName, packageRoot, res);
132
+ }
133
+ else {
134
+ this.sendError(res, 404, 'Not found');
135
+ }
136
+ }
137
+ async handleGetAllExports(packageName, packageRoot, res) {
138
+ try {
139
+ const exports = await ExportIndexCache.getAll(this.projectRoot, packageRoot, packageName);
140
+ this.sendJson(res, { package: packageName, exports });
141
+ }
142
+ catch (error) {
143
+ if (error.message?.includes('Index file not found')) {
144
+ this.sendError(res, 404, `Indices not found for package '${packageName}'. Run 'bai --map-exports' to generate indices.`);
145
+ }
146
+ else {
147
+ this.sendError(res, 500, error.message || 'Failed to get exports');
148
+ }
149
+ }
150
+ }
151
+ async handleGetByName(packageName, packageRoot, symbolName, res) {
152
+ try {
153
+ const symbol = await ExportIndexCache.getByName(this.projectRoot, packageRoot, packageName, symbolName);
154
+ if (!symbol) {
155
+ this.sendError(res, 404, `Symbol '${symbolName}' not found in package '${packageName}'`);
156
+ return;
157
+ }
158
+ this.sendJson(res, { package: packageName, symbol });
159
+ }
160
+ catch (error) {
161
+ if (error.message?.includes('Index file not found')) {
162
+ this.sendError(res, 404, `Indices not found for package '${packageName}'. Run 'bai --map-exports' to generate indices.`);
163
+ }
164
+ else {
165
+ this.sendError(res, 500, error.message || 'Failed to get symbol');
166
+ }
167
+ }
168
+ }
169
+ async handleGetByFile(packageName, packageRoot, filePath, res) {
170
+ try {
171
+ const exports = await ExportIndexCache.getByFile(this.projectRoot, packageRoot, packageName, filePath);
172
+ this.sendJson(res, { package: packageName, filePath, exports });
173
+ }
174
+ catch (error) {
175
+ if (error.message?.includes('Index file not found')) {
176
+ this.sendError(res, 404, `Indices not found for package '${packageName}'. Run 'bai --map-exports' to generate indices.`);
177
+ }
178
+ else {
179
+ this.sendError(res, 500, error.message || 'Failed to get exports by file');
180
+ }
181
+ }
182
+ }
183
+ async handleGetByType(packageName, packageRoot, symbolType, res) {
184
+ try {
185
+ const exports = await ExportIndexCache.getByType(this.projectRoot, packageRoot, packageName, symbolType);
186
+ this.sendJson(res, { package: packageName, symbolType, exports });
187
+ }
188
+ catch (error) {
189
+ if (error.message?.includes('Index file not found')) {
190
+ this.sendError(res, 404, `Indices not found for package '${packageName}'. Run 'bai --map-exports' to generate indices.`);
191
+ }
192
+ else {
193
+ this.sendError(res, 500, error.message || 'Failed to get exports by type');
194
+ }
195
+ }
196
+ }
197
+ async handleStale(packageName, packageRoot, res) {
198
+ try {
199
+ const stale = await ExportIndexCache.isStale(this.projectRoot, packageRoot, packageName);
200
+ this.sendJson(res, {
201
+ package: packageName,
202
+ stale,
203
+ message: stale
204
+ ? "Source files are newer than index files. Run 'bai --map-exports' to regenerate."
205
+ : 'Indices are up to date.'
206
+ });
207
+ }
208
+ catch (error) {
209
+ this.sendError(res, 500, error.message || 'Failed to check stale status');
210
+ }
211
+ }
212
+ sendJson(res, data) {
213
+ res.writeHead(200);
214
+ res.end(JSON.stringify(data, null, 2));
215
+ }
216
+ sendError(res, statusCode, message) {
217
+ res.writeHead(statusCode);
218
+ res.end(JSON.stringify({ error: message }, null, 2));
219
+ }
220
+ }
@@ -0,0 +1,3 @@
1
+ // Export types will be defined here if needed
2
+ // Currently using types from ExportMapper.ts
3
+ export {};
package/package.json CHANGED
@@ -1,24 +1,32 @@
1
1
  {
2
2
  "name": "@nu-art/build-and-install",
3
- "version": "0.401.0",
4
- "description": "",
3
+ "version": "0.401.1",
4
+ "description": "A build system for monorepos that orchestrates building, testing, and deploying units with dependency-aware phase execution",
5
5
  "type": "module",
6
6
  "keywords": [
7
- "TacB0sS",
8
- "infra",
7
+ "typescript",
8
+ "build-system",
9
+ "monorepo",
10
+ "dependency-management",
11
+ "phase-execution",
12
+ "workspace",
13
+ "units",
14
+ "automation",
9
15
  "nu-art",
10
- "commando"
16
+ "thunderstorm",
17
+ "build-and-install"
11
18
  ],
12
19
  "homepage": "https://github.com/nu-art-js/thunderstorm",
13
20
  "bugs": {
14
- "url": "https://github.com/nu-art-js/thunderstorm/issues"
21
+ "url": "https://github.com/nu-art-js/thunderstorm/issues?q=is%3Aissue+label%3Abuild-and-install"
15
22
  },
16
23
  "publishConfig": {
17
24
  "directory": "dist"
18
25
  },
19
26
  "repository": {
20
27
  "type": "git",
21
- "url": "git+ssh://git@github.com:nu-art-js/thunderstorm.git"
28
+ "url": "git+ssh://git@github.com:nu-art-js/thunderstorm.git",
29
+ "directory": "_thunderstorm/build-and-install"
22
30
  },
23
31
  "license": "Apache-2.0",
24
32
  "author": "TacB0sS",
@@ -31,8 +39,11 @@
31
39
  },
32
40
  "dependencies": {
33
41
  "chokidar": "^3.6.0",
34
- "@nu-art/ts-common": "0.401.0",
35
- "@nu-art/commando": "0.401.0"
42
+ "@nu-art/ts-common": "0.401.1",
43
+ "@nu-art/commando": "0.401.1"
44
+ },
45
+ "devDependencies": {
46
+ "@nu-art/testalot": "0.401.1"
36
47
  },
37
48
  "unitConfig": {
38
49
  "type": "typescript-lib"
@@ -0,0 +1,130 @@
1
+ import { Logger } from '@nu-art/ts-common';
2
+ import { RunningStatusHandler } from '../runtime/RunningStatusHandler.js';
3
+ import { Phase } from './definitions/index.js';
4
+ import { BaseUnit } from '../units/index.js';
5
+ /**
6
+ * Scheduled execution step (before mapping to actual phases/units).
7
+ */
8
+ export type ScheduledStep = {
9
+ phases: string[];
10
+ units: string[];
11
+ };
12
+ /**
13
+ * Mapped execution step with actual phase and unit instances.
14
+ */
15
+ export type ExecutionStep = {
16
+ phases: Phase<any>[];
17
+ units: BaseUnit<any>[];
18
+ };
19
+ /**
20
+ * Manages phase execution across units in dependency order.
21
+ *
22
+ * **Execution Model**:
23
+ * - **Phase Groups**: Phases that can run in parallel (e.g., [prepare, compile])
24
+ * - **Unit Layers**: Units grouped by dependency level (dependencies first)
25
+ * - **Steps**: Combinations of phase groups × unit layers
26
+ *
27
+ * **Execution Flow**:
28
+ * 1. `calculateExecutionSteps()`: Plans which phases run on which units
29
+ * 2. `execute()`: Executes steps sequentially, phases in parallel within steps
30
+ * 3. Units in same layer run phases in parallel (Promise.all)
31
+ *
32
+ * **Eligibility Rules**:
33
+ * - Unit must implement the phase method (e.g., `compile()`, `test()`)
34
+ * - Unit must be in active/project units (based on phase.unitCategory)
35
+ * - Phase filter (if present) must pass runtime params
36
+ *
37
+ * **Error Handling**:
38
+ * - First failure stops execution (sets `killed = true`)
39
+ * - Aggregates all errors into `PhaseAggregatedException`
40
+ * - Tracks running units for graceful shutdown
41
+ *
42
+ * **Resume Support**:
43
+ * - Skips completed steps (via `runningStatus.startIndex`)
44
+ * - Skips completed units within steps (via `runningStatus.isCompleted()`)
45
+ *
46
+ * **Validation**:
47
+ * - Constructor validates no duplicate units or phases
48
+ * - Throws `BadImplementationException` on duplicates
49
+ */
50
+ export declare class PhaseManager extends Logger {
51
+ private readonly phases;
52
+ private readonly units;
53
+ private runningUnits;
54
+ private killed;
55
+ private runningStatus;
56
+ private activeUnits;
57
+ private projectUnitKeys;
58
+ private readonly keyToPhaseMap;
59
+ constructor(runningStatus: RunningStatusHandler, phases: Phase<any>[][], units: BaseUnit[][], activeUnits: string[], projectUnitKeys: string[]);
60
+ /**
61
+ * Calculates the execution plan: which phases run on which units.
62
+ *
63
+ * **Algorithm**:
64
+ * 1. For each phase group (phases that can run together)
65
+ * 2. Filter phases by runtime params (if phase.filter exists)
66
+ * 3. For each unit layer (dependency level)
67
+ * 4. Find units eligible for at least one phase in the group
68
+ * 5. Group units by which phases they support
69
+ * 6. Create steps: phase combinations × unit groups
70
+ *
71
+ * **Phase Grouping**: Units that support the same set of phases are grouped
72
+ * together in a step (identified by phase keys joined with '|').
73
+ *
74
+ * **Unit Eligibility**:
75
+ * - Unit must implement phase method
76
+ * - Unit must be in active/project units (based on phase.unitCategory)
77
+ *
78
+ * @returns Array of scheduled steps (phases and unit keys)
79
+ */
80
+ calculateExecutionSteps(): Promise<ScheduledStep[]>;
81
+ /**
82
+ * Executes the planned steps sequentially.
83
+ *
84
+ * **Execution Model**:
85
+ * - Steps run sequentially (one after another)
86
+ * - Units within a step run phases in parallel (Promise.all)
87
+ * - Phases for a unit run sequentially (in phase group order)
88
+ *
89
+ * **Resume Support**:
90
+ * - Starts from `runningStatus.startIndex` (if --continue)
91
+ * - Skips units marked as completed
92
+ *
93
+ * **Dry Run**: If `--dry-run`, only logs phase/unit names without executing.
94
+ *
95
+ * **Error Handling**:
96
+ * - First error stops execution (sets `killed = true`)
97
+ * - All errors aggregated into `PhaseAggregatedException`
98
+ * - Running units tracked for graceful shutdown
99
+ *
100
+ * **Performance**: Logs operation duration if > 1.5 seconds.
101
+ *
102
+ * @param _steps - Scheduled steps to execute
103
+ * @throws PhaseAggregatedException if any phase fails
104
+ */
105
+ execute(_steps: ScheduledStep[]): Promise<void>;
106
+ /**
107
+ * Gracefully stops execution and kills all running units.
108
+ *
109
+ * Called on SIGINT (Ctrl+C). Sets `killed = true` to stop further execution,
110
+ * then calls `kill()` on all currently running units.
111
+ *
112
+ * @returns Promise that resolves when all units are killed
113
+ */
114
+ break(): Promise<void[]>;
115
+ /**
116
+ * Maps scheduled step (with string keys) to execution step (with actual instances).
117
+ *
118
+ * **Mapping Process**:
119
+ * - Maps phase keys to Phase instances using `keyToPhaseMap`
120
+ * - Maps unit keys to BaseUnit instances by searching through unit layers
121
+ *
122
+ * **Performance Note**: Unit lookup iterates through all layers (O(n) complexity).
123
+ * Consider using a lookup map for O(1) access in large workspaces.
124
+ *
125
+ * @param scheduledStep - Scheduled step with phase/unit keys
126
+ * @returns Execution step with phase/unit instances
127
+ * @throws Error if phase or unit not found
128
+ */
129
+ private mapStep;
130
+ }
@@ -1,6 +1,37 @@
1
1
  import { addItemToArray, BadImplementationException, exists, flatArray, Logger, removeItemFromArray, timeCounter } from '@nu-art/ts-common';
2
- import { PhaseAggregatedException } from '../core/exceptions/PhaseAggregatedException.js';
3
- import { UnitPhaseException } from '../core/exceptions/UnitPhaseException.js';
2
+ import { PhaseAggregatedException } from '../exceptions/PhaseAggregatedException.js';
3
+ import { UnitPhaseException } from '../exceptions/UnitPhaseException.js';
4
+ /**
5
+ * Manages phase execution across units in dependency order.
6
+ *
7
+ * **Execution Model**:
8
+ * - **Phase Groups**: Phases that can run in parallel (e.g., [prepare, compile])
9
+ * - **Unit Layers**: Units grouped by dependency level (dependencies first)
10
+ * - **Steps**: Combinations of phase groups × unit layers
11
+ *
12
+ * **Execution Flow**:
13
+ * 1. `calculateExecutionSteps()`: Plans which phases run on which units
14
+ * 2. `execute()`: Executes steps sequentially, phases in parallel within steps
15
+ * 3. Units in same layer run phases in parallel (Promise.all)
16
+ *
17
+ * **Eligibility Rules**:
18
+ * - Unit must implement the phase method (e.g., `compile()`, `test()`)
19
+ * - Unit must be in active/project units (based on phase.unitCategory)
20
+ * - Phase filter (if present) must pass runtime params
21
+ *
22
+ * **Error Handling**:
23
+ * - First failure stops execution (sets `killed = true`)
24
+ * - Aggregates all errors into `PhaseAggregatedException`
25
+ * - Tracks running units for graceful shutdown
26
+ *
27
+ * **Resume Support**:
28
+ * - Skips completed steps (via `runningStatus.startIndex`)
29
+ * - Skips completed units within steps (via `runningStatus.isCompleted()`)
30
+ *
31
+ * **Validation**:
32
+ * - Constructor validates no duplicate units or phases
33
+ * - Throws `BadImplementationException` on duplicates
34
+ */
4
35
  export class PhaseManager extends Logger {
5
36
  phases;
6
37
  units;
@@ -36,6 +67,26 @@ export class PhaseManager extends Logger {
36
67
  }, {});
37
68
  }
38
69
  //######################### Initialization #########################
70
+ /**
71
+ * Calculates the execution plan: which phases run on which units.
72
+ *
73
+ * **Algorithm**:
74
+ * 1. For each phase group (phases that can run together)
75
+ * 2. Filter phases by runtime params (if phase.filter exists)
76
+ * 3. For each unit layer (dependency level)
77
+ * 4. Find units eligible for at least one phase in the group
78
+ * 5. Group units by which phases they support
79
+ * 6. Create steps: phase combinations × unit groups
80
+ *
81
+ * **Phase Grouping**: Units that support the same set of phases are grouped
82
+ * together in a step (identified by phase keys joined with '|').
83
+ *
84
+ * **Unit Eligibility**:
85
+ * - Unit must implement phase method
86
+ * - Unit must be in active/project units (based on phase.unitCategory)
87
+ *
88
+ * @returns Array of scheduled steps (phases and unit keys)
89
+ */
39
90
  async calculateExecutionSteps() {
40
91
  const steps = [];
41
92
  this.logDebug('Calculating execution steps for phases: ', this.phases.map(phases => phases.map(phase => phase.key)));
@@ -87,6 +138,30 @@ export class PhaseManager extends Logger {
87
138
  this.logVerbose('Calculated execution steps: ', steps);
88
139
  return steps;
89
140
  }
141
+ /**
142
+ * Executes the planned steps sequentially.
143
+ *
144
+ * **Execution Model**:
145
+ * - Steps run sequentially (one after another)
146
+ * - Units within a step run phases in parallel (Promise.all)
147
+ * - Phases for a unit run sequentially (in phase group order)
148
+ *
149
+ * **Resume Support**:
150
+ * - Starts from `runningStatus.startIndex` (if --continue)
151
+ * - Skips units marked as completed
152
+ *
153
+ * **Dry Run**: If `--dry-run`, only logs phase/unit names without executing.
154
+ *
155
+ * **Error Handling**:
156
+ * - First error stops execution (sets `killed = true`)
157
+ * - All errors aggregated into `PhaseAggregatedException`
158
+ * - Running units tracked for graceful shutdown
159
+ *
160
+ * **Performance**: Logs operation duration if > 1.5 seconds.
161
+ *
162
+ * @param _steps - Scheduled steps to execute
163
+ * @throws PhaseAggregatedException if any phase fails
164
+ */
90
165
  async execute(_steps) {
91
166
  this.runningUnits = [];
92
167
  for (let i = this.runningStatus.startIndex; i < _steps.length; i++) {
@@ -143,10 +218,32 @@ export class PhaseManager extends Logger {
143
218
  }
144
219
  this.logInfo('All steps completed.');
145
220
  }
221
+ /**
222
+ * Gracefully stops execution and kills all running units.
223
+ *
224
+ * Called on SIGINT (Ctrl+C). Sets `killed = true` to stop further execution,
225
+ * then calls `kill()` on all currently running units.
226
+ *
227
+ * @returns Promise that resolves when all units are killed
228
+ */
146
229
  break() {
147
230
  this.killed = true;
148
231
  return Promise.all(this.runningUnits.map(unit => unit.kill()));
149
232
  }
233
+ /**
234
+ * Maps scheduled step (with string keys) to execution step (with actual instances).
235
+ *
236
+ * **Mapping Process**:
237
+ * - Maps phase keys to Phase instances using `keyToPhaseMap`
238
+ * - Maps unit keys to BaseUnit instances by searching through unit layers
239
+ *
240
+ * **Performance Note**: Unit lookup iterates through all layers (O(n) complexity).
241
+ * Consider using a lookup map for O(1) access in large workspaces.
242
+ *
243
+ * @param scheduledStep - Scheduled step with phase/unit keys
244
+ * @returns Execution step with phase/unit instances
245
+ * @throws Error if phase or unit not found
246
+ */
150
247
  mapStep(scheduledStep) {
151
248
  const mappedPhases = scheduledStep.phases.map(phaseKey => {
152
249
  const phase = this.keyToPhaseMap[phaseKey];
@@ -1,3 +1,24 @@
1
+ /**
2
+ * Phase definitions for the build system.
3
+ *
4
+ * **Phase Groups**:
5
+ * - `phases_Terminating`: Phases that terminate execution after completion
6
+ * - `phases_Build`: Main build phases (purge, prepare, install, compile, test, etc.)
7
+ * - `phases_Launch`: Launch phases (start applications)
8
+ * - `phases_Deploy`: Deployment phases
9
+ *
10
+ * **Phase Execution Order**:
11
+ * 1. Build phases run first (prepare, install, compile, test)
12
+ * 2. Terminating phases can stop execution early
13
+ * 3. Launch phases start applications
14
+ * 4. Deploy phases publish/deploy
15
+ *
16
+ * **Phase Filters**: Most phases have filters based on runtime params (e.g., `--lint`, `--test`).
17
+ * Phases only run if their filter returns true (or no filter is present).
18
+ *
19
+ * **Dependency Phases**: Some phases depend on others (e.g., `compile` depends on `preCompile`).
20
+ * Dependencies are automatically resolved by PhaseManager.
21
+ */
1
22
  import { Phase } from './types.js';
2
23
  export type Phase_PrintDependencyTree = typeof phase_PrintDependencyTree;
3
24
  export declare const phaseKey_PrintDependencyTree = "print-dependency-tree";
@@ -24,6 +45,12 @@ export declare const phase_Lint: Phase<'lint'>;
24
45
  export type Phase_PreCompile = typeof phase_PreCompile;
25
46
  export declare const phaseKey_PreCompile = "preCompile";
26
47
  export declare const phase_PreCompile: Phase<'preCompile'>;
48
+ export type Phase_ExtractDynamicDeps = typeof phase_ExtractDynamicDeps;
49
+ export declare const phaseKey_ExtractDynamicDeps = "extract-dynamic-deps";
50
+ export declare const phase_ExtractDynamicDeps: Phase<'extractDynamicDeps'>;
51
+ export type Phase_MapExports = typeof phase_MapExports;
52
+ export declare const phaseKey_MapExports = "map-exports";
53
+ export declare const phase_MapExports: Phase<'mapExports'>;
27
54
  export type Phase_Compile = typeof phase_Compile;
28
55
  export declare const phaseKey_Compile = "compile";
29
56
  export declare const phase_Compile: Phase<'compile'>;
@@ -40,6 +67,9 @@ export declare const phases_Build: Phase<string>[][];
40
67
  export type Phase_Launch = typeof phase_Launch;
41
68
  export declare const phaseKey_Launch = "launch";
42
69
  export declare const phase_Launch: Phase<'launch'>;
70
+ export type Phase_IndicesMcpServer = typeof phase_IndicesMcpServer;
71
+ export declare const phaseKey_IndicesMcpServer = "indices-mcp-server";
72
+ export declare const phase_IndicesMcpServer: Phase<'indicesMcpServer'>;
43
73
  export declare const phases_Launch: Phase<string>[][];
44
74
  export type Phase_Publish = typeof phase_Publish;
45
75
  export declare const phaseKey_Publish = "publish";
@@ -50,4 +80,10 @@ export declare const phase_PostPublish: Phase<'postPublish'>;
50
80
  export type Phase_Deploy = typeof phase_Deploy;
51
81
  export declare const phaseKey_Deploy = "deploy";
52
82
  export declare const phase_Deploy: Phase<'deploy'>;
83
+ export type Phase_BuildPushImage = typeof phase_BuildPushImage;
84
+ export declare const phaseKey_BuildPushImage = "build-push-image";
85
+ export declare const phase_BuildPushImage: Phase<'buildPushImage'>;
86
+ export type Phase_DeployImage = typeof phase_DeployImage;
87
+ export declare const phaseKey_DeployImage = "deploy-image";
88
+ export declare const phase_DeployImage: Phase<'deployImage'>;
53
89
  export declare const phases_Deploy: Phase<string>[][];