@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.
- package/LICENSE +24 -0
- package/README.md +113 -0
- package/SECURITY.md +8 -0
- package/dist/config/environment.d.ts +78 -0
- package/dist/config/environment.js +150 -0
- package/dist/config/path-resolver.d.ts +117 -0
- package/dist/config/path-resolver.js +247 -0
- package/dist/dependency/dependency-manager.d.ts +66 -0
- package/dist/dependency/dependency-manager.js +257 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +17 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +36 -0
- package/dist/libs/archive-service.d.ts +21 -0
- package/dist/libs/archive-service.js +145 -0
- package/dist/libs/file-management-service.d.ts +59 -0
- package/dist/libs/file-management-service.js +189 -0
- package/dist/libs/iparams-service.d.ts +69 -0
- package/dist/libs/iparams-service.js +136 -0
- package/dist/libs/template-service.d.ts +57 -0
- package/dist/libs/template-service.js +152 -0
- package/dist/logger/cb-logger.d.ts +56 -0
- package/dist/logger/cb-logger.js +13 -0
- package/dist/logger/internal-logger.d.ts +81 -0
- package/dist/logger/internal-logger.js +146 -0
- package/dist/node/file-system.d.ts +66 -0
- package/dist/node/file-system.js +76 -0
- package/dist/node/process.d.ts +30 -0
- package/dist/node/process.js +25 -0
- package/dist/sandbox/sandbox-context.d.ts +37 -0
- package/dist/sandbox/sandbox-context.js +48 -0
- package/dist/sandbox/sandbox-wrapper.d.ts +75 -0
- package/dist/sandbox/sandbox-wrapper.js +2 -0
- package/dist/types/common.d.ts +135 -0
- package/dist/types/common.js +20 -0
- package/dist/validator/iparam-constants.d.ts +49 -0
- package/dist/validator/iparam-constants.js +52 -0
- package/dist/validator/iparam-defns-validator.d.ts +46 -0
- package/dist/validator/iparam-defns-validator.js +291 -0
- package/dist/validator/iparams-inputs-validator.d.ts +62 -0
- package/dist/validator/iparams-inputs-validator.js +289 -0
- package/dist/validator/manifest-validator.d.ts +48 -0
- package/dist/validator/manifest-validator.js +138 -0
- package/dist/validator/package-validator.d.ts +27 -0
- package/dist/validator/package-validator.js +43 -0
- package/dist/validator/validator-utils.d.ts +13 -0
- package/dist/validator/validator-utils.js +26 -0
- package/package.json +45 -0
|
@@ -0,0 +1,247 @@
|
|
|
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.PathResolver = exports.PathType = void 0;
|
|
40
|
+
const path_1 = __importDefault(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const environment_1 = require("./environment");
|
|
43
|
+
/**
|
|
44
|
+
* Path type enum for different package paths
|
|
45
|
+
*/
|
|
46
|
+
var PathType;
|
|
47
|
+
(function (PathType) {
|
|
48
|
+
/** Root directory of the CLI workspace */
|
|
49
|
+
PathType["CLI_ROOT"] = "CLI_ROOT";
|
|
50
|
+
/** Private application distribution directory */
|
|
51
|
+
PathType["PRIVATE_APP_DIST"] = "PRIVATE_APP_DIST";
|
|
52
|
+
/** Private application root directory */
|
|
53
|
+
PathType["PRIVATE_APP_ROOT"] = "PRIVATE_APP_ROOT";
|
|
54
|
+
/** Public libs templates directory */
|
|
55
|
+
PathType["PUBLIC_LIBS_TEMPLATES"] = "PUBLIC_LIBS_TEMPLATES";
|
|
56
|
+
/** Public libs UI web directory */
|
|
57
|
+
PathType["PUBLIC_LIBS_UI_WEB"] = "PUBLIC_LIBS_UI_WEB";
|
|
58
|
+
})(PathType || (exports.PathType = PathType = {}));
|
|
59
|
+
/**
|
|
60
|
+
* Path resolver class for resolving paths based on environment
|
|
61
|
+
* @class PathResolver
|
|
62
|
+
* @implements {IPathResolver}
|
|
63
|
+
*
|
|
64
|
+
* @description
|
|
65
|
+
* This class provides centralized path resolution for all packages in the CLI.
|
|
66
|
+
* It detects the environment (development vs production) and resolves paths accordingly:
|
|
67
|
+
* - In development: Uses workspace-relative paths
|
|
68
|
+
* - In production: Uses require.resolve to find installed packages
|
|
69
|
+
*
|
|
70
|
+
* This eliminates the need for try-catch error handling scattered across the codebase.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const pathResolver = new PathResolver();
|
|
75
|
+
* const templatesDir = pathResolver.getPublicLibsTemplatesDir();
|
|
76
|
+
* console.log(`Templates directory: ${templatesDir}`);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
class PathResolver {
|
|
80
|
+
constructor(envConfig) {
|
|
81
|
+
this.cliRoot = null;
|
|
82
|
+
this.envConfig = envConfig || new environment_1.EnvironmentConfig();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolves a path based on the path type and environment
|
|
86
|
+
* @param {PathType} pathType - Type of path to resolve
|
|
87
|
+
* @returns {string} Resolved path
|
|
88
|
+
* @throws {Error} If path cannot be resolved
|
|
89
|
+
*/
|
|
90
|
+
resolvePath(pathType) {
|
|
91
|
+
switch (pathType) {
|
|
92
|
+
case PathType.CLI_ROOT:
|
|
93
|
+
return this.getCliRoot();
|
|
94
|
+
case PathType.PRIVATE_APP_DIST:
|
|
95
|
+
return this.getPrivateAppDistDir();
|
|
96
|
+
case PathType.PRIVATE_APP_ROOT:
|
|
97
|
+
return this.getPrivateAppRootDir();
|
|
98
|
+
case PathType.PUBLIC_LIBS_TEMPLATES:
|
|
99
|
+
return this.getPublicLibsTemplatesDir();
|
|
100
|
+
case PathType.PUBLIC_LIBS_UI_WEB:
|
|
101
|
+
return this.getPublicLibsUiWebDir();
|
|
102
|
+
default:
|
|
103
|
+
throw new Error(`Unknown path type: ${pathType}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Gets the CLI workspace root path
|
|
108
|
+
* @returns {string} Path to CLI workspace root
|
|
109
|
+
*/
|
|
110
|
+
getCliRoot() {
|
|
111
|
+
if (this.cliRoot) {
|
|
112
|
+
return this.cliRoot;
|
|
113
|
+
}
|
|
114
|
+
if (this.envConfig.isDevelopment()) {
|
|
115
|
+
// Development: Find the project root by looking for package.json with workspaces
|
|
116
|
+
this.cliRoot = this.findProjectRootWithWorkspaces(__dirname);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Production: Use the package installation directory
|
|
120
|
+
// In production, packages are installed via npm and there's no workspace structure
|
|
121
|
+
this.cliRoot = path_1.default.resolve(__dirname, '../..');
|
|
122
|
+
}
|
|
123
|
+
return this.cliRoot;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets the private application distribution directory path
|
|
127
|
+
* @returns {string} Path to private application dist directory
|
|
128
|
+
*/
|
|
129
|
+
getPrivateAppDistDir() {
|
|
130
|
+
if (this.envConfig.isDevelopment()) {
|
|
131
|
+
// Development: Use workspace path
|
|
132
|
+
const cliRoot = this.getCliRoot();
|
|
133
|
+
return path_1.default.join(cliRoot, 'packages', 'private-application', 'dist');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Production: Find the installed package
|
|
137
|
+
try {
|
|
138
|
+
const resolvedPath = require.resolve('@chargebee-private/chargebee-apps-private-application');
|
|
139
|
+
return path_1.default.dirname(resolvedPath);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new Error('Failed to resolve private-application path. ' +
|
|
143
|
+
'Ensure @chargebee-private/chargebee-apps-private-application is installed.');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Gets the private application root directory path
|
|
149
|
+
* @returns {string} Path to private application root directory
|
|
150
|
+
*/
|
|
151
|
+
getPrivateAppRootDir() {
|
|
152
|
+
if (this.envConfig.isDevelopment()) {
|
|
153
|
+
// Development: Use workspace path
|
|
154
|
+
const cliRoot = this.getCliRoot();
|
|
155
|
+
return path_1.default.join(cliRoot, 'packages', 'private-application');
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// Production: Find the installed package root
|
|
159
|
+
try {
|
|
160
|
+
const packageJsonPath = require.resolve('@chargebee-private/chargebee-apps-private-application/package.json');
|
|
161
|
+
return path_1.default.dirname(packageJsonPath);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
throw new Error('Failed to resolve private-application root path. ' +
|
|
165
|
+
'Ensure @chargebee-private/chargebee-apps-private-application is installed.');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Gets the public libs templates directory path
|
|
171
|
+
* @returns {string} Path to public libs templates directory
|
|
172
|
+
*/
|
|
173
|
+
getPublicLibsTemplatesDir() {
|
|
174
|
+
if (this.envConfig.isDevelopment()) {
|
|
175
|
+
// Development: Use workspace path
|
|
176
|
+
const cliRoot = this.getCliRoot();
|
|
177
|
+
return path_1.default.join(cliRoot, 'packages', 'public-libs', 'templates');
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// Production: Find the installed package and get templates from package root
|
|
181
|
+
try {
|
|
182
|
+
const publicLibsPath = require.resolve('@chargebee/chargebee-apps-libs');
|
|
183
|
+
const packageRoot = path_1.default.dirname(path_1.default.dirname(publicLibsPath));
|
|
184
|
+
return path_1.default.join(packageRoot, 'templates');
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
throw new Error('Failed to resolve public-libs templates path. ' +
|
|
188
|
+
'Ensure @chargebee/chargebee-apps-libs is installed.');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Gets the public libs UI web directory path
|
|
194
|
+
* @returns {string} Path to public libs UI web directory
|
|
195
|
+
*/
|
|
196
|
+
getPublicLibsUiWebDir() {
|
|
197
|
+
if (this.envConfig.isDevelopment()) {
|
|
198
|
+
// Development: Use workspace path
|
|
199
|
+
const cliRoot = this.getCliRoot();
|
|
200
|
+
return path_1.default.join(cliRoot, 'packages', 'public-libs', 'ui', 'web');
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// Production: Find the installed package and get UI from package root
|
|
204
|
+
try {
|
|
205
|
+
const publicLibsPath = require.resolve('@chargebee/chargebee-apps-libs');
|
|
206
|
+
const packageRoot = path_1.default.dirname(path_1.default.dirname(publicLibsPath));
|
|
207
|
+
return path_1.default.join(packageRoot, 'ui', 'web');
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
throw new Error('Failed to resolve public-libs UI web path. ' +
|
|
211
|
+
'Ensure @chargebee/chargebee-apps-libs is installed.');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Finds the project root by looking for package.json with workspaces
|
|
217
|
+
* @param {string} startDir - Directory to start searching from
|
|
218
|
+
* @returns {string} Path to project root
|
|
219
|
+
* @throws {Error} If project root cannot be found
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
findProjectRootWithWorkspaces(startDir) {
|
|
223
|
+
let currentDir = startDir;
|
|
224
|
+
const root = path_1.default.parse(currentDir).root;
|
|
225
|
+
while (currentDir !== root) {
|
|
226
|
+
const packageJsonPath = path_1.default.join(currentDir, 'package.json');
|
|
227
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
228
|
+
try {
|
|
229
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
230
|
+
if (packageJson.workspaces) {
|
|
231
|
+
return currentDir;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
// Continue searching if package.json is invalid
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const parent = path_1.default.dirname(currentDir);
|
|
239
|
+
if (parent === currentDir) {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
currentDir = parent;
|
|
243
|
+
}
|
|
244
|
+
throw new Error('Could not find project root with workspaces');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.PathResolver = PathResolver;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CBFileSystem } from '../node/file-system';
|
|
2
|
+
import { AllowedModule, Manifest } from '../types/common';
|
|
3
|
+
/**
|
|
4
|
+
* DependencyManager handles isolated npm installations for user projects
|
|
5
|
+
* Public implementation for managing dependencies in development environment
|
|
6
|
+
*/
|
|
7
|
+
export declare class DependencyManager {
|
|
8
|
+
private installed;
|
|
9
|
+
private fileSystem;
|
|
10
|
+
constructor(fileSystem: CBFileSystem);
|
|
11
|
+
/**
|
|
12
|
+
* Ensures dependencies are installed for a user project
|
|
13
|
+
* @param {string} projectPath - Path to the user project directory
|
|
14
|
+
* @param {Manifest} manifest - The project manifest containing dependencies
|
|
15
|
+
* @returns {Promise<void>}
|
|
16
|
+
*/
|
|
17
|
+
ensureDependencies(projectPath: string, manifest: Manifest): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a safe require function that uses isolated node_modules
|
|
20
|
+
* @param {string} projectPath - Path to the user project
|
|
21
|
+
* @param {AllowedModule[]} allowedModules - List of allowed modules
|
|
22
|
+
* @returns {Function} Safe require function
|
|
23
|
+
*/
|
|
24
|
+
createIsolatedRequire(projectPath: string, allowedModules: AllowedModule[]): (moduleName: string) => any;
|
|
25
|
+
/**
|
|
26
|
+
* Creates or updates package.json for the project
|
|
27
|
+
* @param {string} packageJsonPath - Path to package.json
|
|
28
|
+
* @param {Record<string, string>} dependencies - Dependencies from manifest
|
|
29
|
+
*/
|
|
30
|
+
protected createPackageJson(packageJsonPath: string, dependencies: Record<string, string>): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Installs dependencies using npm
|
|
33
|
+
* @param {string} handlerPath - Path to the handler directory
|
|
34
|
+
*/
|
|
35
|
+
protected installDependencies(handlerPath: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Tries to load a CommonJS alternative for an ES module. This is a fallback for when the common JS is not the default export.
|
|
38
|
+
* @param moduleName - Name of the module to require
|
|
39
|
+
* @param resolvedModulePath - Path to the resolved module
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
protected tryLoadCommonJSAlternative(moduleName: string, resolvedModulePath: string): any;
|
|
43
|
+
/**
|
|
44
|
+
* Gets the relative path require.
|
|
45
|
+
* @param moduleName - Name of the module to require
|
|
46
|
+
* @param handlerPath - Path to the handler directory
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
protected getRelativePathRequire(moduleName: string, handlerPath: string): any;
|
|
50
|
+
/**
|
|
51
|
+
* Gets the generic dependency require. Unless there are special cases like ES modules, this should work for all dependencies.
|
|
52
|
+
* @param moduleName - Name of the module to require
|
|
53
|
+
* @param allowedModules - List of allowed modules
|
|
54
|
+
* @param nodeModulesPath - Path to the node_modules directory
|
|
55
|
+
* @returns
|
|
56
|
+
*/
|
|
57
|
+
protected getGenericDependencyRequire(moduleName: string, allowedModules: AllowedModule[], nodeModulesPath: string): any;
|
|
58
|
+
/**
|
|
59
|
+
* Validates and gets the resolved path to the module.
|
|
60
|
+
* @param allowedModules - List of allowed modules
|
|
61
|
+
* @param nodeModulesPath - Path to the node_modules directory
|
|
62
|
+
* @param moduleName - Name of the module to validate
|
|
63
|
+
* @returns Path to the module
|
|
64
|
+
*/
|
|
65
|
+
protected validateAndGetModulePath(allowedModules: AllowedModule[], nodeModulesPath: string, moduleName: string): string;
|
|
66
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
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.DependencyManager = void 0;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const semver_1 = __importDefault(require("semver"));
|
|
10
|
+
const internal_logger_1 = require("../logger/internal-logger");
|
|
11
|
+
/**
|
|
12
|
+
* DependencyManager handles isolated npm installations for user projects
|
|
13
|
+
* Public implementation for managing dependencies in development environment
|
|
14
|
+
*/
|
|
15
|
+
class DependencyManager {
|
|
16
|
+
constructor(fileSystem) {
|
|
17
|
+
this.fileSystem = fileSystem;
|
|
18
|
+
this.installed = false;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Ensures dependencies are installed for a user project
|
|
22
|
+
* @param {string} projectPath - Path to the user project directory
|
|
23
|
+
* @param {Manifest} manifest - The project manifest containing dependencies
|
|
24
|
+
* @returns {Promise<void>}
|
|
25
|
+
*/
|
|
26
|
+
async ensureDependencies(projectPath, manifest) {
|
|
27
|
+
if (!manifest.dependencies || Object.keys(manifest.dependencies).length === 0) {
|
|
28
|
+
internal_logger_1.__logger.debug('No dependencies to install');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Check if already installed
|
|
32
|
+
if (this.installed) {
|
|
33
|
+
internal_logger_1.__logger.debug('Dependencies already installed for this project');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const handlerPath = path_1.default.join(projectPath, 'handler');
|
|
37
|
+
const packageJsonPath = path_1.default.join(handlerPath, 'package.json');
|
|
38
|
+
try {
|
|
39
|
+
// Create handler directory if it doesn't exist
|
|
40
|
+
if (!this.fileSystem.existsSync(handlerPath)) {
|
|
41
|
+
this.fileSystem.mkdirSync(handlerPath, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
// Create or update package.json
|
|
44
|
+
await this.createPackageJson(packageJsonPath, manifest.dependencies);
|
|
45
|
+
// Install dependencies
|
|
46
|
+
await this.installDependencies(handlerPath);
|
|
47
|
+
// Mark as installed
|
|
48
|
+
this.installed = true;
|
|
49
|
+
internal_logger_1.__logger.info(`Installed ${Object.keys(manifest.dependencies).length} dependencies for project`);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const err = error;
|
|
53
|
+
internal_logger_1.__logger.error('Failed to install dependencies:', err.message);
|
|
54
|
+
throw new Error(`Dependency installation failed: ${err.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Creates a safe require function that uses isolated node_modules
|
|
59
|
+
* @param {string} projectPath - Path to the user project
|
|
60
|
+
* @param {AllowedModule[]} allowedModules - List of allowed modules
|
|
61
|
+
* @returns {Function} Safe require function
|
|
62
|
+
*/
|
|
63
|
+
createIsolatedRequire(projectPath, allowedModules) {
|
|
64
|
+
const handlerPath = path_1.default.resolve(projectPath, 'handler');
|
|
65
|
+
const nodeModulesPath = path_1.default.join(handlerPath, 'node_modules');
|
|
66
|
+
return (moduleName) => {
|
|
67
|
+
// Check if the module is a relative path
|
|
68
|
+
if (moduleName.startsWith('./')) {
|
|
69
|
+
// Normalize the path to prevent path traversal attacks
|
|
70
|
+
return this.getRelativePathRequire(moduleName, handlerPath);
|
|
71
|
+
}
|
|
72
|
+
// Handle direct CommonJS paths (e.g., 'axios/dist/node/axios.cjs')
|
|
73
|
+
if (moduleName.includes('/')) {
|
|
74
|
+
// Extract the base module name
|
|
75
|
+
return this.getGenericDependencyRequire(moduleName, allowedModules, nodeModulesPath);
|
|
76
|
+
}
|
|
77
|
+
// Verify version if constraint is specified
|
|
78
|
+
const resolvedModulePath = this.validateAndGetModulePath(allowedModules, nodeModulesPath, moduleName);
|
|
79
|
+
try {
|
|
80
|
+
// Check if this is an ES module that loaded but doesn't have the expected interface
|
|
81
|
+
// This happens when ES modules export named exports instead of a default function
|
|
82
|
+
// Try to load the module and handle ES module issues with cjs (if available) else fallback to the ES module
|
|
83
|
+
return this.tryLoadCommonJSAlternative(moduleName, resolvedModulePath);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
const err = error;
|
|
87
|
+
throw new Error(`Failed to load module "${moduleName}": ${err.message}`);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Creates or updates package.json for the project
|
|
93
|
+
* @param {string} packageJsonPath - Path to package.json
|
|
94
|
+
* @param {Record<string, string>} dependencies - Dependencies from manifest
|
|
95
|
+
*/
|
|
96
|
+
async createPackageJson(packageJsonPath, dependencies) {
|
|
97
|
+
const packageJson = {
|
|
98
|
+
dependencies: { ...dependencies }
|
|
99
|
+
};
|
|
100
|
+
const content = JSON.stringify(packageJson, null, 2);
|
|
101
|
+
this.fileSystem.writeFileSync(packageJsonPath, content);
|
|
102
|
+
internal_logger_1.__logger.debug('Created/updated package.json');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Installs dependencies using npm
|
|
106
|
+
* @param {string} handlerPath - Path to the handler directory
|
|
107
|
+
*/
|
|
108
|
+
async installDependencies(handlerPath) {
|
|
109
|
+
try {
|
|
110
|
+
(0, child_process_1.execSync)('npm install --ignore-scripts --no-audit --no-fund --loglevel=error', {
|
|
111
|
+
cwd: handlerPath,
|
|
112
|
+
stdio: 'pipe',
|
|
113
|
+
timeout: 60000 // 60 second timeout
|
|
114
|
+
});
|
|
115
|
+
internal_logger_1.__logger.debug('npm install completed successfully');
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
const err = error;
|
|
119
|
+
throw new Error(`npm install failed: ${err.message}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Tries to load a CommonJS alternative for an ES module. This is a fallback for when the common JS is not the default export.
|
|
124
|
+
* @param moduleName - Name of the module to require
|
|
125
|
+
* @param resolvedModulePath - Path to the resolved module
|
|
126
|
+
* @returns
|
|
127
|
+
*/
|
|
128
|
+
tryLoadCommonJSAlternative(moduleName, resolvedModulePath) {
|
|
129
|
+
const module = require(resolvedModulePath);
|
|
130
|
+
if (module && typeof module === 'object' && module.__esModule && typeof module !== 'function') {
|
|
131
|
+
internal_logger_1.__logger.debug(`ES module detected for ${moduleName} (loaded but has named exports), looking for CommonJS alternative`);
|
|
132
|
+
const packageJsonPath = path_1.default.join(resolvedModulePath, 'package.json');
|
|
133
|
+
if (this.fileSystem.existsSync(packageJsonPath)) {
|
|
134
|
+
const packageJson = JSON.parse(this.fileSystem.readFileSync(packageJsonPath, 'utf8'));
|
|
135
|
+
// Try to find CommonJS export from package.json exports
|
|
136
|
+
if (packageJson.exports && packageJson.exports['.']) {
|
|
137
|
+
const exports = packageJson.exports['.'];
|
|
138
|
+
// Try direct require field
|
|
139
|
+
if (exports.require) {
|
|
140
|
+
const cjsPath = path_1.default.resolve(resolvedModulePath, exports.require);
|
|
141
|
+
internal_logger_1.__logger.debug(`Trying CommonJS path: ${exports.require}`);
|
|
142
|
+
return require(cjsPath);
|
|
143
|
+
}
|
|
144
|
+
// Try nested default.require (like axios)
|
|
145
|
+
if (exports.default && exports.default.require) {
|
|
146
|
+
const cjsPath = path_1.default.resolve(resolvedModulePath, exports.default.require);
|
|
147
|
+
internal_logger_1.__logger.debug(`Trying default CommonJS path: ${exports.default.require}`);
|
|
148
|
+
return require(cjsPath);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Try to find CommonJS entry point from main field
|
|
152
|
+
if (packageJson.main) {
|
|
153
|
+
const mainPath = path_1.default.resolve(resolvedModulePath, packageJson.main);
|
|
154
|
+
internal_logger_1.__logger.debug(`Trying main field: ${packageJson.main}`);
|
|
155
|
+
return require(mainPath);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// If we can't find a CommonJS alternative, return the ES module as-is
|
|
159
|
+
internal_logger_1.__logger.error(`No CommonJS alternative found for ${moduleName}, using ES module as-is`);
|
|
160
|
+
return module;
|
|
161
|
+
}
|
|
162
|
+
return module;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets the relative path require.
|
|
166
|
+
* @param moduleName - Name of the module to require
|
|
167
|
+
* @param handlerPath - Path to the handler directory
|
|
168
|
+
* @returns
|
|
169
|
+
*/
|
|
170
|
+
getRelativePathRequire(moduleName, handlerPath) {
|
|
171
|
+
const normalizedPath = path_1.default.normalize(moduleName);
|
|
172
|
+
// Check for any path traversal attempts after normalization
|
|
173
|
+
if (normalizedPath.includes('..')) {
|
|
174
|
+
throw new Error('Path traversal not allowed in relative imports');
|
|
175
|
+
}
|
|
176
|
+
// Resolve the path relative to handlerPath
|
|
177
|
+
const resolvedPath = path_1.default.resolve(handlerPath, normalizedPath);
|
|
178
|
+
// Validate that the resolved path is within the handlerPath directory
|
|
179
|
+
if (!resolvedPath.startsWith(handlerPath)) {
|
|
180
|
+
throw new Error('Relative import path resolves outside of handler directory');
|
|
181
|
+
}
|
|
182
|
+
// Check if the file exists and determine the correct path to require
|
|
183
|
+
let finalPath = resolvedPath;
|
|
184
|
+
if (!this.fileSystem.existsSync(resolvedPath)) {
|
|
185
|
+
const jsPath = resolvedPath + ".js";
|
|
186
|
+
if (this.fileSystem.existsSync(jsPath)) {
|
|
187
|
+
finalPath = jsPath; // Use the .js path that actually exists
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
throw new Error(`File or module not found: ${moduleName}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return require(finalPath);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Gets the generic dependency require. Unless there are special cases like ES modules, this should work for all dependencies.
|
|
197
|
+
* @param moduleName - Name of the module to require
|
|
198
|
+
* @param allowedModules - List of allowed modules
|
|
199
|
+
* @param nodeModulesPath - Path to the node_modules directory
|
|
200
|
+
* @returns
|
|
201
|
+
*/
|
|
202
|
+
getGenericDependencyRequire(moduleName, allowedModules, nodeModulesPath) {
|
|
203
|
+
const baseModuleName = moduleName.split('/')[0];
|
|
204
|
+
// Check if the base module is allowed
|
|
205
|
+
const allowedModule = allowedModules.find(module => module.name === baseModuleName);
|
|
206
|
+
if (!allowedModule) {
|
|
207
|
+
throw new Error(`Module "${baseModuleName}" is not allowed in this environment`);
|
|
208
|
+
}
|
|
209
|
+
// Check if the full path exists in project's node_modules
|
|
210
|
+
const fullModulePath = path_1.default.join(nodeModulesPath, moduleName);
|
|
211
|
+
if (!this.fileSystem.existsSync(fullModulePath)) {
|
|
212
|
+
throw new Error(`Module path "${moduleName}" is not installed. Please ensure dependencies are installed.`);
|
|
213
|
+
}
|
|
214
|
+
internal_logger_1.__logger.debug(`Loading CommonJS path: ${moduleName}`);
|
|
215
|
+
return require(path_1.default.resolve(fullModulePath));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Validates and gets the resolved path to the module.
|
|
219
|
+
* @param allowedModules - List of allowed modules
|
|
220
|
+
* @param nodeModulesPath - Path to the node_modules directory
|
|
221
|
+
* @param moduleName - Name of the module to validate
|
|
222
|
+
* @returns Path to the module
|
|
223
|
+
*/
|
|
224
|
+
validateAndGetModulePath(allowedModules, nodeModulesPath, moduleName) {
|
|
225
|
+
// Check if module is installed in project's node_modules
|
|
226
|
+
const modulePath = path_1.default.join(nodeModulesPath, moduleName);
|
|
227
|
+
if (!this.fileSystem.existsSync(modulePath)) {
|
|
228
|
+
throw new Error(`Module "${moduleName}" is not installed. Please ensure dependencies are installed.`);
|
|
229
|
+
}
|
|
230
|
+
// Check if module is allowed
|
|
231
|
+
const allowedModule = allowedModules.find(module => module.name === moduleName);
|
|
232
|
+
if (!allowedModule) {
|
|
233
|
+
throw new Error(`Module "${moduleName}" is not allowed in this environment`);
|
|
234
|
+
}
|
|
235
|
+
if (allowedModule.version) {
|
|
236
|
+
try {
|
|
237
|
+
const packageJsonPath = path_1.default.join(modulePath, 'package.json');
|
|
238
|
+
const packageJson = JSON.parse(this.fileSystem.readFileSync(packageJsonPath, 'utf8'));
|
|
239
|
+
const installedVersion = packageJson.version;
|
|
240
|
+
if (!semver_1.default.satisfies(installedVersion, allowedModule.version)) {
|
|
241
|
+
throw new Error(`Module "${moduleName}" version ${installedVersion} does not satisfy allowed version constraint ${allowedModule.version}`);
|
|
242
|
+
}
|
|
243
|
+
internal_logger_1.__logger.debug(`Module "${moduleName}" version ${installedVersion} satisfies constraint ${allowedModule.version}`);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
const err = error;
|
|
247
|
+
internal_logger_1.__logger.warn(`Warning: Could not verify version for module "${moduleName}":`, err.message);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
throw new Error(`Configuration error: Allowed module "${moduleName}" does not have a version constraint`);
|
|
252
|
+
}
|
|
253
|
+
// Fallback to the module path, might or might not work for some dependencies.
|
|
254
|
+
return path_1.default.resolve(modulePath);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
exports.DependencyManager = DependencyManager;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when required installation parameters are missing.
|
|
3
|
+
* Carries the list of missing parameter names for API responses.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MissingRequiredParamsError extends Error {
|
|
6
|
+
readonly missing: string[];
|
|
7
|
+
constructor(missing: string[]);
|
|
8
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MissingRequiredParamsError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error thrown when required installation parameters are missing.
|
|
6
|
+
* Carries the list of missing parameter names for API responses.
|
|
7
|
+
*/
|
|
8
|
+
class MissingRequiredParamsError extends Error {
|
|
9
|
+
constructor(missing) {
|
|
10
|
+
const params = missing.join(', ');
|
|
11
|
+
super(`Missing required parameter${missing.length > 1 ? 's' : ''}: ${params}`);
|
|
12
|
+
this.name = 'MissingRequiredParamsError';
|
|
13
|
+
this.missing = missing;
|
|
14
|
+
Object.setPrototypeOf(this, MissingRequiredParamsError.prototype);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.MissingRequiredParamsError = MissingRequiredParamsError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './config/environment';
|
|
2
|
+
export * from './errors';
|
|
3
|
+
export * from './config/path-resolver';
|
|
4
|
+
export * from './dependency/dependency-manager';
|
|
5
|
+
export * from './libs/archive-service';
|
|
6
|
+
export * from './libs/file-management-service';
|
|
7
|
+
export * from './libs/iparams-service';
|
|
8
|
+
export * from './libs/template-service';
|
|
9
|
+
export * from './logger/cb-logger';
|
|
10
|
+
export * from './logger/internal-logger';
|
|
11
|
+
export * from './node/file-system';
|
|
12
|
+
export * from './node/process';
|
|
13
|
+
export * from './sandbox/sandbox-context';
|
|
14
|
+
export * from './sandbox/sandbox-wrapper';
|
|
15
|
+
export * from './types/common';
|
|
16
|
+
export * from './validator/manifest-validator';
|
|
17
|
+
export * from './validator/package-validator';
|
|
18
|
+
export * from './validator/iparams-inputs-validator';
|
|
19
|
+
export * from './validator/iparam-defns-validator';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Export all shared interfaces and types
|
|
18
|
+
__exportStar(require("./config/environment"), exports);
|
|
19
|
+
__exportStar(require("./errors"), exports);
|
|
20
|
+
__exportStar(require("./config/path-resolver"), exports);
|
|
21
|
+
__exportStar(require("./dependency/dependency-manager"), exports);
|
|
22
|
+
__exportStar(require("./libs/archive-service"), exports);
|
|
23
|
+
__exportStar(require("./libs/file-management-service"), exports);
|
|
24
|
+
__exportStar(require("./libs/iparams-service"), exports);
|
|
25
|
+
__exportStar(require("./libs/template-service"), exports);
|
|
26
|
+
__exportStar(require("./logger/cb-logger"), exports);
|
|
27
|
+
__exportStar(require("./logger/internal-logger"), exports);
|
|
28
|
+
__exportStar(require("./node/file-system"), exports);
|
|
29
|
+
__exportStar(require("./node/process"), exports);
|
|
30
|
+
__exportStar(require("./sandbox/sandbox-context"), exports);
|
|
31
|
+
__exportStar(require("./sandbox/sandbox-wrapper"), exports);
|
|
32
|
+
__exportStar(require("./types/common"), exports);
|
|
33
|
+
__exportStar(require("./validator/manifest-validator"), exports);
|
|
34
|
+
__exportStar(require("./validator/package-validator"), exports);
|
|
35
|
+
__exportStar(require("./validator/iparams-inputs-validator"), exports);
|
|
36
|
+
__exportStar(require("./validator/iparam-defns-validator"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CBFileSystem } from "../node/file-system";
|
|
2
|
+
/**
|
|
3
|
+
* Archive service for managing zip file creation and extraction
|
|
4
|
+
*/
|
|
5
|
+
export declare class ArchiveService {
|
|
6
|
+
private fileSystem;
|
|
7
|
+
constructor(fileSystem: CBFileSystem);
|
|
8
|
+
/**
|
|
9
|
+
* Creates the zip package
|
|
10
|
+
* @param {string[]} files - Array of files to package
|
|
11
|
+
* @param {string} appDir - The application directory
|
|
12
|
+
* @param {string} outputPath - The output path for the package
|
|
13
|
+
*/
|
|
14
|
+
createZipPackage(files: string[], appDir: string, outputPath: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Extract zip file to specified directory using yauzl
|
|
17
|
+
* @param {string} zipFilePath - Path to the zip file
|
|
18
|
+
* @param {string} extractDir - Directory to extract contents to
|
|
19
|
+
*/
|
|
20
|
+
extractZipFile(zipFilePath: string, extractDir: string): Promise<void>;
|
|
21
|
+
}
|