@nu-art/build-and-install 0.401.9 → 0.500.6

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 (67) hide show
  1. package/BuildAndInstall.d.ts +2 -2
  2. package/BuildAndInstall.js +10 -2
  3. package/config/consts.d.ts +2 -2
  4. package/config/consts.js +1 -1
  5. package/config/package/consts.d.ts +1 -1
  6. package/config/types/package/runtime-package.d.ts +1 -1
  7. package/config/types/project-config.d.ts +17 -2
  8. package/core/FilesCache.d.ts +5 -1
  9. package/core/FilesCache.js +5 -1
  10. package/core/Unit_HelpPrinter.d.ts +4 -7
  11. package/core/Unit_HelpPrinter.js +3 -11
  12. package/core/params.d.ts +2 -1
  13. package/core/params.js +12 -3
  14. package/core/types.d.ts +2 -2
  15. package/dependencies/UnitsDependencyMapper.d.ts +8 -0
  16. package/dependencies/UnitsDependencyMapper.js +58 -4
  17. package/exceptions/UnitPhaseException.d.ts +1 -1
  18. package/exports/IndicesMcpServer.js +1 -1
  19. package/package.json +5 -5
  20. package/phases/PhaseManager.d.ts +2 -2
  21. package/phases/PhaseManager.js +4 -4
  22. package/phases/definitions/consts.d.ts +3 -0
  23. package/phases/definitions/consts.js +7 -0
  24. package/phases/definitions/types.d.ts +1 -1
  25. package/templates/backend/proxy/proxy._ts +36 -31
  26. package/templates/firebase/config/database.rules.json +6 -0
  27. package/units/base/BaseUnit.d.ts +1 -1
  28. package/units/discovery/UnitsMapper.d.ts +3 -2
  29. package/units/discovery/resolvers/UnitMapper_Base.d.ts +2 -2
  30. package/units/discovery/resolvers/UnitMapper_FirebaseFunction.d.ts +12 -1
  31. package/units/discovery/resolvers/UnitMapper_FirebaseFunction.js +48 -18
  32. package/units/discovery/resolvers/UnitMapper_FirebaseHosting.d.ts +5 -9
  33. package/units/discovery/resolvers/UnitMapper_FirebaseHosting.js +3 -1
  34. package/units/discovery/resolvers/UnitMapper_Node.d.ts +1 -1
  35. package/units/discovery/resolvers/UnitMapper_Node.js +8 -15
  36. package/units/discovery/resolvers/UnitMapper_ViteHosting.d.ts +46 -0
  37. package/units/discovery/resolvers/UnitMapper_ViteHosting.js +59 -0
  38. package/units/implementations/Unit_NodeProject.d.ts +3 -2
  39. package/units/implementations/Unit_NodeProject.js +30 -6
  40. package/units/implementations/Unit_PackageJson.d.ts +8 -2
  41. package/units/implementations/Unit_PackageJson.js +46 -11
  42. package/units/implementations/Unit_TypescriptLib.d.ts +8 -2
  43. package/units/implementations/Unit_TypescriptLib.js +155 -4
  44. package/units/implementations/firebase/Unit_FirebaseFunctionsApp.d.ts +12 -2
  45. package/units/implementations/firebase/Unit_FirebaseFunctionsApp.js +73 -17
  46. package/units/implementations/firebase/Unit_FirebaseHostingApp.d.ts +19 -97
  47. package/units/implementations/firebase/Unit_FirebaseHostingApp.js +28 -290
  48. package/units/implementations/firebase/Unit_HostingApp.d.ts +59 -0
  49. package/units/implementations/firebase/Unit_HostingApp.js +225 -0
  50. package/units/implementations/firebase/Unit_ViteHostingApp.d.ts +10 -0
  51. package/units/implementations/firebase/Unit_ViteHostingApp.js +28 -0
  52. package/workspace/Workspace.d.ts +3 -1
  53. package/workspace/Workspace.js +2 -1
  54. package/config/types/configs/index.d.ts +0 -3
  55. package/config/types/configs/index.js +0 -3
  56. package/config/types/index.d.ts +0 -4
  57. package/config/types/index.js +0 -4
  58. package/config/types/package/index.d.ts +0 -2
  59. package/config/types/package/index.js +0 -2
  60. package/phases/definitions/index.d.ts +0 -2
  61. package/phases/definitions/index.js +0 -2
  62. package/phases/index.d.ts +0 -2
  63. package/phases/index.js +0 -2
  64. package/units/discovery/resolvers/index.d.ts +0 -4
  65. package/units/discovery/resolvers/index.js +0 -4
  66. package/units/index.d.ts +0 -6
  67. package/units/index.js +0 -6
@@ -1,10 +1,10 @@
1
1
  import { Logger } from '@nu-art/ts-common';
2
2
  import { BaiParams } from './core/params.js';
3
- import { Phase } from './phases/definitions/index.js';
3
+ import type { Phase } from './phases/definitions/types.js';
4
4
  import { UnitsMapper } from './units/discovery/UnitsMapper.js';
5
5
  import { ProjectUnit } from './units/base/ProjectUnit.js';
6
6
  import { PhaseManager } from './phases/PhaseManager.js';
