@nu-art/build-and-install 0.400.14 → 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 (156) hide show
  1. package/BuildAndInstall.d.ts +40 -0
  2. package/BuildAndInstall.js +155 -0
  3. package/build-and-install-v3.d.ts +1 -32
  4. package/build-and-install-v3.js +1 -154
  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 -334
  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/phases/PhaseManager.js +267 -0
  37. package/{v3/phase → phases/definitions}/consts.d.ts +36 -0
  38. package/{v3/phase → phases/definitions}/consts.js +45 -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 +35 -3
  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 +51 -3
  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 +67 -6
  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/workspace/Workspace.d.ts +95 -0
  89. package/workspace/Workspace.js +192 -0
  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 -26
  100. package/v3/PhaseManager.js +0 -158
  101. package/v3/RunningStatusHandler.d.ts +0 -18
  102. package/v3/RunningStatusHandler.js +0 -67
  103. package/v3/UnitsMapper/UnitsMapper.d.ts +0 -21
  104. package/v3/UnitsMapper/resolvers/UnitMapper_Base.d.ts +0 -23
  105. package/v3/UnitsMapper/resolvers/UnitMapper_Base.js +0 -16
  106. package/v3/UnitsMapper/resolvers/UnitMapper_FirebaseFunction.js +0 -66
  107. package/v3/core/FilesCache.d.ts +0 -7
  108. package/v3/core/FilesCache.js +0 -33
  109. package/v3/phase/types.d.ts +0 -9
  110. package/v3/units/ProjectUnit.d.ts +0 -18
  111. package/v3/units/ProjectUnit.js +0 -11
  112. package/v3/units/Unit_NodeProject.d.ts +0 -30
  113. package/v3/units/Unit_PackageJson.d.ts +0 -17
  114. package/v3/units/firebase/Unit_FirebaseFunctionsApp.d.ts +0 -64
  115. package/v3/units/firebase/Unit_FirebaseFunctionsApp.js +0 -306
  116. package/v3/units/firebase/Unit_FirebaseHostingApp.d.ts +0 -49
  117. package/v3/units/firebase/Unit_FirebaseHostingApp.js +0 -114
  118. package/v3/units/firebase/common.d.ts +0 -3
  119. package/v3/units/firebase/common.js +0 -13
  120. package/v3/units/index.d.ts +0 -6
  121. package/v3/units/index.js +0 -6
  122. /package/{core → config}/package/consts.js +0 -0
  123. /package/{core → config}/types/configs/firebasejson.d.ts +0 -0
  124. /package/{core → config}/types/configs/firebasejson.js +0 -0
  125. /package/{core → config}/types/configs/firebaserc.d.ts +0 -0
  126. /package/{core → config}/types/configs/firebaserc.js +0 -0
  127. /package/{core → config}/types/configs/index.d.ts +0 -0
  128. /package/{core → config}/types/configs/index.js +0 -0
  129. /package/{core → config}/types/configs/package-json.d.ts +0 -0
  130. /package/{core → config}/types/configs/package-json.js +0 -0
  131. /package/{core → config}/types/core.d.ts +0 -0
  132. /package/{core → config}/types/core.js +0 -0
  133. /package/{core → config}/types/index.d.ts +0 -0
  134. /package/{core → config}/types/index.js +0 -0
  135. /package/{core → config}/types/package/index.d.ts +0 -0
  136. /package/{core → config}/types/package/index.js +0 -0
  137. /package/{core → config}/types/package/package.d.ts +0 -0
  138. /package/{core → config}/types/package/package.js +0 -0
  139. /package/{core → config}/types/package/runtime-package.d.ts +0 -0
  140. /package/{core → config}/types/package/runtime-package.js +0 -0
  141. /package/{core → config}/types/project-config.js +0 -0
  142. /package/{v3/core → core}/types.js +0 -0
  143. /package/{v3/UnitsMapper/types.js → exports/types.d.ts} +0 -0
  144. /package/{v3/phase → phases/definitions}/index.d.ts +0 -0
  145. /package/{v3/phase → phases/definitions}/index.js +0 -0
  146. /package/{v3/phase → phases/definitions}/types.js +0 -0
  147. /package/{v3/units/types.js → run.d.ts} +0 -0
  148. /package/{defaults/backend-proxy → templates/backend/proxy}/proxy._ts +0 -0
  149. /package/{defaults/.firebase_config → templates/firebase/config}/database.rules.json +0 -0
  150. /package/{defaults/.firebase_config → templates/firebase/config}/firestore.indexes.json +0 -0
  151. /package/{defaults/.firebase_config → templates/firebase/config}/firestore.rules +0 -0
  152. /package/{defaults/.firebase_config → templates/firebase/config}/storage.rules +0 -0
  153. /package/{v3/units → units/base}/types.d.ts +0 -0
  154. /package/{v3/UnitsMapper → units/discovery}/resolvers/index.d.ts +0 -0
  155. /package/{v3/UnitsMapper → units/discovery}/resolvers/index.js +0 -0
  156. /package/{v3/UnitsMapper → units/discovery}/types.d.ts +0 -0
