@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
@@ -1,6 +1,21 @@
1
- import { Unit_NodeProject } from '../../units/index.js';
1
+ import { Unit_NodeProject } from '../../implementations/Unit_NodeProject.js';
2
2
  import { tsValidateValue } from '@nu-art/ts-common';
3
3
  import { UnitMapper_Node } from './UnitMapper_Node.js';
4
+ /**
5
+ * Mapper for discovering root NodeProject unit.
6
+ *
7
+ * **Discovery Criteria**:
8
+ * - Must have `package.json` with `unitConfig.type === 'node-project'`
9
+ * - Typically the monorepo root
10
+ *
11
+ * **Unit Creation**:
12
+ * - Creates `Unit_NodeProject` instance
13
+ * - Marks as root and top-level app
14
+ * - Enables hot reload
15
+ *
16
+ * **Usage**: Automatically registered by `BuildAndInstall.prepareUnitsMapper()`.
17
+ * There should typically be only one NodeProject unit per workspace.
18
+ */
4
19
  export class UnitMapper_NodeProject_Class extends UnitMapper_Node {
5
20
  static tsValidator_NodeProject = {
6
21
  type: tsValidateValue(['node-project']),
@@ -9,6 +24,12 @@ export class UnitMapper_NodeProject_Class extends UnitMapper_Node {
9
24
  constructor() {
10
25
  super(UnitMapper_NodeProject_Class.tsValidator_NodeProject);
11
26
  }
27
+ /**
28
+ * Creates a Unit_NodeProject instance from resolved context.
29
+ *
30
+ * @param context - Resolved node unit context
31
+ * @returns Unit_NodeProject instance
32
+ */
12
33
  async resolveNodeUnit(context) {
13
34
  return new Unit_NodeProject({
14
35
  ...context.baseConfig,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ import { UnitPhaseImplementor } from '../../core/types.js';
2
+ import { StringMap } from '@nu-art/ts-common/utils/types';
3
+ import { Unit_PackageJson, Unit_PackageJson_Config } from './Unit_PackageJson.js';
4
+ import { ProjectUnit } from '../base/ProjectUnit.js';
5
+ import { Phase_Install, Phase_IndicesMcpServer, Phase_PostPublish, Phase_Watch } from '../../phases/definitions/index.js';
6
+ /**
7
+ * Configuration for NodeProject (root project unit).
8
+ */
9
+ type Unit_TypescriptProject_Config = Unit_PackageJson_Config & {
10
+ globalPackages?: StringMap;
11
+ isRoot: true;
12
+ };
13
+ /**
14
+ * Root project unit representing the entire monorepo/workspace.
15
+ *
16
+ * **Key Responsibilities**:
17
+ * - Manages child units (all packages in workspace)
18
+ * - Handles workspace-level operations (install, watch)
19
+ * - Creates PNPM workspace configuration
20
+ * - Manages file watching for hot reload
21
+ *
22
+ * **Phases Implemented**:
23
+ * - `install()`: Installs all packages using PNPM workspace
24
+ * - `watch()`: Watches file changes and triggers incremental compilation
25
+ * - `postPublish()`: Post-publish operations
26
+ *
27
+ * **Watch Mode**:
28
+ * - Watches TypeScript, SCSS, JSON, SVG files in all child units
29
+ * - Uses chokidar for file watching
30
+ * - Debounces changes and compiles affected units in dependency order
31
+ * - Supports hot reload for units with `hasSelfHotReload` flag
32
+ *
33
+ * **Workspace Management**:
34
+ * - Creates `pnpm-workspace.yaml` with all child unit paths
35
+ * - Manages global packages installation
36
+ * - Handles dependency tree for watch compilation
37
+ */
38
+ export declare class Unit_NodeProject<C extends Unit_TypescriptProject_Config = Unit_TypescriptProject_Config> extends Unit_PackageJson<C> implements UnitPhaseImplementor<[Phase_Install, Phase_Watch, Phase_PostPublish, Phase_IndicesMcpServer]> {
39
+ private watcher?;
40
+ readonly innerUnits: Unit_PackageJson[];
41
+ private readonly suffixesToWatch;
42
+ constructor(config: Unit_NodeProject<C>['config']);
43
+ protected deriveDistDependencies(): StringMap;
44
+ assignUnit(units: ProjectUnit[]): void;
45
+ /**
46
+ * Resolve all paths to watch in all project libs
47
+ * @private
48
+ * @returns string[]
49
+ */
50
+ private prepareWatchPaths;
51
+ stopWatch(): Promise<void | undefined>;
52
+ private findUnit;
53
+ install(): Promise<void>;
54
+ watch(timeout?: number, maxTimeout?: number): Promise<void>;
55
+ purge(): Promise<void>;
56
+ postPublish(): Promise<void>;
57
+ indicesMcpServer(): Promise<void>;
58
+ }
59
+ export {};
@@ -6,13 +6,39 @@ import { Commando_PNPM } from '@nu-art/commando/shell/plugins/pnpm';
6
6
  import { PNPM } from '@nu-art/commando/shell/services/pnpm';
7
7
  import { Unit_PackageJson } from './Unit_PackageJson.js';
8
8
  import { resolve } from 'path';
9
- import { PhaseManager } from '../PhaseManager.js';
10
- import { phase_CompileWatch } from '../phase/index.js';
11
- import { UnitsDependencyMapper } from '../UnitsDependencyMapper/UnitsDependencyMapper.js';
9
+ import { PhaseManager } from '../../phases/PhaseManager.js';
10
+ import { phase_CompileWatch } from '../../phases/definitions/index.js';
11
+ import { UnitsDependencyMapper } from '../../dependencies/UnitsDependencyMapper.js';
12
12
  import { CommandoException } from '@nu-art/commando/shell/core/CliError';
13
- import { CONST_PNPM_LOCK, CONST_PNPM_WORKSPACE } from '../../core/consts.js';
14
- import { RunningStatusHandler } from '../RunningStatusHandler.js';
13
+ import { CONST_PNPM_LOCK, CONST_PNPM_WORKSPACE } from '../../config/consts.js';
14
+ import { RunningStatusHandler } from '../../runtime/RunningStatusHandler.js';
15
15
  import { FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
16
+ import { IndicesMcpServer } from '../../exports/IndicesMcpServer.js';
17
+ /**
18
+ * Root project unit representing the entire monorepo/workspace.
19
+ *
20
+ * **Key Responsibilities**:
21
+ * - Manages child units (all packages in workspace)
22
+ * - Handles workspace-level operations (install, watch)
23
+ * - Creates PNPM workspace configuration
24
+ * - Manages file watching for hot reload
25
+ *
26
+ * **Phases Implemented**:
27
+ * - `install()`: Installs all packages using PNPM workspace
28
+ * - `watch()`: Watches file changes and triggers incremental compilation
29
+ * - `postPublish()`: Post-publish operations
30
+ *
31
+ * **Watch Mode**:
32
+ * - Watches TypeScript, SCSS, JSON, SVG files in all child units
33
+ * - Uses chokidar for file watching
34
+ * - Debounces changes and compiles affected units in dependency order
35
+ * - Supports hot reload for units with `hasSelfHotReload` flag
36
+ *
37
+ * **Workspace Management**:
38
+ * - Creates `pnpm-workspace.yaml` with all child unit paths
39
+ * - Manages global packages installation
40
+ * - Handles dependency tree for watch compilation
41
+ */
16
42
  export class Unit_NodeProject extends Unit_PackageJson {
17
43
  watcher;
18
44
  innerUnits = [];
@@ -241,4 +267,38 @@ export class Unit_NodeProject extends Unit_PackageJson {
241
267
  }
242
268
  async postPublish() {
243
269
  }
270
+ async indicesMcpServer() {
271
+ this.setStatus('Starting Export Indices MCP Server', 'start');
272
+ const projectRoot = this.config.fullPath;
273
+ const port = this.runtimeContext.runtimeParams.indicesMcpPort || 3001;
274
+ // Get active TypeScriptLib packages
275
+ const packages = this.innerUnits.filter(unit => unit.isInstanceOf(Unit_TypescriptLib));
276
+ if (packages.length === 0) {
277
+ this.logWarning('No TypeScriptLib packages found. MCP server will have no packages to expose.');
278
+ }
279
+ const server = new IndicesMcpServer(port, projectRoot, packages);
280
+ // Handle graceful shutdown
281
+ const shutdown = async () => {
282
+ this.logInfo('Shutting down Export Indices MCP Server...');
283
+ await server.stop();
284
+ process.exit(0);
285
+ };
286
+ process.on('SIGINT', shutdown);
287
+ process.on('SIGTERM', shutdown);
288
+ try {
289
+ await server.start();
290
+ this.setStatus('Export Indices MCP Server running', 'end');
291
+ this.logInfo(`Export Indices MCP Server is running on http://localhost:${port}`);
292
+ this.logInfo('Press Ctrl+C to stop the server');
293
+ // Keep process alive - return a promise that never resolves
294
+ return new Promise(() => {
295
+ // This promise never resolves, keeping the process alive
296
+ });
297
+ }
298
+ catch (error) {
299
+ this.logError('Failed to start Export Indices MCP Server:', error);
300
+ this.setStatus('Export Indices MCP Server failed', 'end');
301
+ throw error;
302
+ }
303
+ }
244
304
  }
@@ -0,0 +1,56 @@
1
+ import { StringMap } from '@nu-art/ts-common';
2
+ import { UnitPhaseImplementor } from '../../core/types.js';
3
+ import { Config_ProjectUnit, ProjectUnit } from '../base/ProjectUnit.js';
4
+ import { TS_PackageJSON } from '../discovery/types.js';
5
+ import { Phase_Prepare, Phase_Purge } from '../../phases/definitions/index.js';
6
+ /**
7
+ * Configuration for PackageJson units (units with package.json).
8
+ */
9
+ export type Unit_PackageJson_Config = Config_ProjectUnit & {
10
+ packageJson: TS_PackageJSON;
11
+ };
12
+ /**
13
+ * Base class for all units that have a package.json file.
14
+ *
15
+ * **Key Responsibilities**:
16
+ * - Manages package.json template transformation
17
+ * - Handles dependency derivation (lib and dist dependencies)
18
+ * - Implements prepare and purge phases
19
+ *
20
+ * **Dependency Management**:
21
+ * - `deriveLibDependencies()`: Creates workspace dependencies for development
22
+ * - `deriveDistDependencies()`: Creates versioned dependencies for distribution
23
+ *
24
+ * **Template System**: Uses FileSystemUtils to transform package.json templates
25
+ * with runtime parameters (THUNDERSTORM_VERSION, __ENV__, etc.).
26
+ *
27
+ * **Phases Implemented**:
28
+ * - `prepare()`: Generates package.json from template with resolved dependencies
29
+ * - `purge()`: Deletes package.json and node_modules
30
+ *
31
+ * **Base For**: Unit_NodeProject, Unit_TypescriptLib, Unit_FirebaseHosting, etc.
32
+ */
33
+ export declare class Unit_PackageJson<C extends Unit_PackageJson_Config = Unit_PackageJson_Config> extends ProjectUnit<C> implements UnitPhaseImplementor<[Phase_Purge, Phase_Prepare]> {
34
+ constructor(config: C);
35
+ protected npmCommand(command: string): string;
36
+ protected deriveDistDependencies(): StringMap;
37
+ protected deriveLibDependencies(): StringMap;
38
+ /**
39
+ * Prepares package.json by generating it from template with resolved dependencies.
40
+ *
41
+ * **Process**:
42
+ * 1. Derives lib dependencies (workspace:* for development)
43
+ * 2. Transforms package.json template with params
44
+ * 3. Writes transformed package.json to disk
45
+ *
46
+ * **Template Params**: Includes THUNDERSTORM_VERSION, __ENV__, and child unit versions.
47
+ */
48
+ prepare(): Promise<void>;
49
+ /**
50
+ * Purges package.json and node_modules folder.
51
+ *
52
+ * Used by `--purge` flag to clean up before reinstall.
53
+ */
54
+ purge(): Promise<void>;
55
+ protected releasePorts(allPorts: string[]): Promise<void>;
56
+ }
@@ -1,9 +1,30 @@
1
- import { CONST_NodeModules, CONST_PackageJSON } from '../../core/consts.js';
1
+ import { CONST_NodeModules, CONST_PackageJSON } from '../../config/consts.js';
2
2
  import { __stringify } from '@nu-art/ts-common';
3
- import { ProjectUnit } from './ProjectUnit.js';
3
+ import { ProjectUnit } from '../base/ProjectUnit.js';
4
4
  import { resolve } from 'path';
5
5
  import { Commando_NVM } from '@nu-art/commando/shell/plugins/nvm';
6
6
  import { DEFAULT_OLD_TEMPLATE_PATTERN, FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
7
+ /**
8
+ * Base class for all units that have a package.json file.
9
+ *
10
+ * **Key Responsibilities**:
11
+ * - Manages package.json template transformation
12
+ * - Handles dependency derivation (lib and dist dependencies)
13
+ * - Implements prepare and purge phases
14
+ *
15
+ * **Dependency Management**:
16
+ * - `deriveLibDependencies()`: Creates workspace dependencies for development
17
+ * - `deriveDistDependencies()`: Creates versioned dependencies for distribution
18
+ *
19
+ * **Template System**: Uses FileSystemUtils to transform package.json templates
20
+ * with runtime parameters (THUNDERSTORM_VERSION, __ENV__, etc.).
21
+ *
22
+ * **Phases Implemented**:
23
+ * - `prepare()`: Generates package.json from template with resolved dependencies
24
+ * - `purge()`: Deletes package.json and node_modules
25
+ *
26
+ * **Base For**: Unit_NodeProject, Unit_TypescriptLib, Unit_FirebaseHosting, etc.
27
+ */
7
28
  export class Unit_PackageJson extends ProjectUnit {
8
29
  constructor(config) {
9
30
  super(config);
@@ -14,7 +35,7 @@ export class Unit_PackageJson extends ProjectUnit {
14
35
  return resolve(this.runtimeContext.parentUnit.config.fullPath, './node_modules/.bin', command);
15
36
  }
16
37
  deriveDistDependencies() {
17
- const params = this.runtimeContext.childUnits.reduce((dependencies, unit) => {
38
+ const params = this.runtimeContext.parentUnit.innerUnits.reduce((dependencies, unit) => {
18
39
  dependencies[unit.config.key] = unit.config.packageJson.version;
19
40
  return dependencies;
20
41
  }, {
@@ -32,12 +53,27 @@ export class Unit_PackageJson extends ProjectUnit {
32
53
  }, { ...this.runtimeContext.baiConfig.templateParams?.packageJson, __ENV__: this.runtimeContext.runtimeParams.environment });
33
54
  }
34
55
  //######################### Phase Implementations #########################
56
+ /**
57
+ * Prepares package.json by generating it from template with resolved dependencies.
58
+ *
59
+ * **Process**:
60
+ * 1. Derives lib dependencies (workspace:* for development)
61
+ * 2. Transforms package.json template with params
62
+ * 3. Writes transformed package.json to disk
63
+ *
64
+ * **Template Params**: Includes THUNDERSTORM_VERSION, __ENV__, and child unit versions.
65
+ */
35
66
  async prepare() {
36
67
  const targetPath = resolve(this.config.fullPath, CONST_PackageJSON);
37
68
  const params = this.deriveLibDependencies();
38
69
  const packageJson = FileSystemUtils.file.template.transform(__stringify(this.config.packageJson, true), params);
39
70
  await FileSystemUtils.file.template.write(targetPath, packageJson, params, DEFAULT_OLD_TEMPLATE_PATTERN);
40
71
  }
72
+ /**
73
+ * Purges package.json and node_modules folder.
74
+ *
75
+ * Used by `--purge` flag to clean up before reinstall.
76
+ */
41
77
  async purge() {
42
78
  await FileSystemUtils.file.delete(resolve(this.config.fullPath, CONST_PackageJSON));
43
79
  await FileSystemUtils.folder.delete(resolve(this.config.fullPath, CONST_NodeModules));
@@ -1,15 +1,48 @@
1
1
  import { RecursivePartial, TypedMap } from '@nu-art/ts-common';
2
- import { UnitPhaseImplementor } from '../core/types.js';
2
+ import { UnitPhaseImplementor } from '../../core/types.js';
3
3
  import { Unit_PackageJson, Unit_PackageJson_Config } from './Unit_PackageJson.js';
4
- import { Phase_CheckCyclicImports, Phase_Compile, Phase_Lint, Phase_PreCompile, Phase_PrintDependencyTree, Phase_Publish, Phase_Test, Phase_ToESM } from '../phase/index.js';
5
- import { TsConfig } from './types.js';
4
+ import { Phase_CheckCyclicImports, Phase_Compile, Phase_ExtractDynamicDeps, Phase_Lint, Phase_MapExports, Phase_PreCompile, Phase_PrintDependencyTree, Phase_Publish, Phase_Test, Phase_ToESM } from '../../phases/definitions/index.js';
5
+ import { TsConfig } from '../base/types.js';
6
6
  export type Unit_TypescriptLib_Config = Unit_PackageJson_Config & {
7
7
  customESLintConfig: boolean;
8
8
  customTSConfig: boolean;
9
9
  hasSelfHotReload: boolean;
10
10
  output: string;
11
11
  };
12
- export declare class Unit_TypescriptLib<C extends Unit_TypescriptLib_Config = Unit_TypescriptLib_Config> extends Unit_PackageJson<C> implements UnitPhaseImplementor<[Phase_PreCompile, Phase_Compile, Phase_PrintDependencyTree, Phase_CheckCyclicImports, Phase_Lint, Phase_Test, Phase_Publish, Phase_ToESM]> {
12
+ /**
13
+ * TypeScript library unit for building TypeScript packages.
14
+ *
15
+ * **Key Responsibilities**:
16
+ * - Compiles TypeScript to JavaScript
17
+ * - Runs tests (pure, firebase, ui, mobile)
18
+ * - Lints code
19
+ * - Publishes packages
20
+ * - Manages assets (JSON, SCSS, SVG, images)
21
+ * - Handles ESM conversion
22
+ *
23
+ * **Phases Implemented**:
24
+ * - `preCompile()`: Prepares compilation (creates output dir, clears if needed)
25
+ * - `compile()`: Compiles TypeScript using tsc
26
+ * - `watchCompile()`: Incremental compilation for watch mode
27
+ * - `runTests()`: Runs tests based on test type
28
+ * - `lint()`: Lints code using ESLint
29
+ * - `publish()`: Publishes package to registry
30
+ * - `convertToESM()`: Converts package to ESM format
31
+ * - `printDependencyTree()`: Prints dependency tree
32
+ * - `checkCyclicImports()`: Checks for circular imports
33
+ *
34
+ * **Test Types**:
35
+ * - **pure**: Standard TypeScript tests (ts-mocha)
36
+ * - **firebase**: Tests with Firebase emulators
37
+ * - **ui**: UI tests (not implemented)
38
+ * - **mobile**: Mobile tests (not implemented)
39
+ *
40
+ * **Asset Management**: Automatically copies non-TypeScript files (JSON, SCSS, SVG, images)
41
+ * to output directory during compilation.
42
+ *
43
+ * **Dependency Resolution**: Resolves transitive dependencies for compilation order.
44
+ */
45
+ export declare class Unit_TypescriptLib<C extends Unit_TypescriptLib_Config = Unit_TypescriptLib_Config> extends Unit_PackageJson<C> implements UnitPhaseImplementor<[Phase_PreCompile, Phase_Compile, Phase_PrintDependencyTree, Phase_CheckCyclicImports, Phase_Lint, Phase_Test, Phase_Publish, Phase_ToESM, Phase_ExtractDynamicDeps, Phase_MapExports]> {
13
46
  private TestTypeWorkspaceSetup;
14
47
  runTests(): Promise<void>;
15
48
  protected dependencyUnits: Unit_TypescriptLib[];
@@ -32,6 +65,9 @@ export declare class Unit_TypescriptLib<C extends Unit_TypescriptLib_Config = Un
32
65
  */
33
66
  removeSpecificFileFromDist(path: string): Promise<void>;
34
67
  preCompile(): Promise<void>;
68
+ extractDynamicDeps(): Promise<void>;
69
+ private extractPackageName;
70
+ mapExports(): Promise<void>;
35
71
  compile(): Promise<void>;
36
72
  protected postCompile(): Promise<void>;
37
73
  protected copyPackageJSONToOutput(): Promise<void>;
@@ -1,27 +1,30 @@
1
1
  import * as fs from 'fs';
2
2
  import { copyFileSync, existsSync, promises as _fs, readdirSync, statSync } from 'fs';
3
3
  import { __stringify, arrayToMap, BadImplementationException, ImplementationMissingException, LogLevel, merge, NotImplementedYetException } from '@nu-art/ts-common';
4
- import { CONST_BaiConfig, CONST_FirebaseJSON, CONST_FirebaseRC, CONST_PackageJSON, CONST_PackageJSONTemplate, CONST_TS_CONFIG } from '../../core/consts.js';
4
+ import { CONST_BaiConfig, CONST_FirebaseJSON, CONST_FirebaseRC, CONST_PackageJSON, CONST_PackageJSONTemplate, CONST_TS_CONFIG } from '../../config/consts.js';
5
5
  import { CommandoException } from '@nu-art/commando/shell/core/CliError';
6
6
  import { Commando_NVM } from '@nu-art/commando/shell/plugins/nvm';
7
7
  import { Commando_Basic } from '@nu-art/commando/shell/plugins/basic';
8
8
  import { resolve, resolve as pathResolve } from 'path';
9
9
  import { Unit_PackageJson } from './Unit_PackageJson.js';
10
10
  import { glob } from 'node:fs/promises';
11
- import { TestTypes } from '../../core/params/params.js';
11
+ import { TestTypes } from '../../core/params.js';
12
12
  import { DEFAULT_OLD_TEMPLATE_PATTERN, DEFAULT_TEMPLATE_PATTERN, FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
13
13
  import path from 'node:path';
14
- const assetExtensions = [
15
- 'json',
16
- 'scss',
17
- 'svg',
18
- 'png',
19
- 'jpg',
20
- 'jpeg',
21
- 'rules',
22
- '_ts',
23
- 'gif',
24
- 'csv',
14
+ import { ExportMapper } from '../../exports/ExportMapper.js';
15
+ const assets = [
16
+ '*.json',
17
+ '*.scss',
18
+ '*.svg',
19
+ '*.png',
20
+ '*.jpg',
21
+ '*.jpeg',
22
+ '*.rules',
23
+ '*._ts',
24
+ '*.gif',
25
+ '*.csv',
26
+ '*.yaml',
27
+ 'dockerfile',
25
28
  ];
26
29
  const defaultTestPatterns = {
27
30
  pure: '**/*.test.ts',
@@ -33,9 +36,14 @@ const CONST_ESM_PREFIX = 'export NODE_OPTIONS=\'--import data:text/javascript,im
33
36
  const TestsCommandComposer = {
34
37
  pure: async (config, runtimeContext) => {
35
38
  const command = resolve(runtimeContext.parentUnit.config.fullPath, 'node_modules/.bin/ts-mocha');
36
- const testFile = runtimeContext.runtimeParams.testFiles;
37
- const grep = testFile?.length ? ` '${testFile.join('\' \'')}'` : ` '${defaultTestPatterns.pure}'`;
38
- return `${CONST_ESM_PREFIX} && ${command} -p src/test/${CONST_TS_CONFIG} --timeout 0 ${grep}`;
39
+ const files = runtimeContext.runtimeParams.testFiles ?? [`src/test/${defaultTestPatterns.pure}`].map(file => `'${file}'`);
40
+ const testCases = runtimeContext.runtimeParams.testCases;
41
+ const cli_testFiles = ` ${files.join(' ')}`;
42
+ const cli_testCases = testCases ? ` --grep '${testCases.join('|')}'` : '';
43
+ const cli_watchFiles = files.map(file => `-watch-files ${file}`).join(' ');
44
+ const debugPort = runtimeContext.runtimeParams.testDebugPort;
45
+ const cli_debug = debugPort ? ` --inspect=${debugPort} -w ${cli_watchFiles}` : '';
46
+ return `${CONST_ESM_PREFIX} && ${command} -p src/test/${CONST_TS_CONFIG} --timeout 0 ${cli_debug}${cli_testFiles}${cli_testCases}`;
39
47
  },
40
48
  firebase: async (config, runtimeContext) => {
41
49
  const command = resolve(runtimeContext.parentUnit.config.fullPath, 'node_modules/.bin/ts-mocha');
@@ -57,6 +65,39 @@ const TestsCommandComposer = {
57
65
  throw new NotImplementedYetException('Mobile tests not implemented yet');
58
66
  },
59
67
  };
68
+ /**
69
+ * TypeScript library unit for building TypeScript packages.
70
+ *
71
+ * **Key Responsibilities**:
72
+ * - Compiles TypeScript to JavaScript
73
+ * - Runs tests (pure, firebase, ui, mobile)
74
+ * - Lints code
75
+ * - Publishes packages
76
+ * - Manages assets (JSON, SCSS, SVG, images)
77
+ * - Handles ESM conversion
78
+ *
79
+ * **Phases Implemented**:
80
+ * - `preCompile()`: Prepares compilation (creates output dir, clears if needed)
81
+ * - `compile()`: Compiles TypeScript using tsc
82
+ * - `watchCompile()`: Incremental compilation for watch mode
83
+ * - `runTests()`: Runs tests based on test type
84
+ * - `lint()`: Lints code using ESLint
85
+ * - `publish()`: Publishes package to registry
86
+ * - `convertToESM()`: Converts package to ESM format
87
+ * - `printDependencyTree()`: Prints dependency tree
88
+ * - `checkCyclicImports()`: Checks for circular imports
89
+ *
90
+ * **Test Types**:
91
+ * - **pure**: Standard TypeScript tests (ts-mocha)
92
+ * - **firebase**: Tests with Firebase emulators
93
+ * - **ui**: UI tests (not implemented)
94
+ * - **mobile**: Mobile tests (not implemented)
95
+ *
96
+ * **Asset Management**: Automatically copies non-TypeScript files (JSON, SCSS, SVG, images)
97
+ * to output directory during compilation.
98
+ *
99
+ * **Dependency Resolution**: Resolves transitive dependencies for compilation order.
100
+ */
60
101
  export class Unit_TypescriptLib extends Unit_PackageJson {
61
102
  TestTypeWorkspaceSetup = {
62
103
  pure: async (config, runtimeContext) => {
@@ -168,7 +209,7 @@ export class Unit_TypescriptLib extends Unit_PackageJson {
168
209
  });
169
210
  }
170
211
  async copyAssetsToOutput() {
171
- const command = `find . \\( -name ${assetExtensions.map(suffix => `'*.${suffix}'`)
212
+ const command = `find . \\( -name ${assets.map(pattern => `'${pattern}'`)
172
213
  .join(' -o -name ')} \\) | cpio -pdmuv "${this.config.output}" > /dev/null 2>&1`;
173
214
  await this.allocateCommando(Commando_Basic)
174
215
  .cd(`${this.config.fullPath}/src/main`)
@@ -229,6 +270,115 @@ export class Unit_TypescriptLib extends Unit_PackageJson {
229
270
  .append('bash prebuild.sh')
230
271
  .execute();
231
272
  }
273
+ async extractDynamicDeps() {
274
+ this.setStatus('Extracting dynamic dependencies', 'start');
275
+ // Get all workspace package names from parent unit's child units
276
+ const workspacePackageNames = new Set();
277
+ for (const unit of this.runtimeContext.childUnits) {
278
+ workspacePackageNames.add(unit.config.key);
279
+ }
280
+ // Find all TypeScript files in src/main and src/test
281
+ const srcMainTs = `${this.config.fullPath}/src/main/**/*.ts`;
282
+ const srcMainTsx = `${this.config.fullPath}/src/main/**/*.tsx`;
283
+ const allFiles = [];
284
+ for await (const file of glob(srcMainTs, {}))
285
+ allFiles.push(file);
286
+ for await (const file of glob(srcMainTsx, {}))
287
+ allFiles.push(file);
288
+ // Regex patterns for ESM imports
289
+ const importFromRegex = /from\s+["']([^"']+)["']/g;
290
+ const dynamicImportRegex = /import\(["']([^"']+)["']\)/g;
291
+ const workspacePackages = new Set();
292
+ const externalPackages = new Set();
293
+ // Helper function to process import matches
294
+ const processImportMatches = (regex, content) => {
295
+ let match;
296
+ while ((match = regex.exec(content)) !== null) {
297
+ const importPath = match[1];
298
+ const packageName = this.extractPackageName(importPath);
299
+ if (packageName) {
300
+ if (workspacePackageNames.has(packageName)) {
301
+ workspacePackages.add(packageName);
302
+ }
303
+ else {
304
+ externalPackages.add(packageName);
305
+ }
306
+ }
307
+ }
308
+ regex.lastIndex = 0;
309
+ };
310
+ // Process each file
311
+ for (const filePath of allFiles) {
312
+ const content = await FileSystemUtils.file.read(filePath);
313
+ // Extract imports from "import ... from 'package'" and dynamic import('package')
314
+ processImportMatches(importFromRegex, content);
315
+ processImportMatches(dynamicImportRegex, content);
316
+ }
317
+ // Sort and convert to arrays
318
+ const workspaceArray = Array.from(workspacePackages).sort();
319
+ const externalArray = Array.from(externalPackages).sort();
320
+ // Write to _dynamic-deps.json
321
+ const outputPath = pathResolve(this.config.fullPath, '_dynamic-deps.json');
322
+ const output = {
323
+ workspace: workspaceArray,
324
+ external: externalArray
325
+ };
326
+ await FileSystemUtils.file.write(outputPath, __stringify(output, true));
327
+ this.logInfo(`Extracted ${workspaceArray.length} workspace and ${externalArray.length} external dependencies`);
328
+ this.setStatus('Dynamic dependencies extracted', 'end');
329
+ }
330
+ extractPackageName(importPath) {
331
+ // Skip relative imports
332
+ if (importPath.startsWith('.') || importPath.startsWith('/')) {
333
+ return null;
334
+ }
335
+ // Handle scoped packages: @scope/package or @scope/package/path
336
+ if (importPath.startsWith('@')) {
337
+ const parts = importPath.split('/');
338
+ if (parts.length >= 2) {
339
+ return `${parts[0]}/${parts[1]}`;
340
+ }
341
+ return null;
342
+ }
343
+ // Handle unscoped packages: package or package/path
344
+ const firstSlash = importPath.indexOf('/');
345
+ if (firstSlash === -1) {
346
+ return importPath;
347
+ }
348
+ return importPath.substring(0, firstSlash);
349
+ }
350
+ async mapExports() {
351
+ this.setStatus('Mapping exports', 'start');
352
+ // Get project root
353
+ const projectRoot = this.runtimeContext.parentUnit.config.fullPath;
354
+ // Find all TypeScript files in src/main
355
+ const srcMainTs = `${this.config.fullPath}/src/main/**/*.ts`;
356
+ const srcMainTsx = `${this.config.fullPath}/src/main/**/*.tsx`;
357
+ const allFiles = [];
358
+ for await (const file of glob(srcMainTs, {}))
359
+ allFiles.push(file);
360
+ for await (const file of glob(srcMainTsx, {}))
361
+ allFiles.push(file);
362
+ // Load previous errors if they exist (for retry capability)
363
+ const previousErrors = await ExportMapper.loadPreviousErrors(projectRoot, this.config.key);
364
+ // Map exports
365
+ const { exports, errors } = await ExportMapper.mapExports(projectRoot, this.config.fullPath, this.config.key, allFiles, previousErrors || undefined);
366
+ // Write exports to centralized location
367
+ const indexPath = ExportMapper.getIndexPath(projectRoot, this.config.key);
368
+ await FileSystemUtils.folder.create(indexPath);
369
+ const outputPath = pathResolve(indexPath, '_export-for-import.json');
370
+ await FileSystemUtils.file.write(outputPath, __stringify(exports, true));
371
+ // Generate optimized index files
372
+ await ExportMapper.generateIndexFiles(projectRoot, this.config.key, exports);
373
+ // Write errors to centralized location (if any)
374
+ await ExportMapper.writeErrors(projectRoot, this.config.key, errors);
375
+ // Log summary
376
+ this.logInfo(`Mapped ${exports.length} exports`);
377
+ if (errors.length > 0) {
378
+ this.logWarning(`Encountered ${errors.length} errors during export mapping. See ${indexPath}/_export-errors.json for details.`);
379
+ }
380
+ this.setStatus('Exports mapped', 'end');
381
+ }
232
382
  async compile() {
233
383
  if (!this.dependencyUnits)
234
384
  await this.prepare();