7
- import { Unit_NodeProject } from './units/index.js';
7
+ import { Unit_NodeProject } from './units/implementations/Unit_NodeProject.js';
8
8
  import { Workspace } from './workspace/Workspace.js';
9
9
  import { BaseCliParam } from '@nu-art/cli-params';
10
10
  import { RunningStatusHandler } from './runtime/RunningStatusHandler.js';
@@ -1,6 +1,7 @@
1
1
  import { BeLogged, DebugFlag, filterDuplicates, ImplementationMissingException, LogClient_Terminal, Logger, LogLevel, merge } from '@nu-art/ts-common';
2
2
  import { AllBaiParams } from './core/params.js';
3
- import { phases_Build, phases_Deploy, phases_Launch, phases_Terminating } from './phases/definitions/index.js';
3
+ import { phase_Help, Unit_HelpPrinter } from './core/Unit_HelpPrinter.js';
4
+ import { phases_Build, phases_Deploy, phases_Launch, phases_Terminating } from './phases/definitions/consts.js';
4
5
  import { UnitsMapper } from './units/discovery/UnitsMapper.js';
5
6
  import { FilesCache } from './core/FilesCache.js';
6
7
  import { ProjectUnit } from './units/base/ProjectUnit.js';
@@ -8,11 +9,16 @@ import { PhaseManager } from './phases/PhaseManager.js';
8
9
  import { Workspace } from './workspace/Workspace.js';
9
10
  import { resolve } from 'path';
10
11
  import { CONST_BaiConfig, CONST_NodeModules, CONST_VersionApp } from './config/consts.js';
11
- import { UnitMapper_FirebaseFunction, UnitMapper_FirebaseHosting, UnitMapper_NodeLib, UnitMapper_NodeProject } from './units/discovery/resolvers/index.js';
12
+ import { UnitMapper_FirebaseFunction } from './units/discovery/resolvers/UnitMapper_FirebaseFunction.js';
13
+ import { UnitMapper_FirebaseHosting } from './units/discovery/resolvers/UnitMapper_FirebaseHosting.js';
14
+ import { UnitMapper_NodeLib } from './units/discovery/resolvers/UnitMapper_NodeLib.js';
15
+ import { UnitMapper_NodeProject } from './units/discovery/resolvers/UnitMapper_NodeProject.js';
16
+ import { UnitMapper_ViteHosting } from './units/discovery/resolvers/UnitMapper_ViteHosting.js';
12
17
  import { CLIParamsResolver } from '@nu-art/cli-params';
13
18
  import { RunningStatusHandler } from './runtime/RunningStatusHandler.js';