@@ -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();
@@ -0,0 +1,233 @@
1
+ import { UnitPhaseImplementor } from '../../../core/types.js';
2
+ import { FirebasePackageConfig } from '../../../config/types/index.js';
3
+ import { StringMap } from '@nu-art/ts-common';
4
+ import { Phase_BuildPushImage, Phase_Deploy, Phase_DeployImage, Phase_Launch } from '../../../phases/definitions/index.js';
5
+ import { Unit_TypescriptLib, Unit_TypescriptLib_Config } from '../Unit_TypescriptLib.js';
6
+ export declare const firebaseFunctionEmulator_ErrorStrings: string[];
7
+ export declare const firebaseFunctionEmulator_WarningStrings: string[];
8
+ type EnvConfig = {
9
+ defaultConfig?: string;
10
+ envConfig?: string;
11
+ projectId: string;
12
+ isLocal?: boolean;
13
+ };
14
+ export type FunctionTriggerType = 'http' | 'schedule' | 'eventarc';
15
+ export type FunctionResourceConfig = {
16
+ cpu?: string | number;
17
+ memory?: string;
18
+ timeout?: number;
19
+ concurrency?: number;
20
+ minInstances?: number;
21
+ maxInstances?: number;
22
+ };
23
+ export type FunctionConfig = {
24
+ name: string;
25
+ trigger: FunctionTriggerType;
26
+ schedule?: string;
27
+ serviceAccountName?: string;
28
+ resources?: FunctionResourceConfig;
29
+ };
30
+ export type Unit_FirebaseFunctionsApp_Config = Unit_TypescriptLib_Config & {
31
+ firebaseConfig?: FirebasePackageConfig;
32
+ pathToFirebaseConfig: string;
33
+ envConfig: EnvConfig;
34
+ ignore?: string[];
35
+ debugPort: number;
36
+ basePort: number;
37
+ sslKey: string;
38
+ sslCert: string;
39
+ pathToEmulatorData: string;
40
+ sources?: string[];
41
+ functions: string[] | FunctionConfig[];
42
+ containerDeployment?: {
43
+ artifactRegistry: {
44
+ region: string;
45
+ repository: string;
46
+ projectId: string;
47
+ };
48
+ imageName: string;
49
+ dockerfile?: string;
50
+ };
51
+ };
52
+ /**
53
+ * Firebase Functions application unit.
54
+ *
55
+ * **Key Features**:
56
+ * - Extends Unit_TypescriptLib (compiles TypeScript)
57
+ * - Manages Firebase Functions configuration
58
+ * - Supports emulator with SSL and debug ports
59
+ * - Handles function deployment
60
+ *
61
+ * **Phases Implemented**:
62
+ * - `prepare()`: Sets up Firebase Functions config
63
+ * - `compile()`: Compiles TypeScript for functions
64
+ * - `launch()`: Starts Firebase Functions emulator
65
+ * - `deploy()`: Deploys functions to Firebase
66
+ *
67
+ * **Configuration**:
68
+ * - `debugPort`: Port for Node.js debugger
69
+ * - `basePort`: Base port for emulator
70
+ * - `sslKey`/`sslCert`: SSL certificates for emulator
71
+ * - `pathToEmulatorData`: Path for emulator data persistence
72
+ * - `envConfig`: Environment config (projectId, identityAccount)
73
+ *
74
+ * **Emulator**: Runs Firebase Functions emulator with log filtering and error detection.
75
+ */
76
+ export declare class Unit_FirebaseFunctionsApp<C extends Unit_FirebaseFunctionsApp_Config = Unit_FirebaseFunctionsApp_Config> extends Unit_TypescriptLib<C> implements UnitPhaseImplementor<[Phase_Launch, Phase_Deploy, Phase_BuildPushImage, Phase_DeployImage]> {
77
+ functions: StringMap;
78
+ injectedMetadata: StringMap;
79
+ static staggerCount: number;
80
+ static DefaultConfig_FirebaseFunction: {
81
+ pathToFirebaseConfig: string;
82
+ debugPort: number;
83
+ basePort: number;
84
+ sslKey: string;
85
+ sslCert: string;
86
+ output: string;
87
+ pathToEmulatorData: string;
88
+ };
89
+ readonly emulatorLogStrings: {
90
+ error: string[];
91
+ warning: string[];
92
+ };
93
+ constructor(config: Unit_FirebaseFunctionsApp<C>['config']);
94
+ protected copyPackageJSONToOutput(): Promise<void>;
95
+ prepare(): Promise<void>;
96
+ resolveConfigs(): Promise<void>;
97
+ compile(): Promise<void>;
98
+ postCompile(): Promise<void>;
99
+ launch(): Promise<void>;
100
+ releaseEmulatorPorts(): Promise<void>;
101
+ deploy(): Promise<void>;
102
+ /**
103
+ * Builds Docker container image using Google Cloud Build and pushes it to Artifact Registry.
104
+ *
105
+ * **Process**:
106
+ * 1. Validates image tag is provided via CLI
107
+ * 2. Validates containerDeployment config exists
108
+ * 3. Constructs Artifact Registry image reference
109
+ * 4. Creates isolated staging directory with only required files (dist/, Dockerfile, .cloudbuild.yaml)
110
+ * 5. Builds and pushes image using Google Cloud Build from staging directory (no local Docker required)
111
+ *
112
+ * **Staging Directory Structure**:
113
+ * - `dist/` - Contains compiled code and package.json (copied from output)
114
+ * - `Dockerfile` - Container build instructions
115
+ * - `.cloudbuild.yaml` - Cloud Build configuration
116
+ *
117
+ * **Requirements**:
118
+ * - `--build-push-image <tag>` CLI flag with tag value
119
+ * - `containerDeployment` config in unit config
120
+ * - gcloud CLI installed and authenticated
121
+ * - Cloud Build API enabled in GCP project
122
+ * - No local Docker daemon required - Cloud Build handles everything
123
+ */
124
+ buildPushImage(): Promise<void>;
125
+ /**
126
+ * Discovers exported functions from the compiled dist/index.js file.
127
+ * Parses export statements to extract function names.
128
+ *
129
+ * @returns Array of function names found in exports
130
+ */
131
+ private discoverExportedFunctions;
132
+ /**
133
+ * Normalizes function configuration to FunctionConfig[] format.
134
+ * Handles both legacy format (string[]) and new format (FunctionConfig[]).
135
+ */
136
+ private normalizeFunctionConfigs;
137
+ /**
138
+ * Gets function names from configuration (for backward compatibility).
139
+ */
140
+ private getFunctionNames;
141
+ /**
142
+ * Gets function config by name.
143
+ */
144
+ private getFunctionConfig;
145
+ /**
146
+ * Validates that all configured functions exist in the compiled dist/index.js file.
147
+ * Throws ImplementationMissingException if any configured function is missing.
148
+ */
149
+ private validateFunctionsExist;
150
+ /**
151
+ * Deletes a single function using gcloud run services delete.
152
+ *
153
+ * @param functionName Name of the function to delete (original function name with underscores)
154
+ */
155
+ private deleteFunction;
156
+ /**
157
+ * Deletes multiple functions.
158
+ * Determines which functions to delete based on CLI parameters.
159
+ *
160
+ * @returns Array of function names that were deleted (or would be deleted in dry run)
161
+ */
162
+ private deleteFunctions;
163
+ /**
164
+ * Deploys container image from Artifact Registry to Firebase Functions using gcloud.
165
+ *
166
+ * **Process**:
167
+ * 1. Validates image tag is provided via CLI
168
+ * 2. Validates containerDeployment config exists
169
+ * 3. Validates configured functions exist in dist/index.js
170
+ * 4. Deletes functions if requested via CLI flags
171
+ * 5. Determines which functions to deploy (single or all)
172
+ * 6. Generates Cloud Run service YAML definitions for each function
173
+ * 7. Sets required environment variables (FIREBASE_CONFIG, GCLOUD_PROJECT, FUNCTION_TARGET, etc.)
174
+ * 8. Deploys each function using `gcloud run services replace` with YAML definition
175
+ * 9. Retrieves function URLs after successful deployment
176
+ *
177
+ * **Environment Variables Set**:
178
+ * - `FUNCTION_TARGET`: Function name to invoke
179
+ * - `GCLOUD_PROJECT`: Runtime project ID
180
+ * - `GOOGLE_CLOUD_PROJECT`: Runtime project ID (alternative)
181
+ * - `FIREBASE_CONFIG`: JSON string with projectId, databaseURL, storageBucket, locationId
182
+ * - `EVENTARC_CLOUD_EVENT_SOURCE`: Eventarc source path
183
+ * - `LOG_EXECUTION_ID`: Set to 'true' for execution ID logging
184
+ *
185
+ * **Function Configuration**:
186
+ * Functions can be configured in two formats:
187
+ * 1. **Legacy format** (string[]): Simple array of function names (all default to HTTP trigger)
188
+ * 2. **New format** (FunctionConfig[]): Array of function config objects with:
189
+ * - `name`: Function name (must match exported function name)
190
+ * - `trigger`: Trigger type ('http', 'schedule', or 'eventarc')
191
+ * - `schedule`: Schedule expression (required for 'schedule' trigger, e.g., 'every 24 hours', '0 2 * * *')
192
+ * - `resources`: Per-function resource configuration:
193
+ * - `cpu`: CPU allocation (e.g., '1', '2', '4')
194
+ * - `memory`: Memory allocation (e.g., '512Mi', '1Gi', '2Gi', '4Gi', '8Gi')
195
+ * - `timeout`: Timeout in seconds (default: 300, max: 3600)
196
+ * - `concurrency`: Container concurrency (default: 80, max: 1000)
197
+ * - `minInstances`: Minimum number of instances (default: 0)
198
+ * - `maxInstances`: Maximum number of instances (default: 100)
199
+ *
200
+ * **Trigger Types**:
201
+ * - `http`: HTTP-triggered function (deployed as Cloud Run service)
202
+ * - `schedule`: Scheduled function (requires `schedule` property, deployed as Cloud Run service with Cloud Scheduler)
203
+ * - `eventarc`: Event-triggered function (deployed as Cloud Run service with Eventarc)
204
+ *
205
+ * **Requirements**:
206
+ * - `--deploy-image <tag>` CLI flag with tag value
207
+ * - `containerDeployment` config in unit config
208
+ * - `functions` array in unit config (legacy or new format)
209
+ * - Image must already exist in Artifact Registry (built via buildPushImage)
210
+ * - gcloud CLI installed and authenticated
211
+ * - Cloud Functions API enabled in GCP project
212
+ * - Cloud Scheduler API enabled (for scheduled functions)
213
+ *
214
+ * **Note on Request Size Limits**:
215
+ * The `PayloadTooLargeError` is typically caused by Express body-parser limits, not Cloud Run limits.
216
+ * Configure `bodyParserLimit` in your HttpServer module config to increase the limit (default: 200kb).
217
+ * Cloud Run supports request bodies up to 32MB, but Express must be configured to accept them.
218
+ */
219
+ deployImage(): Promise<void>;
220
+ private getEnvConfig;
221
+ private resolveFunctionsRC;
222
+ private resolveProxyFile;
223
+ private pathToProxy;
224
+ private resolveConfigDir;
225
+ private resolveFunctionsJSON;
226
+ private resolveFunctionsRuntimeConfig;
227
+ private createAppVersionFile;
228
+ protected deriveDistDependencies(): StringMap;
229
+ private createDependenciesDir;
230
+ private runProxy;
231
+ private runEmulator;
232
+ }
233
+ export {};