@chargebee/chargebee-apps-shared 0.0.2

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 (48) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +113 -0
  3. package/SECURITY.md +8 -0
  4. package/dist/config/environment.d.ts +78 -0
  5. package/dist/config/environment.js +150 -0
  6. package/dist/config/path-resolver.d.ts +117 -0
  7. package/dist/config/path-resolver.js +247 -0
  8. package/dist/dependency/dependency-manager.d.ts +66 -0
  9. package/dist/dependency/dependency-manager.js +257 -0
  10. package/dist/errors.d.ts +8 -0
  11. package/dist/errors.js +17 -0
  12. package/dist/index.d.ts +19 -0
  13. package/dist/index.js +36 -0
  14. package/dist/libs/archive-service.d.ts +21 -0
  15. package/dist/libs/archive-service.js +145 -0
  16. package/dist/libs/file-management-service.d.ts +59 -0
  17. package/dist/libs/file-management-service.js +189 -0
  18. package/dist/libs/iparams-service.d.ts +69 -0
  19. package/dist/libs/iparams-service.js +136 -0
  20. package/dist/libs/template-service.d.ts +57 -0
  21. package/dist/libs/template-service.js +152 -0
  22. package/dist/logger/cb-logger.d.ts +56 -0
  23. package/dist/logger/cb-logger.js +13 -0
  24. package/dist/logger/internal-logger.d.ts +81 -0
  25. package/dist/logger/internal-logger.js +146 -0
  26. package/dist/node/file-system.d.ts +66 -0
  27. package/dist/node/file-system.js +76 -0
  28. package/dist/node/process.d.ts +30 -0
  29. package/dist/node/process.js +25 -0
  30. package/dist/sandbox/sandbox-context.d.ts +37 -0
  31. package/dist/sandbox/sandbox-context.js +48 -0
  32. package/dist/sandbox/sandbox-wrapper.d.ts +75 -0
  33. package/dist/sandbox/sandbox-wrapper.js +2 -0
  34. package/dist/types/common.d.ts +135 -0
  35. package/dist/types/common.js +20 -0
  36. package/dist/validator/iparam-constants.d.ts +49 -0
  37. package/dist/validator/iparam-constants.js +52 -0
  38. package/dist/validator/iparam-defns-validator.d.ts +46 -0
  39. package/dist/validator/iparam-defns-validator.js +291 -0
  40. package/dist/validator/iparams-inputs-validator.d.ts +62 -0
  41. package/dist/validator/iparams-inputs-validator.js +289 -0
  42. package/dist/validator/manifest-validator.d.ts +48 -0
  43. package/dist/validator/manifest-validator.js +138 -0
  44. package/dist/validator/package-validator.d.ts +27 -0
  45. package/dist/validator/package-validator.js +43 -0
  46. package/dist/validator/validator-utils.d.ts +13 -0
  47. package/dist/validator/validator-utils.js +26 -0
  48. package/package.json +45 -0
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ArchiveService = void 0;
40
+ const archiver_1 = __importDefault(require("archiver"));
41
+ const path_1 = __importDefault(require("path"));
42
+ const internal_logger_1 = require("../logger/internal-logger");
43
+ const yauzl = __importStar(require("yauzl"));
44
+ const fs_1 = __importDefault(require("fs"));
45
+ const fs_2 = require("fs");
46
+ /**
47
+ * Archive service for managing zip file creation and extraction
48
+ */
49
+ class ArchiveService {
50
+ constructor(fileSystem) {
51
+ this.fileSystem = fileSystem;
52
+ }
53
+ /**
54
+ * Creates the zip package
55
+ * @param {string[]} files - Array of files to package
56
+ * @param {string} appDir - The application directory
57
+ * @param {string} outputPath - The output path for the package
58
+ */
59
+ createZipPackage(files, appDir, outputPath) {
60
+ return new Promise((resolve, reject) => {
61
+ const output = this.fileSystem.createWriteStream(outputPath);
62
+ const archive = (0, archiver_1.default)('zip');
63
+ output.on('close', () => {
64
+ internal_logger_1.__logger.info(`Archive created: ${archive.pointer()} total bytes`);
65
+ resolve();
66
+ });
67
+ output.on('error', (err) => {
68
+ internal_logger_1.__logger.error('Error writing to output file:', err);
69
+ reject(err);
70
+ });
71
+ archive.on('error', (err) => {
72
+ internal_logger_1.__logger.error('Error creating archive:', err);
73
+ reject(err);
74
+ });
75
+ archive.pipe(output);
76
+ // Add files to the archive
77
+ files.forEach(file => {
78
+ const filePath = path_1.default.join(appDir, file);
79
+ if (this.fileSystem.existsSync(filePath)) {
80
+ archive.file(filePath, { name: file });
81
+ internal_logger_1.__logger.info(` - Added: ${file}`);
82
+ }
83
+ });
84
+ archive.finalize();
85
+ });
86
+ }
87
+ /**
88
+ * Extract zip file to specified directory using yauzl
89
+ * @param {string} zipFilePath - Path to the zip file
90
+ * @param {string} extractDir - Directory to extract contents to
91
+ */
92
+ extractZipFile(zipFilePath, extractDir) {
93
+ return new Promise((resolve, reject) => {
94
+ yauzl.open(zipFilePath, { lazyEntries: true }, (err, zipfile) => {
95
+ if (err) {
96
+ internal_logger_1.__logger.error('Error opening zip file:', err);
97
+ reject(err);
98
+ return;
99
+ }
100
+ zipfile.readEntry();
101
+ zipfile.on('entry', (entry) => {
102
+ if (/\/$/.test(entry.fileName)) {
103
+ // Directory entry
104
+ const dirPath = path_1.default.join(extractDir, entry.fileName);
105
+ fs_1.default.mkdirSync(dirPath, { recursive: true });
106
+ zipfile.readEntry();
107
+ }
108
+ else {
109
+ // File entry
110
+ zipfile.openReadStream(entry, (err, readStream) => {
111
+ if (err) {
112
+ internal_logger_1.__logger.error('Error opening read stream:', err);
113
+ reject(err);
114
+ return;
115
+ }
116
+ const filePath = path_1.default.join(extractDir, entry.fileName);
117
+ const dirPath = path_1.default.dirname(filePath);
118
+ // Ensure directory exists
119
+ fs_1.default.mkdirSync(dirPath, { recursive: true });
120
+ const writeStream = (0, fs_2.createWriteStream)(filePath);
121
+ readStream.pipe(writeStream);
122
+ writeStream.on('close', () => {
123
+ internal_logger_1.__logger.info(`Extracted: ${entry.fileName}`);
124
+ zipfile.readEntry();
125
+ });
126
+ writeStream.on('error', (err) => {
127
+ internal_logger_1.__logger.error('Error writing to file:', err);
128
+ reject(err);
129
+ });
130
+ });
131
+ }
132
+ });
133
+ zipfile.on('end', () => {
134
+ internal_logger_1.__logger.info('Extraction completed');
135
+ resolve();
136
+ });
137
+ zipfile.on('error', (err) => {
138
+ internal_logger_1.__logger.error('Error processing zip file:', err);
139
+ reject(err);
140
+ });
141
+ });
142
+ });
143
+ }
144
+ }
145
+ exports.ArchiveService = ArchiveService;
@@ -0,0 +1,59 @@
1
+ import { CBFileSystem } from "../node/file-system";
2
+ export interface FileSystemConfig {
3
+ include: {
4
+ directories: DirectoryConfig[];
5
+ };
6
+ }
7
+ export interface DirectoryConfig {
8
+ name: string;
9
+ allowedExtensions?: string[];
10
+ excludeSubdirs?: string[];
11
+ includeFiles?: string[];
12
+ excludeFiles?: string[];
13
+ }
14
+ /**
15
+ * File management service for handling file operations
16
+ */
17
+ export declare class FileManagementService {
18
+ private fileSystem;
19
+ private packageConfig;
20
+ constructor(fileSystem: CBFileSystem, packageConfig: FileSystemConfig);
21
+ /**
22
+ * Collects essential files for the serverless application package
23
+ * Only includes files and directories specified in packageConfig
24
+ * @param {string} appDir - The application directory
25
+ * @returns {string[]} Array of file paths to package
26
+ */
27
+ collectFilesToPackage(appDir: string): string[];
28
+ /**
29
+ * Cleans all files and folders inside the dist directory
30
+ * @param {string} appDir - The application directory
31
+ */
32
+ cleanExistingPackages(appDir: string): void;
33
+ /**
34
+ * Determines the output path for the package
35
+ * @param {string} appDir - The application directory
36
+ * @param {string} appName - The application name
37
+ * @param {PackageOptions} options - Package options
38
+ * @returns {string} The output path for the package
39
+ */
40
+ determineOutputPath(appDir: string, appName: string, packageName?: string): string;
41
+ /**
42
+ * Gets the file size in a human-readable format
43
+ * @param {string} filePath - The file path
44
+ * @returns {string} Human-readable file size
45
+ */
46
+ getFileSize(filePath: string): string;
47
+ /**
48
+ * Collects files recursively from a directory based on directory-specific configurations
49
+ * @param {string} dir - The directory to scan
50
+ * @param {DirectoryConfig} dirConfig - Directory configuration with file inclusion/exclusion rules
51
+ * @returns {string[]} Array of file paths relative to the scanned directory
52
+ */
53
+ protected getFilesRecursively(dir: string, dirConfig: DirectoryConfig): string[];
54
+ /**
55
+ * Recursively deletes a directory and all its contents
56
+ * @param {string} dirPath - The directory path to delete
57
+ */
58
+ protected deleteDirectoryRecursively(dirPath: string): void;
59
+ }
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FileManagementService = void 0;
7
+ const internal_logger_1 = require("../logger/internal-logger");
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * File management service for handling file operations
11
+ */
12
+ class FileManagementService {
13
+ constructor(fileSystem, packageConfig) {
14
+ this.fileSystem = fileSystem;
15
+ this.packageConfig = packageConfig;
16
+ }
17
+ /**
18
+ * Collects essential files for the serverless application package
19
+ * Only includes files and directories specified in packageConfig
20
+ * @param {string} appDir - The application directory
21
+ * @returns {string[]} Array of file paths to package
22
+ */
23
+ collectFilesToPackage(appDir) {
24
+ const files = [];
25
+ // Process directories specified in packageConfig
26
+ this.packageConfig.include.directories.forEach(dirConfig => {
27
+ if (dirConfig.name === '.') {
28
+ // Handle root directory case - collect files directly from appDir
29
+ const rootFiles = this.getFilesRecursively(appDir, dirConfig);
30
+ files.push(...rootFiles);
31
+ }
32
+ else {
33
+ // Handle subdirectory case
34
+ const dirPath = path_1.default.join(appDir, dirConfig.name);
35
+ if (this.fileSystem.existsSync(dirPath)) {
36
+ const dirFiles = this.getFilesRecursively(dirPath, dirConfig);
37
+ // Add directory files with directory prefix
38
+ dirFiles.forEach((file) => {
39
+ files.push(`${dirConfig.name}/${file}`);
40
+ });
41
+ }
42
+ else {
43
+ throw new Error(`Directory ${dirPath} does not exist`);
44
+ }
45
+ }
46
+ });
47
+ internal_logger_1.__logger.info(`Collected ${files.length} files to package`);
48
+ internal_logger_1.__logger.info(` - Directories: ${this.packageConfig.include.directories.map(d => d.name).join(', ')}`);
49
+ return files;
50
+ }
51
+ /**
52
+ * Cleans all files and folders inside the dist directory
53
+ * @param {string} appDir - The application directory
54
+ */
55
+ cleanExistingPackages(appDir) {
56
+ const distDir = path_1.default.join(appDir, 'dist');
57
+ if (!this.fileSystem.existsSync(distDir)) {
58
+ this.fileSystem.mkdirSync(distDir, { recursive: true });
59
+ return;
60
+ }
61
+ const files = this.fileSystem.readdirSync(distDir);
62
+ if (files.length > 0) {
63
+ internal_logger_1.__logger.info(`Cleaning ${files.length} item(s) in dist directory...`);
64
+ files.forEach(item => {
65
+ const itemPath = path_1.default.join(distDir, item);
66
+ const stat = this.fileSystem.statSync(itemPath);
67
+ if (stat.isDirectory()) {
68
+ this.deleteDirectoryRecursively(itemPath);
69
+ internal_logger_1.__logger.info(` - Removed directory: ${item}/`);
70
+ }
71
+ else {
72
+ this.fileSystem.unlinkSync(itemPath);
73
+ }
74
+ });
75
+ }
76
+ }
77
+ /**
78
+ * Determines the output path for the package
79
+ * @param {string} appDir - The application directory
80
+ * @param {string} appName - The application name
81
+ * @param {PackageOptions} options - Package options
82
+ * @returns {string} The output path for the package
83
+ */
84
+ determineOutputPath(appDir, appName, packageName) {
85
+ const distDir = path_1.default.join(appDir, 'dist');
86
+ packageName = packageName || appName;
87
+ const zipFileName = `${packageName}.zip`;
88
+ return path_1.default.join(distDir, zipFileName);
89
+ }
90
+ /**
91
+ * Gets the file size in a human-readable format
92
+ * @param {string} filePath - The file path
93
+ * @returns {string} Human-readable file size
94
+ */
95
+ getFileSize(filePath) {
96
+ const stats = this.fileSystem.statSync(filePath);
97
+ const bytes = stats.size;
98
+ if (bytes === 0) {
99
+ return '0 Bytes';
100
+ }
101
+ const k = 1024;
102
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
103
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
104
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
105
+ }
106
+ /**
107
+ * Collects files recursively from a directory based on directory-specific configurations
108
+ * @param {string} dir - The directory to scan
109
+ * @param {DirectoryConfig} dirConfig - Directory configuration with file inclusion/exclusion rules
110
+ * @returns {string[]} Array of file paths relative to the scanned directory
111
+ */
112
+ getFilesRecursively(dir, dirConfig) {
113
+ const files = [];
114
+ // Get configuration values
115
+ const allowedExtensions = dirConfig.allowedExtensions || [];
116
+ const excludeSubdirs = dirConfig.excludeSubdirs || [];
117
+ const includeFiles = dirConfig.includeFiles || [];
118
+ const excludeFiles = dirConfig.excludeFiles || [];
119
+ const scanDirectory = (currentDir, baseDir) => {
120
+ const items = this.fileSystem.readdirSync(currentDir);
121
+ for (const item of items) {
122
+ const itemPath = path_1.default.join(currentDir, item);
123
+ const lstat = this.fileSystem.lstatSync(itemPath);
124
+ // Skip symlinks — they may be broken (e.g. .bin/ entries in Docker overlay fs)
125
+ if (lstat.isSymbolicLink()) {
126
+ continue;
127
+ }
128
+ const stat = this.fileSystem.statSync(itemPath);
129
+ if (stat.isDirectory()) {
130
+ // Skip excluded subdirectories
131
+ if (!excludeSubdirs.includes(item)) {
132
+ scanDirectory(itemPath, baseDir);
133
+ }
134
+ }
135
+ else {
136
+ // Apply file inclusion/exclusion logic
137
+ if (item && typeof item === 'string') {
138
+ const relativePath = path_1.default.relative(baseDir, itemPath);
139
+ let shouldInclude = false;
140
+ // Priority 1: Check specific file inclusion (highest priority)
141
+ if (includeFiles.length > 0) {
142
+ shouldInclude = includeFiles.includes(item);
143
+ }
144
+ // Priority 2: Check extension-based inclusion (if no specific files defined)
145
+ else if (allowedExtensions.length > 0) {
146
+ const ext = path_1.default.extname(item).toLowerCase();
147
+ shouldInclude = allowedExtensions.includes(ext);
148
+ }
149
+ // Priority 3: Include all files if no inclusion rules defined
150
+ else {
151
+ shouldInclude = true;
152
+ }
153
+ // Apply exclusion rules (always applied if file was included)
154
+ if (shouldInclude && excludeFiles.length > 0) {
155
+ shouldInclude = !excludeFiles.includes(item);
156
+ }
157
+ if (shouldInclude) {
158
+ files.push(relativePath);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ };
164
+ if (this.fileSystem.existsSync(dir)) {
165
+ scanDirectory(dir, dir);
166
+ }
167
+ return files;
168
+ }
169
+ /**
170
+ * Recursively deletes a directory and all its contents
171
+ * @param {string} dirPath - The directory path to delete
172
+ */
173
+ deleteDirectoryRecursively(dirPath) {
174
+ const files = this.fileSystem.readdirSync(dirPath);
175
+ for (const file of files) {
176
+ const filePath = path_1.default.join(dirPath, file);
177
+ const stat = this.fileSystem.statSync(filePath);
178
+ if (stat.isDirectory()) {
179
+ this.deleteDirectoryRecursively(filePath);
180
+ }
181
+ else {
182
+ this.fileSystem.unlinkSync(filePath);
183
+ }
184
+ }
185
+ // Remove the empty directory
186
+ this.fileSystem.rmdirSync(dirPath);
187
+ }
188
+ }
189
+ exports.FileManagementService = FileManagementService;
@@ -0,0 +1,69 @@
1
+ import { CBFileSystem } from '../node/file-system';
2
+ import { IparamInputs, IparamDefns } from '../types/common';
3
+ /**
4
+ * Service for managing parameters
5
+ * Handles loading, validation, and management of iparams and inputs
6
+ */
7
+ export declare class IparamsService {
8
+ private fileSystem;
9
+ private iparamDefnsValidator;
10
+ private inputsValidator;
11
+ constructor(fileSystem: CBFileSystem);
12
+ private getIparamsFilePath;
13
+ private getInputsFilePath;
14
+ /**
15
+ * Checks if iparams.json file exists
16
+ * @param {string} appDir - The application directory
17
+ * @returns {boolean} True if the file exists
18
+ */
19
+ iparamsFileExists(appDir: string): boolean;
20
+ /**
21
+ * Loads and validates the iparamDefns
22
+ * @param {string} appDir - The application directory
23
+ * @returns {IparamDefns} The validated iparamDefns
24
+ * @throws {Error} If the iparamDefns is invalid or cannot be read
25
+ */
26
+ loadIparamDefns(appDir: string): IparamDefns;
27
+ /**
28
+ * Loads iparam inputs (without validation against defns). Validates file shape only.
29
+ * @param {string} appDir - The application directory
30
+ * @returns {IparamInputs} The loaded inputs
31
+ * @throws {Error} If `iparams.local.json` is missing, invalid JSON, or not a plain object
32
+ */
33
+ loadInputs(appDir: string): IparamInputs;
34
+ /**
35
+ * Merges inputs with defaults per section.
36
+ * @param {IparamInputs} inputs - The provided input values
37
+ * @param {IparamDefns} iparamDefns - The iparam defns
38
+ * @returns {IparamInputs} The merged inputs with defaults applied
39
+ * @throws {MissingRequiredParamsError} When required parameters are missing
40
+ */
41
+ mergeInputsWithDefaults(inputs: IparamInputs, iparamDefns: IparamDefns): IparamInputs;
42
+ /**
43
+ * Loads inputs and defns, validates inputs against defns, merges with defaults, returns resolved iparams.
44
+ * @param {string} appDir - The application directory
45
+ * @returns {IparamInputs} The merged inputs with defaults applied
46
+ * @throws {Error} If validation fails, or required parameters are missing and have no defaults
47
+ */
48
+ validateAndGetInputsForExecution(appDir: string): IparamInputs;
49
+ /**
50
+ * Saves the iparamDefns to file
51
+ * @param {string} appDir - The application directory
52
+ * @param {IparamDefns} iparamDefns - The iparamDefns to save
53
+ * @throws {Error} If the iparamDefns is invalid or cannot be written
54
+ */
55
+ saveIparamDefns(appDir: string, iparamDefns: IparamDefns): void;
56
+ /**
57
+ * Loads defns and merges inputs, ensures iparams.local.json exists, then writes.
58
+ * @param {string} appDir - The application directory
59
+ * @param {IparamInputs} inputs - The raw input values from the request
60
+ * @throws {Error} If iparams.json or iparams.local.json is missing, or validation fails
61
+ */
62
+ saveInputs(appDir: string, inputs: IparamInputs): void;
63
+ /**
64
+ * Validates iparams file without loading it
65
+ * @param {string} appDir - The application directory
66
+ * @throws {Error} If the iparamDefns is invalid
67
+ */
68
+ validateIparamDefns(appDir: string): void;
69
+ }
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.IparamsService = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const errors_1 = require("../errors");
9
+ const iparams_inputs_validator_1 = require("../validator/iparams-inputs-validator");
10
+ const iparam_defns_validator_1 = require("../validator/iparam-defns-validator");
11
+ const validator_utils_1 = require("../validator/validator-utils");
12
+ /**
13
+ * Service for managing parameters
14
+ * Handles loading, validation, and management of iparams and inputs
15
+ */
16
+ class IparamsService {
17
+ constructor(fileSystem) {
18
+ this.fileSystem = fileSystem;
19
+ this.iparamDefnsValidator = new iparam_defns_validator_1.IparamDefnsValidator(fileSystem);
20
+ this.inputsValidator = new iparams_inputs_validator_1.IparamInputsValidator(fileSystem);
21
+ }
22
+ getIparamsFilePath(appDir) {
23
+ return path_1.default.join(appDir, 'iparams.json');
24
+ }
25
+ getInputsFilePath(appDir) {
26
+ return path_1.default.join(appDir, 'iparams.local.json');
27
+ }
28
+ /**
29
+ * Checks if iparams.json file exists
30
+ * @param {string} appDir - The application directory
31
+ * @returns {boolean} True if the file exists
32
+ */
33
+ iparamsFileExists(appDir) {
34
+ return this.fileSystem.existsSync(this.getIparamsFilePath(appDir));
35
+ }
36
+ /**
37
+ * Loads and validates the iparamDefns
38
+ * @param {string} appDir - The application directory
39
+ * @returns {IparamDefns} The validated iparamDefns
40
+ * @throws {Error} If the iparamDefns is invalid or cannot be read
41
+ */
42
+ loadIparamDefns(appDir) {
43
+ return this.iparamDefnsValidator.validateAndGetIparamDefnsFile(this.getIparamsFilePath(appDir));
44
+ }
45
+ /**
46
+ * Loads iparam inputs (without validation against defns). Validates file shape only.
47
+ * @param {string} appDir - The application directory
48
+ * @returns {IparamInputs} The loaded inputs
49
+ * @throws {Error} If `iparams.local.json` is missing, invalid JSON, or not a plain object
50
+ */
51
+ loadInputs(appDir) {
52
+ return this.inputsValidator.validateAndGetIparamInputsFile(this.getInputsFilePath(appDir));
53
+ }
54
+ /**
55
+ * Merges inputs with defaults per section.
56
+ * @param {IparamInputs} inputs - The provided input values
57
+ * @param {IparamDefns} iparamDefns - The iparam defns
58
+ * @returns {IparamInputs} The merged inputs with defaults applied
59
+ * @throws {MissingRequiredParamsError} When required parameters are missing
60
+ */
61
+ mergeInputsWithDefaults(inputs, iparamDefns) {
62
+ const mergedInputs = {};
63
+ const missingRequired = [];
64
+ for (const section of iparamDefns.installation_parameters?.sections ?? []) {
65
+ const sectionInputs = inputs[section.name] ?? {};
66
+ const mergedSection = {};
67
+ for (const param of section.parameters) {
68
+ const value = sectionInputs[param.name];
69
+ const hasValue = iparams_inputs_validator_1.IparamInputsValidator.isProvidedIparamInputValue(value);
70
+ if (hasValue) {
71
+ mergedSection[param.name] = value;
72
+ continue;
73
+ }
74
+ if (param.default !== undefined && param.default !== null) {
75
+ mergedSection[param.name] = param.default;
76
+ continue;
77
+ }
78
+ if (param.required) {
79
+ missingRequired.push(`${section.name}.${param.name}`);
80
+ }
81
+ }
82
+ if (Object.keys(mergedSection).length > 0) {
83
+ mergedInputs[section.name] = mergedSection;
84
+ }
85
+ }
86
+ if (missingRequired.length > 0) {
87
+ throw new errors_1.MissingRequiredParamsError(missingRequired);
88
+ }
89
+ return mergedInputs;
90
+ }
91
+ /**
92
+ * Loads inputs and defns, validates inputs against defns, merges with defaults, returns resolved iparams.
93
+ * @param {string} appDir - The application directory
94
+ * @returns {IparamInputs} The merged inputs with defaults applied
95
+ * @throws {Error} If validation fails, or required parameters are missing and have no defaults
96
+ */
97
+ validateAndGetInputsForExecution(appDir) {
98
+ const inputs = this.loadInputs(appDir);
99
+ const iparamDefns = this.loadIparamDefns(appDir);
100
+ this.inputsValidator.validateInputs(inputs, iparamDefns);
101
+ return this.mergeInputsWithDefaults(inputs, iparamDefns);
102
+ }
103
+ /**
104
+ * Saves the iparamDefns to file
105
+ * @param {string} appDir - The application directory
106
+ * @param {IparamDefns} iparamDefns - The iparamDefns to save
107
+ * @throws {Error} If the iparamDefns is invalid or cannot be written
108
+ */
109
+ saveIparamDefns(appDir, iparamDefns) {
110
+ (0, validator_utils_1.ensureFileExists)(this.fileSystem, this.getIparamsFilePath(appDir));
111
+ this.iparamDefnsValidator.validate(iparamDefns);
112
+ this.fileSystem.writeFileSync(this.getIparamsFilePath(appDir), JSON.stringify(iparamDefns, null, '\t'));
113
+ }
114
+ /**
115
+ * Loads defns and merges inputs, ensures iparams.local.json exists, then writes.
116
+ * @param {string} appDir - The application directory
117
+ * @param {IparamInputs} inputs - The raw input values from the request
118
+ * @throws {Error} If iparams.json or iparams.local.json is missing, or validation fails
119
+ */
120
+ saveInputs(appDir, inputs) {
121
+ const iparamDefns = this.loadIparamDefns(appDir);
122
+ this.inputsValidator.validateInputs(inputs, iparamDefns);
123
+ const mergedInputs = this.mergeInputsWithDefaults(inputs, iparamDefns);
124
+ (0, validator_utils_1.ensureFileExists)(this.fileSystem, this.getInputsFilePath(appDir));
125
+ this.fileSystem.writeFileSync(this.getInputsFilePath(appDir), JSON.stringify(mergedInputs, null, '\t'));
126
+ }
127
+ /**
128
+ * Validates iparams file without loading it
129
+ * @param {string} appDir - The application directory
130
+ * @throws {Error} If the iparamDefns is invalid
131
+ */
132
+ validateIparamDefns(appDir) {
133
+ this.iparamDefnsValidator.validateAndGetIparamDefnsFile(this.getIparamsFilePath(appDir));
134
+ }
135
+ }
136
+ exports.IparamsService = IparamsService;
@@ -0,0 +1,57 @@
1
+ import { CBFileSystem } from '../node/file-system';
2
+ /**
3
+ * Template service for managing templates across different CLI packages
4
+ */
5
+ export declare class TemplateService {
6
+ private fileSystem;
7
+ private templatesDir;
8
+ constructor(fileSystem: CBFileSystem, templatesDir: string);
9
+ /**
10
+ * Validates template exists
11
+ * @param {string} template - Template name to validate
12
+ * @returns {boolean} True if template is valid
13
+ */
14
+ validateTemplate(template: string): boolean;
15
+ /**
16
+ * Validates app directory for conflicts
17
+ * @param {string} targetDir - Target directory path
18
+ * @param {string} appDir - Original app directory argument
19
+ * @param {string} template - Template name
20
+ * @returns {string[]} Array of conflicting files (empty if no conflicts)
21
+ */
22
+ validateAppDirectory(targetDir: string, appDir: string, template: string): string[];
23
+ /**
24
+ * Gets a list of available templates from the templates directory
25
+ * @returns {string[]} Array of template names
26
+ */
27
+ getAvailableTemplates(): string[];
28
+ /**
29
+ * Gets the full path to a specific template
30
+ * @param {string} template - Template name
31
+ * @returns {string} Full path to the template directory
32
+ */
33
+ getTemplatePath(template: string): string;
34
+ /**
35
+ * Gets the templates directory path
36
+ * @returns {string} Path to the templates directory
37
+ */
38
+ getTemplatesDirectory(): string;
39
+ /**
40
+ * Recursively collects all files from a template directory
41
+ * @param {string} templatePath - Path to the template directory
42
+ * @returns {string[]} Array of file paths relative to template root
43
+ */
44
+ getTemplateFiles(templatePath: string): string[];
45
+ /**
46
+ * Recursively copies all files from template directory to target directory
47
+ * @param {string} templatePath - Source template directory path
48
+ * @param {string} targetPath - Target directory path
49
+ */
50
+ copyTemplateFiles(templatePath: string, targetPath: string): void;
51
+ /**
52
+ * Prints a tree-like structure of the project directory
53
+ * @param {string} dir - Directory path to print structure for
54
+ * @param {string} [indent=''] - Current indentation level
55
+ */
56
+ printProjectStructure(dir: string, indent?: string): void;
57
+ }