14
19
  import { FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
15
20
  export const DefaultPhases = [
21
+ [phase_Help],
16
22
  ...phases_Build,
17
23
  ...phases_Terminating,
18
24
  ...phases_Launch,
@@ -60,6 +66,7 @@ export class BuildAndInstall extends Logger {
60
66
  .addRules(UnitMapper_NodeLib)
61
67
  .addRules(UnitMapper_NodeProject)
62
68
  .addRules(UnitMapper_FirebaseHosting)
69
+ .addRules(UnitMapper_ViteHosting)
63
70
  .addRules(UnitMapper_FirebaseFunction)
64
71
  .setRuntimeParams(this.runtimeParams);
65
72
  }
@@ -99,6 +106,7 @@ export class BuildAndInstall extends Logger {
99
106
  }
100
107
  async build() {
101
108
  await this.init();
109
+ this.workspace.addProjectUnits([Unit_HelpPrinter]);
102
110
  // Scan units from workspace
103
111
  await this.workspace.scanUnits(this.pathToProject, this.unitsMapper);
104
112
  const nodeProjectUnit = this.workspace.getNodeProjectUnit();
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Constants for file names and configuration keys used throughout the build system.
3
3
  */
4
- import { MemKey } from '@nu-art/ts-common/mem-storage/index';
5
- import { RuntimeProjectConfig } from './types/index.js';
4
+ import { MemKey } from '@nu-art/ts-common/mem-storage';
5
+ import { RuntimeProjectConfig } from './types/project-config.js';
6
6
  /** Version file name (version-app.json) */
7
7
  export declare const CONST_VersionApp = "version-app.json";
8
8
  /** Package.json template file name (__package.json) */
package/config/consts.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Constants for file names and configuration keys used throughout the build system.
3
3
  */
4
- import { MemKey } from '@nu-art/ts-common/mem-storage/index';
4
+ import { MemKey } from '@nu-art/ts-common/mem-storage';
5
5
  /** Version file name (version-app.json) */
6
6
  export const CONST_VersionApp = 'version-app.json';
7
7
  /** Package.json template file name (__package.json) */
@@ -1,4 +1,4 @@
1
- import { FirebasePackageConfig } from '../types/index.js';
1
+ import { FirebasePackageConfig } from '../types/package/package.js';
2
2
  export type DefaultType_ProjectEnvs = 'local' | 'dev' | 'staging' | 'prod';
3
3
  export declare const Default_ProjectEnvs: ("local" | "staging" | "dev" | "prod")[];
4
4
  export declare const Default_FunctionsIgnoreFiles: string[];
@@ -1,4 +1,4 @@
1
- import { PackageJson } from '../configs/index.js';
1
+ import { PackageJson } from '../configs/package-json.js';
2
2
  import { Package, Package_Sourceless } from './package.js';
3
3
  type WithPackageJson = {
4
4
  packageJsonTemplate: PackageJson;
@@ -1,5 +1,6 @@
1
1
  import { StringMap, TypedMap } from '@nu-art/ts-common';
2
- import { Package, RuntimePackage } from './package/index.js';
2
+ import type { Package } from './package/package.js';
3
+ import type { RuntimePackage } from './package/runtime-package.js';
3
4
  export type ProjectConfig = {
4
5
  params: StringMap;
5
6
  packages: Package[];
@@ -28,6 +29,20 @@ export type BAI_Config = {
28
29
  'firebase.json'?: string;
29
30
  '.firebaserc'?: string;
30
31
  baseEmulationPort?: number;
32
+ mongoPort?: number;
33
+ };
34
+ playwright?: {
35
+ browsers?: ('chromium' | 'firefox' | 'webkit')[];
36
+ headless?: boolean;
37
+ baseURL?: string;
38
+ viewport?: {
39
+ width: number;
40
+ height: number;
41
+ };
42
+ vite?: {
43
+ port?: number;
44
+ configPath?: string;
45
+ };
31
46
  };
32
47
  };
33
48
  firebase?: {
@@ -41,7 +56,7 @@ export type BAI_Config = {
41
56
  eslintConfig?: string;
42
57
  };
43
58
  backend: {
44
- proxy: string;
59
+ proxy: string | null;
45
60
  };
46
61
  };
47
62
  };
@@ -16,11 +16,15 @@
16
16
  */
17
17
  export declare const FilesCache: {
18
18
  /**
19
- * Clears the file cache.
19
+ * Clears the entire file cache.
20
20
  *
21
21
  * Useful for tests or when files may have changed.
22
22
  */
23
23
  clear: () => {};
24
+ /**
25
+ * Invalidates a single cached entry so the next load re-reads from disk.
26
+ */
27
+ invalidate: (path: string) => void;
24
28
  load: {
25
29
  /**
26
30
  * Loads and caches a JSON file.
@@ -32,11 +32,15 @@ const readFile = async (path) => {
32
32
  */
33
33
  export const FilesCache = {
34
34
  /**
35
- * Clears the file cache.
35
+ * Clears the entire file cache.
36
36
  *
37
37
  * Useful for tests or when files may have changed.
38
38
  */
39
39
  clear: () => cachedFiles = {},
40
+ /**
41
+ * Invalidates a single cached entry so the next load re-reads from disk.
42
+ */
43
+ invalidate: (path) => { delete cachedFiles[path]; },
40
44
  load: {
41
45
  /**
42
46
  * Loads and caches a JSON file.
@@ -1,10 +1,8 @@
1
- import { BaseCliParam, CliParams } from '@nu-art/cli-params';
1
+ import { BaiParam_Help } from './params.js';
2
2
  import { UnitPhaseImplementor } from './types.js';
3
- import { Phase } from '../phases/definitions/index.js';
4
- import { ProjectUnit } from '../units/index.js';
5
- export declare const BaiParam_Help: BaseCliParam<'help', boolean>;
6
- declare const AllBaiParams_Help: (BaseCliParam<"allUnits", boolean> | BaseCliParam<"dependencyTree", boolean> | BaseCliParam<"environment", string> | BaseCliParam<"install", boolean> | BaseCliParam<"clean", boolean> | BaseCliParam<"purge", boolean> | BaseCliParam<"generate", boolean> | BaseCliParam<"generateDocs", boolean> | BaseCliParam<"noBuild", boolean> | BaseCliParam<"prepare", boolean> | BaseCliParam<"dryRun", boolean> | BaseCliParam<"lint", boolean> | BaseCliParam<"watch", boolean> | BaseCliParam<"watchBuildTree", boolean> | BaseCliParam<"continue", boolean> | BaseCliParam<"test", boolean> | BaseCliParam<"testType", string[]> | BaseCliParam<"testFiles", string[]> | BaseCliParam<"testCases", string[]> | BaseCliParam<"testDebugPort", number> | BaseCliParam<"launch", boolean> | BaseCliParam<"debugBackend", boolean> | BaseCliParam<"deploy", boolean> | BaseCliParam<"buildPushImage", string> | BaseCliParam<"deployImage", string> | BaseCliParam<"deployFunction", string> | BaseCliParam<"deleteFunctions", boolean> | BaseCliParam<"deleteFunction", string> | BaseCliParam<"debug", boolean> | BaseCliParam<"debugLifecycle", boolean> | BaseCliParam<"verbose", boolean> | BaseCliParam<"publish", "patch" | "minor" | "major"> | BaseCliParam<"usePackage", string[]> | BaseCliParam<"buildTree", boolean> | BaseCliParam<"includeApps", string[]> | BaseCliParam<"toESM", boolean> | BaseCliParam<"simulation", boolean> | BaseCliParam<"checkCyclicImports", boolean> | BaseCliParam<"extractDynamicDeps", boolean> | BaseCliParam<"mapExports", boolean> | BaseCliParam<"indicesMcpServer", boolean> | BaseCliParam<"indicesMcpPort", number> | BaseCliParam<"help", boolean>)[];
7
- export type Help_BaiParams = CliParams<typeof AllBaiParams_Help>;
3
+ import type { Phase } from '../phases/definitions/types.js';
4
+ import { ProjectUnit } from '../units/base/ProjectUnit.js';
5
+ export { BaiParam_Help };
8
6
  export type Phase_Help = typeof phase_Help;
9
7
  export declare const phaseKey_Help = "help";
10
8
  export declare const phase_Help: Phase<'printHelp'>;
@@ -13,4 +11,3 @@ declare class _Unit_HelpPrinter extends ProjectUnit implements UnitPhaseImplemen
13
11
  printHelp(): Promise<void>;
14
12
  }
15
13
  export declare const Unit_HelpPrinter: _Unit_HelpPrinter;
16
- export {};
@@ -1,15 +1,7 @@
1
1
  import { _keys, LogLevel, reduceToMap } from '@nu-art/ts-common';
2
- import { AllBaiParams, BaiParam_AllUnits, BaiParam_NoBuild, BaiParam_Prepare } from './params.js';
3
- import { ProjectUnit } from '../units/index.js';
4
- export const BaiParam_Help = {
5
- keys: ['--help', '-h'],
6
- keyName: 'help',
7
- type: 'boolean',
8
- group: 'General',
9
- description: 'This help menu',
10
- dependencies: [{ param: BaiParam_NoBuild, value: true }, { param: BaiParam_Prepare, value: false }, { param: BaiParam_AllUnits, value: true }],
11
- };
12
- const AllBaiParams_Help = [...AllBaiParams, BaiParam_Help];
2
+ import { AllBaiParams, BaiParam_Help } from './params.js';
3
+ import { ProjectUnit } from '../units/base/ProjectUnit.js';
4
+ export { BaiParam_Help };
13
5
  export const phaseKey_Help = 'help';
14
6
  export const phase_Help = {
15
7
  key: phaseKey_Help,
package/core/params.d.ts CHANGED
@@ -45,6 +45,7 @@ export declare const BaiParam_ExtractDynamicDeps: BaseCliParam<'extractDynamicDe
45
45
  export declare const BaiParam_MapExports: BaseCliParam<'mapExports', boolean>;
46
46
  export declare const BaiParam_IndicesMcpServer: BaseCliParam<'indicesMcpServer', boolean>;
47
47
  export declare const BaiParam_IndicesMcpPort: BaseCliParam<'indicesMcpPort', number>;
48
- export declare const AllBaiParams: (BaseCliParam<"allUnits", boolean> | BaseCliParam<"dependencyTree", boolean> | BaseCliParam<"environment", string> | BaseCliParam<"install", boolean> | BaseCliParam<"clean", boolean> | BaseCliParam<"purge", boolean> | BaseCliParam<"generate", boolean> | BaseCliParam<"generateDocs", boolean> | BaseCliParam<"noBuild", boolean> | BaseCliParam<"prepare", boolean> | BaseCliParam<"dryRun", boolean> | BaseCliParam<"lint", boolean> | BaseCliParam<"watch", boolean> | BaseCliParam<"watchBuildTree", boolean> | BaseCliParam<"continue", boolean> | BaseCliParam<"test", boolean> | BaseCliParam<"testType", string[]> | BaseCliParam<"testFiles", string[]> | BaseCliParam<"testCases", string[]> | BaseCliParam<"testDebugPort", number> | BaseCliParam<"launch", boolean> | BaseCliParam<"debugBackend", boolean> | BaseCliParam<"deploy", boolean> | BaseCliParam<"buildPushImage", string> | BaseCliParam<"deployImage", string> | BaseCliParam<"deployFunction", string> | BaseCliParam<"deleteFunctions", boolean> | BaseCliParam<"deleteFunction", string> | BaseCliParam<"debug", boolean> | BaseCliParam<"debugLifecycle", boolean> | BaseCliParam<"verbose", boolean> | BaseCliParam<"publish", PromoteType> | BaseCliParam<"usePackage", string[]> | BaseCliParam<"buildTree", boolean> | BaseCliParam<"includeApps", string[]> | BaseCliParam<"toESM", boolean> | BaseCliParam<"simulation", boolean> | BaseCliParam<"checkCyclicImports", boolean> | BaseCliParam<"extractDynamicDeps", boolean> | BaseCliParam<"mapExports", boolean> | BaseCliParam<"indicesMcpServer", boolean> | BaseCliParam<"indicesMcpPort", number>)[];
48
+ export declare const BaiParam_Help: BaseCliParam<'help', boolean>;
49
+ export declare const AllBaiParams: (BaseCliParam<"allUnits", boolean> | BaseCliParam<"dependencyTree", boolean> | BaseCliParam<"environment", string> | BaseCliParam<"install", boolean> | BaseCliParam<"clean", boolean> | BaseCliParam<"purge", boolean> | BaseCliParam<"generate", boolean> | BaseCliParam<"generateDocs", boolean> | BaseCliParam<"noBuild", boolean> | BaseCliParam<"prepare", boolean> | BaseCliParam<"dryRun", boolean> | BaseCliParam<"lint", boolean> | BaseCliParam<"watch", boolean> | BaseCliParam<"watchBuildTree", boolean> | BaseCliParam<"continue", boolean> | BaseCliParam<"test", boolean> | BaseCliParam<"testType", string[]> | BaseCliParam<"testFiles", string[]> | BaseCliParam<"testCases", string[]> | BaseCliParam<"testDebugPort", number> | BaseCliParam<"launch", boolean> | BaseCliParam<"debugBackend", boolean> | BaseCliParam<"deploy", boolean> | BaseCliParam<"buildPushImage", string> | BaseCliParam<"deployImage", string> | BaseCliParam<"deployFunction", string> | BaseCliParam<"deleteFunctions", boolean> | BaseCliParam<"deleteFunction", string> | BaseCliParam<"debug", boolean> | BaseCliParam<"debugLifecycle", boolean> | BaseCliParam<"verbose", boolean> | BaseCliParam<"publish", PromoteType> | BaseCliParam<"usePackage", string[]> | BaseCliParam<"buildTree", boolean> | BaseCliParam<"includeApps", string[]> | BaseCliParam<"toESM", boolean> | BaseCliParam<"simulation", boolean> | BaseCliParam<"checkCyclicImports", boolean> | BaseCliParam<"extractDynamicDeps", boolean> | BaseCliParam<"mapExports", boolean> | BaseCliParam<"indicesMcpServer", boolean> | BaseCliParam<"indicesMcpPort", number> | BaseCliParam<"help", boolean>)[];
49
50
  export type BaiParams = CliParams<typeof AllBaiParams>;
50
51
  export {};
package/core/params.js CHANGED
@@ -117,7 +117,7 @@ export const BaiParam_Test = {
117
117
  group: 'Test',
118
118
  description: 'Run the tests in all the project packages',
119
119
  };
120
- export const TestTypes = ['pure', 'firebase', 'ui', 'mobile'];
120
+ export const TestTypes = ['pure', 'firebase', 'ui', 'mobile', 'playwright'];
121
121
  export const BaiParam_TestType = {
122
122
  keys: ['--test-type', '-tt'],
123
123
  keyName: 'testType',
@@ -296,7 +296,7 @@ export const BaiParam_Publish = {
296
296
  process: (part) => part ?? 'patch'
297
297
  };
298
298
  export const BaiParam_UsePackage = {
299
- keys: ['-up', '--use-packages'],
299
+ keys: ['-up', '--use-package'],
300
300
  keyName: 'usePackage',
301
301
  type: 'string[]',
302
302
  group: 'Other',
@@ -395,6 +395,14 @@ export const BaiParam_IndicesMcpPort = {
395
395
  description: 'Port for Export Indices MCP server (default: 3001)',
396
396
  dependencies: [{ param: BaiParam_IndicesMcpServer, value: true }]
397
397
  };
398
+ export const BaiParam_Help = {
399
+ keys: ['--help', '-h'],
400
+ keyName: 'help',
401
+ type: 'boolean',
402
+ group: 'General',
403
+ description: 'This help menu',
404
+ dependencies: [{ param: BaiParam_NoBuild, value: true }, { param: BaiParam_Prepare, value: false }, { param: BaiParam_AllUnits, value: true }],
405
+ };
398
406
  export const AllBaiParams = [
399
407
  BaiParam_AllUnits,
400
408
  BaiParam_DependencyTree,
@@ -437,5 +445,6 @@ export const AllBaiParams = [
437
445
  BaiParam_MapExports,
438
446
  BaiParam_IndicesMcpServer,
439
447
  BaiParam_IndicesMcpPort,
440
- BaiParam_DebugLifecycle
448
+ BaiParam_DebugLifecycle,
449
+ BaiParam_Help,
441
450
  ];
package/core/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AsyncVoidFunction } from '@nu-art/ts-common';
2
- import { BaseUnit } from '../units/index.js';
3
- import { Phase } from '../phases/definitions/index.js';
2
+ import { BaseUnit } from '../units/base/BaseUnit.js';
3
+ import type { Phase } from '../phases/definitions/types.js';
4
4
  export type Unit<P extends Phase<string>[]> = BaseUnit & UnitPhaseImplementor<P>;
5
5
  export type UnitPhaseImplementor<P extends Phase<string>[]> = {
6
6
  [K in P[number]['method']]: AsyncVoidFunction;
@@ -69,4 +69,12 @@ export declare class UnitsDependencyMapper extends Logger {
69
69
  * Returns all leaf units (those with no dependencies).
70
70
  */
71
71
  getLeaves(): string[];
72
+ /**
73
+ * Detects cycles in a given dependency map (used for error reporting).
74
+ */
75
+ private detectCyclesInMap;
76
+ /**
77
+ * Formats the dependency graph as a readable string for error messages.
78
+ */
79
+ private formatDependencyGraph;
72
80
  }
@@ -99,10 +99,23 @@ export class UnitsDependencyMapper extends Logger {
99
99
  }
100
100
  }
101
101
  if (nextLayer.length === 0) {
102
- this.logWarning(participatingKeys);
103
- this.logWarning(map);
104
- this.logWarning(`Cyclic or disconnected dependency detected: ${lastNode?.key ?? '??'} and [${nextLayer.join(', ')}]`);
105
- throw new Error('Cyclic or disconnected dependency detected');
102
+ // Detect and report cycles explicitly
103
+ const cycles = this.detectCyclesInMap(map);
104
+ const unresolved = _keys(map).filter(key => !resolved.has(key) && !topLayer.includes(key));
105
+ let errorMessage = '';
106
+ errorMessage += `Last processed node: ${lastNode?.key ?? '??'}\n`;
107
+ errorMessage += `Unresolved nodes: [${unresolved.join(', ')}]\n`;
108
+ errorMessage += 'Cyclic or disconnected dependency detected!\n\n';
109
+ if (cycles.length > 0) {
110
+ errorMessage += `Found ${cycles.length} cycle(s):\n`;
111
+ for (const cycle of cycles) {
112
+ errorMessage += ` Cycle: ${cycle.join(' -> ')}\n`;
113
+ }
114
+ errorMessage += '\n';
115
+ }
116
+ this.logVerbose(`Full dependency graph:`, this.formatDependencyGraph(map));
117
+ this.logWarning(errorMessage);
118
+ throw new Error(errorMessage);
106
119
  }
107
120
  nextLayer.sort();
108
121
  layers.push(sortArray(nextLayer));
@@ -306,4 +319,45 @@ export class UnitsDependencyMapper extends Logger {
306
319
  getLeaves() {
307
320
  return _values(this.map).filter(node => node.dependsOn.length === 0).map(node => node.key).sort();
308
321
  }
322
+ /**
323
+ * Detects cycles in a given dependency map (used for error reporting).
324
+ */
325
+ detectCyclesInMap(map) {
326
+ const visited = new Set();
327
+ const inStack = new Set();
328
+ const cycles = [];
329
+ const visit = (key, path) => {
330
+ if (inStack.has(key)) {
331
+ const cycleStart = path.indexOf(key);
332
+ cycles.push(path.slice(cycleStart).concat(key));
333
+ return;
334
+ }
335
+ if (visited.has(key))
336
+ return;
337
+ visited.add(key);
338
+ inStack.add(key);
339
+ const node = map[key];
340
+ if (node)
341
+ for (const dep of node.dependsOn)
342
+ visit(dep, path.concat(key));
343
+ inStack.delete(key);
344
+ };
345
+ for (const key of _keys(map))
346
+ visit(key, []);
347
+ return cycles;
348
+ }
349
+ /**
350
+ * Formats the dependency graph as a readable string for error messages.
351
+ */
352
+ formatDependencyGraph(map) {
353
+ const lines = [];
354
+ for (const key of _keys(map)) {
355
+ const node = map[key];
356
+ const deps = node.dependsOn.length > 0
357
+ ? ` -> [${node.dependsOn.join(', ')}]`
358
+ : ' (no dependencies)';
359
+ lines.push(` ${key}${deps}`);
360
+ }
361
+ return lines.join('\n');
362
+ }
309
363
  }
@@ -1,5 +1,5 @@
1
1
  import { CustomException } from '@nu-art/ts-common';
2
- import { BaseUnit } from '../units/index.js';
2
+ import { BaseUnit } from '../units/base/BaseUnit.js';
3
3
  /**
4
4
  * Exception thrown when a specific phase fails on a specific unit.
5
5
  *
@@ -201,7 +201,7 @@ export class IndicesMcpServer extends Logger {
201
201
  package: packageName,
202
202
  stale,
203
203
  message: stale
204
- ? "Source files are newer than index files. Run 'bai --map-exports' to regenerate."
204
+ ? 'Source files are newer than index files. Run \'bai --map-exports\' to regenerate.'
205
205
  : 'Indices are up to date.'
206
206
  });
207
207
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nu-art/build-and-install",
3
- "version": "0.401.9",
3
+ "version": "0.500.6",
4
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": [
@@ -39,12 +39,12 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "chokidar": "^3.6.0",
42
- "@nu-art/cli-params": "0.401.9",
43
- "@nu-art/ts-common": "0.401.9",
44
- "@nu-art/commando": "0.401.9"
42
+ "@nu-art/cli-params": "0.500.6",
43
+ "@nu-art/ts-common": "0.500.6",
44
+ "@nu-art/commando": "0.500.6"
45
45
  },
46
46
  "devDependencies": {
47
- "@nu-art/testalot": "0.401.9"
47
+ "@nu-art/testalot": "0.500.6"
48
48
  },
49
49
  "unitConfig": {
50
50
  "type": "typescript-lib"
@@ -1,7 +1,7 @@
1
1
  import { Logger } from '@nu-art/ts-common';
2
2
  import { RunningStatusHandler } from '../runtime/RunningStatusHandler.js';
3
- import { Phase } from './definitions/index.js';
4
- import { BaseUnit } from '../units/index.js';
3
+ import type { Phase } from './definitions/types.js';
4
+ import { BaseUnit } from '../units/base/BaseUnit.js';
5
5
  /**
6
6
  * Scheduled execution step (before mapping to actual phases/units).
7
7
  */
@@ -99,8 +99,8 @@ export class PhaseManager extends Logger {
99
99
  // A unit is eligible if it's eligible for at least one phase in the group
100
100
  const eligibleUnitKeys = new Set();
101
101
  for (const phase of phaseGroup) {
102
- const unitCategory = phase.unitCategory ?? "active";
103
- const phaseEligibleKeys = unitCategory === "project" ? this.projectUnitKeys : this.activeUnits;
102
+ const unitCategory = phase.unitCategory ?? 'active';
103
+ const phaseEligibleKeys = unitCategory === 'project' ? this.projectUnitKeys : this.activeUnits;
104
104
  phaseEligibleKeys.forEach(key => eligibleUnitKeys.add(key));
105
105
  }
106
106
  const layerUnits = layer.filter(u => eligibleUnitKeys.has(u.config.key));
@@ -113,8 +113,8 @@ export class PhaseManager extends Logger {
113
113
  if (!(phase.method in unit && typeof unit[phase.method] === 'function'))
114
114
  return false;
115
115
  // Check if unit is eligible for this specific phase
116
- const unitCategory = phase.unitCategory ?? "active";
117
- const phaseEligibleKeys = unitCategory === "project" ? this.projectUnitKeys : this.activeUnits;
116
+ const unitCategory = phase.unitCategory ?? 'active';
117
+ const phaseEligibleKeys = unitCategory === 'project' ? this.projectUnitKeys : this.activeUnits;
118
118
  return phaseEligibleKeys.includes(unit.config.key);
119
119
  });
120
120
  if (supportedPhases.length === 0)
@@ -57,6 +57,9 @@ export declare const phase_Compile: Phase<'compile'>;
57
57
  export type Phase_PrepareWatch = typeof phase_PrepareWatch;
58
58
  export declare const phaseKey_PrepareWatch = "watchPrepare";
59
59
  export declare const phase_PrepareWatch: Phase<'watchPrepare'>;
60
+ export type Phase_InstallWatch = typeof phase_InstallWatch;
61
+ export declare const phaseKey_InstallWatch = "watchInstall";
62
+ export declare const phase_InstallWatch: Phase<'watchInstall'>;
60
63
  export type Phase_CompileWatch = typeof phase_CompileWatch;
61
64
  export declare const phaseKey_CompileWatch = "watchCompile";
62
65
  export declare const phase_CompileWatch: Phase<'watchCompile'>;
@@ -92,6 +92,13 @@ export const phase_PrepareWatch = {
92
92
  filter: (baiParams) => baiParams.prepare,
93
93
  unitCategory: 'project', // All project units need to be prepared
94
94
  };
95
+ export const phaseKey_InstallWatch = 'watchInstall';
96
+ export const phase_InstallWatch = {
97
+ key: phaseKey_InstallWatch,
98
+ name: 'Install Watch',
99
+ method: 'watchInstall',
100
+ dependencyPhase: [phase_PrepareWatch],
101
+ };
95
102
  export const phaseKey_CompileWatch = 'watchCompile';
96
103
  export const phase_CompileWatch = {
97
104
  key: phaseKey_CompileWatch,
@@ -36,5 +36,5 @@ export type Phase<PhaseMethod extends string> = {
36
36
  /** Phases that must complete before this phase runs */
37
37
  dependencyPhase?: Phase<string>[];
38
38
  /** Unit category: 'project' = all project units (active + dependencies), 'active' = only active units (default) */
39
- unitCategory?: "project" | "active";
39
+ unitCategory?: 'project' | 'active';
40
40
  };
@@ -1,56 +1,61 @@
1
1
  import express from 'express';
2
- import request from 'request';
3
2
  import * as fs from 'fs';
3
+ import {Readable} from 'node:stream';
4
+ import {createServer} from 'node:https';
4
5
 
5
6
 
6
7
  const _express: express.Express = express();
7
8
  let _counter = 0;
8
- _express.all('*', (req, res) => {
9
+ _express.all('*', async (req, res) => {
9
10
  const counter = ++_counter;
10
11
  const qMark = req.originalUrl.indexOf('?');
11
12
  const query = qMark > 1 ? req.originalUrl.substring(qMark) : '';
12
13
  const path = req.path;
13
- let url = `http://127.0.0.1:SERVER_PORT/PROJECT_ID/us-central1/api${path}${query}`;
14
- if (path.startsWith('/emulatorDownload') || path.startsWith('/emulatorUpload'))
15
- url = `http://127.0.0.1:SERVER_PORT/PROJECT_ID/us-central1${path}${query}`;
16
-
14
+ let url = `http://127.0.0.1:{{SERVER_PORT}}/{{PROJECT_ID}}/us-central1/api${path}${query}`;
17
15
  console.log(`PROXY ${counter} - [${req.method}] ${url}`);
18
16
 
19
- const handleError = (error: any) => {
20
- if(!error)
21
- return;
17
+ try {
18
+ const headers: Record<string, string | string[] | undefined> = {...req.headers};
19
+ delete headers['host'];
20
+ delete headers['content-length'];
22
21
 
23
- console.log(`ERROR calling: ${url}`, error);
24
- res.status(503).end();
25
- };
22
+ const fetchOptions: RequestInit = {
23
+ method: req.method,
24
+ headers: headers as HeadersInit
25
+ };
26
26
 
27
- try {
28
- let reqContent;
29
- if (req.method === 'POST') {
30
- reqContent = request.post({uri: url, body: req.body}, handleError);
31
- } else if (req.method === 'PUT') {
32
- reqContent = request.put({uri: url, body: req.body}, handleError);
33
- } else if (req.method === 'GET') {
34
- reqContent = request.get(url, handleError);
35
- } else if (req.method === 'DELETE') {
36
- reqContent = request.delete(url, handleError);
37
- } else if (req.method === 'HEAD') {
38
- reqContent = request.head(url, handleError);
27
+ // Stream request body for methods that can have a body (fetch forbids body on GET/HEAD)
28
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
29
+ fetchOptions.body = Readable.toWeb(req) as any;
30
+ (fetchOptions as RequestInit & { duplex: 'half' }).duplex = 'half';
31
+ }
32
+
33
+ const response = await fetch(url, fetchOptions);
34
+
35
+ res.status(response.status);
36
+ // Don't forward content-encoding/content-length: fetch already decompressed the body
37
+ response.headers.forEach((value, key) => {
38
+ const k = key.toLowerCase();
39
+ if (k === 'content-encoding' || k === 'content-length') return;
40
+ res.setHeader(key, value);
41
+ });
42
+
43
+ if (response.body) {
44
+ Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]).pipe(res, {end: true});
39
45
  } else {
40
- reqContent = request(url, handleError);
46
+ res.end();
41
47
  }
42
48
 
43
- req.pipe(reqContent).pipe(res, {end: true});
44
49
  console.log(`PROXY ${counter} - END`);
45
50
  } catch (e) {
46
51
  console.log(`ERROR calling: ${url}`, e);
47
- res.status(500).end();
52
+ res.status(503).end();
48
53
  }
49
54
  });
50
55
 
51
56
  const ssl = {
52
- key: 'PATH_TO_SSL_KEY',
53
- cert: 'PATH_TO_SSL_CERTIFICATE'
57
+ key: '{{PATH_TO_SSL_KEY}}',
58
+ cert: '{{PATH_TO_SSL_CERTIFICATE}}'
54
59
  };
55
60
 
56
61
  let key = ssl.key;
@@ -68,5 +73,5 @@ const options = {
68
73
  requestCert: false,
69
74
  };
70
75
 
71
- require('https').createServer(options, _express).listen(PROXY_PORT);
72
- console.log('SSL proxy started!!!');
76
+ createServer(options, _express).listen(+'{{PROXY_PORT}}');
77
+ console.log(`SSL proxy started at port: {{PROXY_PORT}}`);
@@ -2,6 +2,12 @@
2
2
  "rules": {
3
3
  ".read": false,
4
4
  ".write": false,
5
+ "_config": {
6
+ "frontend": {
7
+ ".read": true,
8
+ ".write": false
9
+ }
10
+ },
5
11
  "state": {
6
12
  "ModuleBE_SyncManager": {
7
13
  "syncData": {
@@ -3,7 +3,7 @@ import { CommandoInteractive } from '@nu-art/commando';
3
3
  import { BaseCommando } from '@nu-art/commando';
4
4
  import { MergeTypes } from '@nu-art/commando';
5
5
  import { Commando_Basic } from '@nu-art/commando';
6
- import { BAI_Config } from '../../config/types/index.js';
6
+ import { BAI_Config } from '../../config/types/project-config.js';
7
7
  import { UnitsDependencyMapper } from '../../dependencies/UnitsDependencyMapper.js';
8
8
  import { BaiParams } from '../../core/params.js';
9
9
  import { Workspace } from '../../workspace/Workspace.js';
@@ -1,4 +1,5 @@
1
- import { BaseUnit, ProjectUnit } from '../index.js';
1
+ import { BaseUnit } from '../base/BaseUnit.js';
2
+ import { ProjectUnit } from '../base/ProjectUnit.js';
2
3
  import { Logger } from '@nu-art/ts-common';
3
4
  import { UnitMapper_Base } from './resolvers/UnitMapper_Base.js';
4
5
  import { BaiParams } from '../../core/params.js';
@@ -34,7 +35,7 @@ export declare class UnitsMapper extends Logger {
34
35
  * @param projectRoot - The path to the project root
35
36
  * @param units - The project units derived from the file system
36
37
  */
37
- resolveUnits(path: string, projectRoot?: string, units?: BaseUnit<any>[]): Promise<BaseUnit<any, import("../index.js").UnitRuntimeContext>[]>;
38
+ resolveUnits(path: string, projectRoot?: string, units?: BaseUnit<any>[]): Promise<BaseUnit<any, import("../base/BaseUnit.js").UnitRuntimeContext>[]>;
38
39
  /**
39
40
  * Adds unit resolution rules.
40
41
  *
@@ -1,6 +1,6 @@
1
1
  import { AbsolutePath, Logger, RelativePath, StringMap, TypeValidator } from '@nu-art/ts-common';
2
- import { BaseUnit } from '../../index.js';
3
- import { BAI_Config } from '../../../config/types/index.js';
2
+ import { BaseUnit } from '../../base/BaseUnit.js';
3
+ import { BAI_Config } from '../../../config/types/project-config.js';
4
4
  import { BaiParams } from '../../../core/params.js';
5
5
  export type BaseUnitConfig = {
6
6
  fullPath: AbsolutePath;