@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.
- package/BuildAndInstall.d.ts +40 -0
- package/BuildAndInstall.js +155 -0
- package/build-and-install-v3.d.ts +1 -44
- package/build-and-install-v3.js +1 -157
- package/build-and-install.js +11 -11
- package/config/consts.d.ts +43 -0
- package/config/consts.js +42 -0
- package/{core → config}/package/consts.d.ts +1 -1
- package/{core → config}/types/project-config.d.ts +3 -0
- package/core/FilesCache.d.ts +50 -0
- package/core/FilesCache.js +76 -0
- package/core/Unit_HelpPrinter.d.ts +16 -0
- package/core/Unit_HelpPrinter.js +47 -0
- package/core/params/params.d.ts +1 -41
- package/core/params/params.js +1 -332
- package/core/params.d.ts +50 -0
- package/core/params.js +441 -0
- package/{v3/core → core}/types.d.ts +1 -1
- package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.d.ts +21 -1
- package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.js +26 -3
- package/dependencies/types.d.ts +1 -0
- package/dependencies/types.js +1 -0
- package/exceptions/PhaseAggregatedException.d.ts +34 -0
- package/{core/exceptions → exceptions}/PhaseAggregatedException.js +26 -0
- package/exceptions/UnitPhaseException.d.ts +20 -0
- package/exceptions/UnitPhaseException.js +21 -0
- package/exports/ExportIndexCache.d.ts +25 -0
- package/exports/ExportIndexCache.js +115 -0
- package/exports/ExportMapper.d.ts +43 -0
- package/exports/ExportMapper.js +519 -0
- package/exports/IndicesMcpServer.d.ts +22 -0
- package/exports/IndicesMcpServer.js +220 -0
- package/exports/types.js +3 -0
- package/package.json +20 -9
- package/phases/PhaseManager.d.ts +130 -0
- package/{v3 → phases}/PhaseManager.js +99 -2
- package/{v3/phase → phases/definitions}/consts.d.ts +36 -0
- package/{v3/phase → phases/definitions}/consts.js +44 -2
- package/phases/definitions/types.d.ts +40 -0
- package/phases/index.d.ts +2 -0
- package/phases/index.js +2 -0
- package/run.js +10 -0
- package/runtime/RunningStatusHandler.d.ts +104 -0
- package/runtime/RunningStatusHandler.js +153 -0
- package/runtime/types.d.ts +1 -0
- package/runtime/types.js +2 -0
- package/{defaults → templates}/consts.d.ts +9 -0
- package/{defaults → templates}/consts.js +12 -2
- package/templates/firebase/functions/cloudbuild.yaml +17 -0
- package/templates/firebase/functions/dockerfile +19 -0
- package/templates/firebase/functions/service.yaml +49 -0
- package/{v3/units → units/base}/BaseUnit.d.ts +34 -4
- package/{v3/units → units/base}/BaseUnit.js +22 -2
- package/units/base/ProjectUnit.d.ts +32 -0
- package/units/base/ProjectUnit.js +25 -0
- package/units/base/types.js +1 -0
- package/units/discovery/UnitsMapper.d.ts +69 -0
- package/{v3/UnitsMapper → units/discovery}/UnitsMapper.js +50 -2
- package/units/discovery/resolvers/UnitMapper_Base.d.ts +65 -0
- package/units/discovery/resolvers/UnitMapper_Base.js +46 -0
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseFunction.d.ts +5 -3
- package/units/discovery/resolvers/UnitMapper_FirebaseFunction.js +105 -0
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.d.ts +3 -2
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.js +14 -10
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.d.ts +1 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.js +2 -2
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.d.ts +24 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.js +24 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.d.ts +22 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.js +22 -1
- package/units/discovery/types.js +1 -0
- package/units/implementations/Unit_NodeProject.d.ts +59 -0
- package/{v3/units → units/implementations}/Unit_NodeProject.js +65 -5
- package/units/implementations/Unit_PackageJson.d.ts +56 -0
- package/{v3/units → units/implementations}/Unit_PackageJson.js +39 -3
- package/{v3/units → units/implementations}/Unit_TypescriptLib.d.ts +40 -4
- package/{v3/units → units/implementations}/Unit_TypescriptLib.js +167 -17
- package/units/implementations/firebase/Unit_FirebaseFunctionsApp.d.ts +233 -0
- package/units/implementations/firebase/Unit_FirebaseFunctionsApp.js +804 -0
- package/units/implementations/firebase/Unit_FirebaseHostingApp.d.ts +113 -0
- package/units/implementations/firebase/Unit_FirebaseHostingApp.js +320 -0
- package/units/implementations/firebase/common.d.ts +26 -0
- package/units/implementations/firebase/common.js +65 -0
- package/units/index.d.ts +6 -0
- package/units/index.js +6 -0
- package/v3/core/Unit_HelpPrinter.d.ts +1 -16
- package/v3/core/Unit_HelpPrinter.js +1 -47
- package/{v3 → workspace}/Workspace.d.ts +30 -15
- package/{v3 → workspace}/Workspace.js +48 -35
- package/core/consts.d.ts +0 -13
- package/core/consts.js +0 -12
- package/core/exceptions/PhaseAggregatedException.d.ts +0 -8
- package/core/exceptions/UnitPhaseException.d.ts +0 -5
- package/core/exceptions/UnitPhaseException.js +0 -6
- package/old/PhaseRunnerDispatcher.d.ts +0 -24
- package/old/PhaseRunnerDispatcher.js +0 -32
- package/old/runner-dispatchers.d.ts +0 -10
- package/old/runner-dispatchers.js +0 -3
- package/v3/PhaseManager.d.ts +0 -27
- package/v3/RunningStatusHandler.d.ts +0 -18
- package/v3/RunningStatusHandler.js +0 -67
- package/v3/UnitsMapper/UnitsMapper.d.ts +0 -21
- package/v3/UnitsMapper/resolvers/UnitMapper_Base.d.ts +0 -23
- package/v3/UnitsMapper/resolvers/UnitMapper_Base.js +0 -16
- package/v3/UnitsMapper/resolvers/UnitMapper_FirebaseFunction.js +0 -66
- package/v3/core/FilesCache.d.ts +0 -7
- package/v3/core/FilesCache.js +0 -33
- package/v3/phase/types.d.ts +0 -10
- package/v3/units/ProjectUnit.d.ts +0 -18
- package/v3/units/ProjectUnit.js +0 -11
- package/v3/units/Unit_NodeProject.d.ts +0 -30
- package/v3/units/Unit_PackageJson.d.ts +0 -17
- package/v3/units/firebase/Unit_FirebaseFunctionsApp.d.ts +0 -64
- package/v3/units/firebase/Unit_FirebaseFunctionsApp.js +0 -306
- package/v3/units/firebase/Unit_FirebaseHostingApp.d.ts +0 -49
- package/v3/units/firebase/Unit_FirebaseHostingApp.js +0 -118
- package/v3/units/firebase/common.d.ts +0 -3
- package/v3/units/firebase/common.js +0 -13
- package/v3/units/index.d.ts +0 -6
- package/v3/units/index.js +0 -6
- /package/{core → config}/package/consts.js +0 -0
- /package/{core → config}/types/configs/firebasejson.d.ts +0 -0
- /package/{core → config}/types/configs/firebasejson.js +0 -0
- /package/{core → config}/types/configs/firebaserc.d.ts +0 -0
- /package/{core → config}/types/configs/firebaserc.js +0 -0
- /package/{core → config}/types/configs/index.d.ts +0 -0
- /package/{core → config}/types/configs/index.js +0 -0
- /package/{core → config}/types/configs/package-json.d.ts +0 -0
- /package/{core → config}/types/configs/package-json.js +0 -0
- /package/{core → config}/types/core.d.ts +0 -0
- /package/{core → config}/types/core.js +0 -0
- /package/{core → config}/types/index.d.ts +0 -0
- /package/{core → config}/types/index.js +0 -0
- /package/{core → config}/types/package/index.d.ts +0 -0
- /package/{core → config}/types/package/index.js +0 -0
- /package/{core → config}/types/package/package.d.ts +0 -0
- /package/{core → config}/types/package/package.js +0 -0
- /package/{core → config}/types/package/runtime-package.d.ts +0 -0
- /package/{core → config}/types/package/runtime-package.js +0 -0
- /package/{core → config}/types/project-config.js +0 -0
- /package/{v3/core → core}/types.js +0 -0
- /package/{v3/UnitsMapper/types.js → exports/types.d.ts} +0 -0
- /package/{v3/phase → phases/definitions}/index.d.ts +0 -0
- /package/{v3/phase → phases/definitions}/index.js +0 -0
- /package/{v3/phase → phases/definitions}/types.js +0 -0
- /package/{v3/units/types.js → run.d.ts} +0 -0
- /package/{defaults/backend-proxy → templates/backend/proxy}/proxy._ts +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/database.rules.json +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/firestore.indexes.json +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/firestore.rules +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/storage.rules +0 -0
- /package/{v3/units → units/base}/types.d.ts +0 -0
- /package/{v3/UnitsMapper → units/discovery}/resolvers/index.d.ts +0 -0
- /package/{v3/UnitsMapper → units/discovery}/resolvers/index.js +0 -0
- /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
|
+
}
|
package/exports/types.js
ADDED
package/package.json
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nu-art/build-and-install",
|
|
3
|
-
"version": "0.401.
|
|
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
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"typescript",
|
|
8
|
+
"build-system",
|
|
9
|
+
"monorepo",
|
|
10
|
+
"dependency-management",
|
|
11
|
+
"phase-execution",
|
|
12
|
+
"workspace",
|
|
13
|
+
"units",
|
|
14
|
+
"automation",
|
|
9
15
|
"nu-art",
|
|
10
|
-
"
|
|
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.
|
|
35
|
-
"@nu-art/commando": "0.401.
|
|
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 '../
|
|
3
|
-
import { UnitPhaseException } from '../
|
|
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>[][];
|