@chargebee/chargebee-apps-libs
Advanced tools
@@ -1,95 +0,1 @@ | ||
| "use strict"; | ||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||
| return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.ConfigLoader = void 0; | ||
| const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared"); | ||
| const path_1 = __importDefault(require("path")); | ||
| const semver_1 = __importDefault(require("semver")); | ||
| /** | ||
| * ConfigLoader provides utilities for loading and managing configuration files | ||
| * Public implementation for loading allowed modules configuration | ||
| */ | ||
| class ConfigLoader { | ||
| constructor(fileSystem) { | ||
| this.fileSystem = fileSystem; | ||
| this.cache = new Map(); | ||
| } | ||
| /** | ||
| * Loads and validates the allowed modules configuration | ||
| * @returns {AllowedModule[]} Array of validated allowed modules | ||
| * @throws {Error} If configuration is invalid or cannot be loaded | ||
| */ | ||
| loadAllowedModules() { | ||
| try { | ||
| // Get config file path | ||
| let configPath; | ||
| try { | ||
| // Production: Find @chargebee/chargebee-apps-libs package and get config from package root | ||
| const packageJsonPath = require.resolve('@chargebee/chargebee-apps-libs'); | ||
| const packageRoot = path_1.default.dirname(path_1.default.dirname(packageJsonPath)); | ||
| configPath = path_1.default.join(packageRoot, 'config', 'allowed-modules.json'); | ||
| } | ||
| catch (error) { | ||
| chargebee_apps_shared_1.__logger.error('Error: Failed to find allowed modules in the published package', error); | ||
| // Development: Use relative path | ||
| configPath = path_1.default.join(__dirname, '../../config/allowed-modules.json'); | ||
| } | ||
| const config = this.loadConfig(configPath); | ||
| if (!config.modules || !Array.isArray(config.modules)) { | ||
| throw new Error('Invalid allowed modules format: "modules" must be an array'); | ||
| } | ||
| const validatedModules = config.modules.map((module, index) => { | ||
| if (!module.name || typeof module.name !== 'string') { | ||
| throw new Error(`Invalid module at index ${index}: "name" must be a string`); | ||
| } | ||
| if (module.version && typeof module.version !== 'string') { | ||
| throw new Error(`Invalid module "${module.name}": "version" must be a string`); | ||
| } | ||
| if (module.version && !semver_1.default.validRange(module.version)) { | ||
| throw new Error(`Invalid semver range "${module.version}" for module "${module.name}"`); | ||
| } | ||
| return module; | ||
| }); | ||
| chargebee_apps_shared_1.__logger.debug(`Loaded ${validatedModules.length} allowed modules from configuration`); | ||
| return validatedModules; | ||
| } | ||
| catch (error) { | ||
| const err = error; | ||
| chargebee_apps_shared_1.__logger.error('Failed to load allowed-modules.json:', err.message); | ||
| throw err; | ||
| } | ||
| } | ||
| /** | ||
| * Loads a JSON configuration file with caching | ||
| * @param {string} configPath - Path to the configuration file | ||
| * @param {boolean} useCache - Whether to use cached version if available | ||
| * @returns {any} Parsed configuration object | ||
| * @throws {Error} If file cannot be loaded or parsed | ||
| */ | ||
| loadConfig(configPath, useCache = true) { | ||
| const absolutePath = path_1.default.resolve(configPath); | ||
| // Check cache first | ||
| if (useCache && this.cache.has(absolutePath)) { | ||
| return this.cache.get(absolutePath); | ||
| } | ||
| try { | ||
| if (!this.fileSystem.existsSync(absolutePath)) { | ||
| throw new Error(`Configuration file not found: ${absolutePath}`); | ||
| } | ||
| const configContent = this.fileSystem.readFileSync(absolutePath, 'utf8'); | ||
| const config = JSON.parse(configContent); | ||
| // Cache the result | ||
| if (useCache) { | ||
| this.cache.set(absolutePath, config); | ||
| } | ||
| return config; | ||
| } | ||
| catch (error) { | ||
| const err = error; | ||
| throw new Error(`Failed to load configuration from ${absolutePath}: ${err.message}`); | ||
| } | ||
| } | ||
| } | ||
| exports.ConfigLoader = ConfigLoader; | ||
| "use strict";var __importDefault=this&&this.__importDefault||function(n){return n&&n.__esModule?n:{default:n}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConfigLoader=void 0;const chargebee_apps_shared_1=require("@chargebee/chargebee-apps-shared"),path_1=__importDefault(require("path")),semver_1=__importDefault(require("semver"));class ConfigLoader{constructor(o){this.fileSystem=o,this.cache=new Map}loadAllowedModules(){try{let o;try{const e=require.resolve("@chargebee/chargebee-apps-libs"),a=path_1.default.dirname(path_1.default.dirname(e));o=path_1.default.join(a,"config","allowed-modules.json")}catch(e){chargebee_apps_shared_1.__logger.error("Error: Failed to find allowed modules in the published package",e),o=path_1.default.join(__dirname,"../../config/allowed-modules.json")}const t=this.loadConfig(o);if(!t.modules||!Array.isArray(t.modules))throw new Error('Invalid allowed modules format: "modules" must be an array');const r=t.modules.map((e,a)=>{if(!e.name||typeof e.name!="string")throw new Error(`Invalid module at index ${a}: "name" must be a string`);if(e.version&&typeof e.version!="string")throw new Error(`Invalid module "${e.name}": "version" must be a string`);if(e.version&&!semver_1.default.validRange(e.version))throw new Error(`Invalid semver range "${e.version}" for module "${e.name}"`);return e});return chargebee_apps_shared_1.__logger.debug(`Loaded ${r.length} allowed modules from configuration`),r}catch(o){const t=o;throw chargebee_apps_shared_1.__logger.error("Failed to load allowed-modules.json:",t.message),t}}loadConfig(o,t=!0){const r=path_1.default.resolve(o);if(t&&this.cache.has(r))return this.cache.get(r);try{if(!this.fileSystem.existsSync(r))throw new Error(`Configuration file not found: ${r}`);const e=this.fileSystem.readFileSync(r,"utf8"),a=JSON.parse(e);return t&&this.cache.set(r,a),a}catch(e){const a=e;throw new Error(`Failed to load configuration from ${r}: ${a.message}`)}}}exports.ConfigLoader=ConfigLoader; |
+1
-21
@@ -1,21 +0,1 @@ | ||
| "use strict"; | ||
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
| if (k2 === undefined) k2 = k; | ||
| var desc = Object.getOwnPropertyDescriptor(m, k); | ||
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
| desc = { enumerable: true, get: function() { return m[k]; } }; | ||
| } | ||
| Object.defineProperty(o, k2, desc); | ||
| }) : (function(o, m, k, k2) { | ||
| if (k2 === undefined) k2 = k; | ||
| o[k2] = m[k]; | ||
| })); | ||
| var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
| for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| // Export all public library implementations | ||
| __exportStar(require("./config/config-loader"), exports); | ||
| __exportStar(require("./libs/port-service"), exports); | ||
| __exportStar(require("./logger/cb-public-logger"), exports); | ||
| __exportStar(require("./sandbox/public-sandbox-wrapper"), exports); | ||
| "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(i,r,e,t){t===void 0&&(t=e);var n=Object.getOwnPropertyDescriptor(r,e);(!n||("get"in n?!r.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return r[e]}}),Object.defineProperty(i,t,n)}):(function(i,r,e,t){t===void 0&&(t=e),i[t]=r[e]})),__exportStar=this&&this.__exportStar||function(i,r){for(var e in i)e!=="default"&&!Object.prototype.hasOwnProperty.call(r,e)&&__createBinding(r,i,e)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./config/config-loader"),exports),__exportStar(require("./libs/port-service"),exports),__exportStar(require("./logger/cb-public-logger"),exports),__exportStar(require("./sandbox/public-sandbox-wrapper"),exports); |
@@ -1,27 +0,1 @@ | ||
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.PortService = void 0; | ||
| /** | ||
| * Port parsing service | ||
| */ | ||
| class PortService { | ||
| constructor() { } | ||
| /** | ||
| * Validates port number | ||
| * @param {string} port - Port string input | ||
| * @returns {boolean} True if port is valid | ||
| */ | ||
| isValidPort(port) { | ||
| const parsedPort = parseInt(port); | ||
| return !isNaN(parsedPort); | ||
| } | ||
| /** | ||
| * Parses port number from string input | ||
| * @param {string} port - Port string input | ||
| * @returns {number} Parsed port number or default | ||
| */ | ||
| parsePort(port) { | ||
| return parseInt(port); | ||
| } | ||
| } | ||
| exports.PortService = PortService; | ||
| "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.PortService=void 0;class PortService{constructor(){}isValidPort(r){const e=parseInt(r);return!isNaN(e)}parsePort(r){return parseInt(r)}}exports.PortService=PortService; |
@@ -1,158 +0,1 @@ | ||
| "use strict"; | ||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||
| return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.CBPublicLogger = void 0; | ||
| exports.createSafeConsole = createSafeConsole; | ||
| exports.createCBPublicLogger = createCBPublicLogger; | ||
| const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared"); | ||
| const path_1 = __importDefault(require("path")); | ||
| const winston_1 = __importDefault(require("winston")); | ||
| /** | ||
| * Public logger implementation for local development | ||
| * This logger provides controlled logging capabilities for sandboxed code execution | ||
| * with correlation context and formatted output using Winston | ||
| */ | ||
| class CBPublicLogger { | ||
| constructor(fileSystem, process, userCodeDir) { | ||
| this.userCodeDir = userCodeDir || process.cwd(); | ||
| this.fileSystem = fileSystem; | ||
| this.process = process; | ||
| this.logger = this.createWinstonLogger(); | ||
| } | ||
| /** | ||
| * Creates a Winston logger with console and file transports | ||
| * @returns {winston.Logger} Configured Winston logger instance | ||
| */ | ||
| createWinstonLogger() { | ||
| // Get current log level from environment | ||
| const currentLogLevel = this.process.env['CB_LOG_LEVEL'] || chargebee_apps_shared_1.LogLevel.INFO; | ||
| try { | ||
| // Use the user code directory (where the logs should be stored) | ||
| const logsDir = path_1.default.join(this.userCodeDir, 'logs'); | ||
| const logFilePath = path_1.default.join(logsDir, 'cb.log'); | ||
| // Create logs directory if it doesn't exist | ||
| if (!this.fileSystem.existsSync(logsDir)) { | ||
| this.fileSystem.mkdirSync(logsDir, { recursive: true }); | ||
| } | ||
| // Clear the log file on each run by writing an empty string | ||
| this.fileSystem.writeFileSync(logFilePath, ''); | ||
| // Create transports | ||
| const transports = [ | ||
| // Console transport for development output | ||
| new winston_1.default.transports.Console({ | ||
| level: currentLogLevel.toLowerCase(), | ||
| format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.colorize(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.printf((info) => { | ||
| return this.formatMessage(info); | ||
| })) | ||
| }), | ||
| // Single file transport for all logs | ||
| new winston_1.default.transports.File({ | ||
| filename: logFilePath, | ||
| level: currentLogLevel.toLowerCase(), | ||
| format: winston_1.default.format.combine(winston_1.default.format.errors({ stack: true }), winston_1.default.format.printf((info) => { | ||
| return this.formatMessage(info); | ||
| })) | ||
| }) | ||
| ]; | ||
| return winston_1.default.createLogger({ | ||
| level: currentLogLevel.toLowerCase(), | ||
| format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true })), | ||
| transports | ||
| }); | ||
| } | ||
| catch (error) { | ||
| // Fallback to console if Winston initialization fails | ||
| chargebee_apps_shared_1.__logger.error('Failed to initialize Winston logger:', error); | ||
| // Return a minimal logger that just logs to console | ||
| return winston_1.default.createLogger({ | ||
| level: currentLogLevel.toLowerCase(), | ||
| transports: [ | ||
| new winston_1.default.transports.Console({ | ||
| format: winston_1.default.format.simple() | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
| * Logs an info message | ||
| * @param {...any[]} args - The message arguments to log | ||
| */ | ||
| info(...args) { | ||
| this.logger.info(args.join(' ')); | ||
| } | ||
| /** | ||
| * Logs a warning message | ||
| * @param {...any[]} args - The message arguments to log | ||
| */ | ||
| warn(...args) { | ||
| this.logger.warn(args.join(' ')); | ||
| } | ||
| /** | ||
| * Logs an error message | ||
| * @param {...any[]} args - The message arguments to log | ||
| */ | ||
| error(...args) { | ||
| this.logger.error(args.join(' ')); | ||
| } | ||
| /** | ||
| * Logs a debug message | ||
| * @param {...any[]} args - The message arguments to log | ||
| */ | ||
| debug(...args) { | ||
| this.logger.debug(args.join(' ')); | ||
| } | ||
| /** | ||
| * Formats a message with timestamp and level | ||
| * @param {winston.Logform.TransformableInfo} info - The log info | ||
| * @returns {string} The formatted message | ||
| */ | ||
| formatMessage(info) { | ||
| const timestamp = info['timestamp']; | ||
| const level = info.level; | ||
| const message = info.message; | ||
| const context = chargebee_apps_shared_1.sandboxContext.getCurrentContext(); | ||
| const eventId = context?.eventId || 'unknown'; | ||
| const eventType = context?.eventType || 'unknown'; | ||
| return `${timestamp} [${level}] [${eventId}] [${eventType}] ${message}`; | ||
| } | ||
| } | ||
| exports.CBPublicLogger = CBPublicLogger; | ||
| /** | ||
| * Creates a safe console object that uses the logger | ||
| * @param {ICBLogger} logger - The logger instance to use | ||
| * @returns {SafeConsole} A safe console object | ||
| */ | ||
| function createSafeConsole(logger) { | ||
| return Object.freeze({ | ||
| log: (...args) => logger.info(...args), | ||
| info: (...args) => logger.info(...args), | ||
| warn: (...args) => logger.warn(...args), | ||
| error: (...args) => logger.error(...args), | ||
| debug: (...args) => logger.debug(...args), | ||
| // Disable potentially dangerous console methods | ||
| trace: () => { }, | ||
| table: () => { }, | ||
| time: () => { }, | ||
| timeEnd: () => { }, | ||
| timeLog: () => { }, | ||
| count: () => { }, | ||
| countReset: () => { }, | ||
| group: () => { }, | ||
| groupCollapsed: () => { }, | ||
| groupEnd: () => { }, | ||
| clear: () => { } | ||
| }); | ||
| } | ||
| /** | ||
| * Creates a new CBPublicLogger instance for a specific user code directory | ||
| * @param {CBFileSystem} fileSystem - The filesystem implementation to use | ||
| * @param {CBProcess} process - The process implementation to use | ||
| * @param {string} userCodeDir - The user code directory where logs should be stored | ||
| * @returns {CBPublicLogger} A new CBPublicLogger instance | ||
| */ | ||
| function createCBPublicLogger(fileSystem, process, userCodeDir) { | ||
| return new CBPublicLogger(fileSystem, process, userCodeDir); | ||
| } | ||
| "use strict";var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.CBPublicLogger=void 0,exports.createSafeConsole=createSafeConsole,exports.createCBPublicLogger=createCBPublicLogger;const chargebee_apps_shared_1=require("@chargebee/chargebee-apps-shared"),path_1=__importDefault(require("path")),winston_1=__importDefault(require("winston"));class CBPublicLogger{constructor(e,r,o){this.userCodeDir=o||r.cwd(),this.fileSystem=e,this.process=r,this.logger=this.createWinstonLogger()}createWinstonLogger(){const e=this.process.env.CB_LOG_LEVEL||chargebee_apps_shared_1.LogLevel.INFO;try{const r=path_1.default.join(this.userCodeDir,"logs"),o=path_1.default.join(r,"cb.log");this.fileSystem.existsSync(r)||this.fileSystem.mkdirSync(r,{recursive:!0}),this.fileSystem.writeFileSync(o,"");const a=[new winston_1.default.transports.Console({level:e.toLowerCase(),format:winston_1.default.format.combine(winston_1.default.format.timestamp(),winston_1.default.format.colorize(),winston_1.default.format.errors({stack:!0}),winston_1.default.format.printf(s=>this.formatMessage(s)))}),new winston_1.default.transports.File({filename:o,level:e.toLowerCase(),format:winston_1.default.format.combine(winston_1.default.format.errors({stack:!0}),winston_1.default.format.printf(s=>this.formatMessage(s)))})];return winston_1.default.createLogger({level:e.toLowerCase(),format:winston_1.default.format.combine(winston_1.default.format.timestamp(),winston_1.default.format.errors({stack:!0})),transports:a})}catch(r){return chargebee_apps_shared_1.__logger.error("Failed to initialize Winston logger:",r),winston_1.default.createLogger({level:e.toLowerCase(),transports:[new winston_1.default.transports.Console({format:winston_1.default.format.simple()})]})}}info(...e){this.logger.info(e.join(" "))}warn(...e){this.logger.warn(e.join(" "))}error(...e){this.logger.error(e.join(" "))}debug(...e){this.logger.debug(e.join(" "))}formatMessage(e){const r=e.timestamp,o=e.level,a=e.message,s=chargebee_apps_shared_1.sandboxContext.getCurrentContext(),n=s?.eventId||"unknown",i=s?.eventType||"unknown";return`${r} [${o}] [${n}] [${i}] ${a}`}}exports.CBPublicLogger=CBPublicLogger;function createSafeConsole(t){return Object.freeze({log:(...e)=>t.info(...e),info:(...e)=>t.info(...e),warn:(...e)=>t.warn(...e),error:(...e)=>t.error(...e),debug:(...e)=>t.debug(...e),trace:()=>{},table:()=>{},time:()=>{},timeEnd:()=>{},timeLog:()=>{},count:()=>{},countReset:()=>{},group:()=>{},groupCollapsed:()=>{},groupEnd:()=>{},clear:()=>{}})}function createCBPublicLogger(t,e,r){return new CBPublicLogger(t,e,r)} |
@@ -1,183 +0,9 @@ | ||
| "use strict"; | ||
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
| if (k2 === undefined) k2 = k; | ||
| var desc = Object.getOwnPropertyDescriptor(m, k); | ||
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
| desc = { enumerable: true, get: function() { return m[k]; } }; | ||
| } | ||
| Object.defineProperty(o, k2, desc); | ||
| }) : (function(o, m, k, k2) { | ||
| if (k2 === undefined) k2 = k; | ||
| o[k2] = m[k]; | ||
| })); | ||
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
| Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
| }) : function(o, v) { | ||
| o["default"] = v; | ||
| }); | ||
| var __importStar = (this && this.__importStar) || (function () { | ||
| var ownKeys = function(o) { | ||
| ownKeys = Object.getOwnPropertyNames || function (o) { | ||
| var ar = []; | ||
| for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; | ||
| return ar; | ||
| }; | ||
| return ownKeys(o); | ||
| }; | ||
| return function (mod) { | ||
| if (mod && mod.__esModule) return mod; | ||
| var result = {}; | ||
| if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); | ||
| __setModuleDefault(result, mod); | ||
| return result; | ||
| }; | ||
| })(); | ||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||
| return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.PublicSandboxWrapper = void 0; | ||
| const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared"); | ||
| const path_1 = __importDefault(require("path")); | ||
| const vm_1 = __importDefault(require("vm")); | ||
| const dotenv = __importStar(require("dotenv")); | ||
| const cb_public_logger_1 = require("../logger/cb-public-logger"); | ||
| /** | ||
| * PublicSandboxWrapper provides a secure environment for executing user-provided NodeJS code | ||
| * Public implementation for local development environment | ||
| */ | ||
| class PublicSandboxWrapper { | ||
| constructor(allowedModules, fileSystem, packageValidator, dependencyManager, manifestValidator) { | ||
| this.fileSystem = fileSystem; | ||
| this.packageValidator = packageValidator; | ||
| this.dependencyManager = dependencyManager; | ||
| this.allowedModules = allowedModules; | ||
| this.manifestValidator = manifestValidator; | ||
| } | ||
| /** | ||
| * Creates a safe require function that uses isolated node_modules | ||
| * @param {string} projectPath - Path to the user project | ||
| * @returns {Function} Safe require function | ||
| */ | ||
| createSafeRequire(projectPath) { | ||
| return this.dependencyManager.createIsolatedRequire(projectPath, this.allowedModules); | ||
| } | ||
| /** | ||
| * Loads environment variables from .env file in the project directory | ||
| * @param {string} projectPath - Path to the user project | ||
| * @returns {Record<string, string>} Environment variables object | ||
| */ | ||
| loadEnvironmentVariables(projectPath) { | ||
| const envPath = path_1.default.join(projectPath, '.env'); | ||
| const envVars = {}; | ||
| try { | ||
| // Load .env file if it exists | ||
| const result = dotenv.config({ path: envPath }); | ||
| if (result.parsed) { | ||
| // Only include MKPLC_CB_READ_ONLY_API and MKPLC_CB_READ_WRITE_API keys | ||
| if (result.parsed['MKPLC_CB_READ_ONLY_API']) { | ||
| envVars['MKPLC_CB_READ_ONLY_API'] = result.parsed['MKPLC_CB_READ_ONLY_API']; | ||
| } | ||
| if (result.parsed['MKPLC_CB_READ_WRITE_API']) { | ||
| envVars['MKPLC_CB_READ_WRITE_API'] = result.parsed['MKPLC_CB_READ_WRITE_API']; | ||
| } | ||
| if (result.parsed['MKPLC_SITE_DOMAIN']) { | ||
| envVars['MKPLC_SITE_DOMAIN'] = result.parsed['MKPLC_SITE_DOMAIN']; | ||
| } | ||
| else { | ||
| envVars['MKPLC_SITE_DOMAIN'] = ''; | ||
| } | ||
| } | ||
| } | ||
| catch (error) { | ||
| chargebee_apps_shared_1.__logger.debug(`Failed to load .env file from ${envPath}: ${error}`); | ||
| } | ||
| return envVars; | ||
| } | ||
| /** | ||
| * Creates a secure sandbox environment for code execution | ||
| * @param {string} projectPath - Path to the user project | ||
| * @param {HandlerPayload} payload - Handler payload (event + iparams) to expose to user code | ||
| * @param {ICBLogger} sessionLogger - Logger instance for this server session | ||
| * @returns {SandboxEnvironment} The sandbox environment object | ||
| */ | ||
| createSandbox(projectPath, payload, sessionLogger) { | ||
| const moduleObj = { exports: {} }; | ||
| const exportsObj = moduleObj.exports; | ||
| // Load environment variables from .env file | ||
| const envVars = this.loadEnvironmentVariables(projectPath); | ||
| const hasIparams = Object.prototype.hasOwnProperty.call(payload, 'iparams'); | ||
| const safePayload = Object.freeze(hasIparams | ||
| ? { event: payload.event, iparams: payload.iparams ?? {} } | ||
| : { event: payload.event }); | ||
| return { | ||
| // Controlled logging | ||
| console: (0, cb_public_logger_1.createSafeConsole)(sessionLogger), | ||
| // Read-only payload (event + iparams) for handler(payload) | ||
| payload: safePayload, | ||
| // Safe async primitives | ||
| setTimeout, | ||
| clearTimeout, | ||
| setImmediate, | ||
| clearImmediate, | ||
| // CommonJS emulation | ||
| module: moduleObj, | ||
| exports: exportsObj, | ||
| // Controlled module access | ||
| require: this.createSafeRequire(projectPath), | ||
| // Limited process access | ||
| process: { | ||
| cwd: () => process.cwd(), | ||
| env: envVars, | ||
| nextTick: process.nextTick | ||
| }, | ||
| // Prevent escape hatches | ||
| global: undefined, | ||
| Buffer: undefined, | ||
| __dirname: undefined, | ||
| __filename: undefined | ||
| }; | ||
| } | ||
| /** | ||
| * Executes user-provided code in a secure sandbox environment. | ||
| * @param userCodePath - Path to the directory containing user code | ||
| * @param payload - Handler payload (event + iparams) to pass to the user handler | ||
| * @param sessionLogger - The logger instance for this server session | ||
| * @returns {Promise<ExecutionResult>} Execution result with success status and data/error | ||
| */ | ||
| async execute(userCodePath, payload, sessionLogger) { | ||
| try { | ||
| chargebee_apps_shared_1.__logger.debug(`Executing user code from: ${userCodePath}`); | ||
| // Check if required files exist. | ||
| this.packageValidator.validateHandlerExists(userCodePath); | ||
| this.packageValidator.validateManifestExists(userCodePath); | ||
| // Validate manifest file. | ||
| const manifestPath = path_1.default.join(userCodePath, 'manifest.json'); | ||
| const manifest = this.manifestValidator.validateAndGetManifestFile(manifestPath); | ||
| // Load user code | ||
| const eventType = payload.event.event_type; | ||
| const eventConfig = manifest.events[eventType]; | ||
| if (!eventConfig) { | ||
| throw new Error(`No handler configured for event type: ${eventType}`); | ||
| } | ||
| const handler = eventConfig.handler; | ||
| const handlerPath = path_1.default.join(userCodePath, 'handler', 'handler.js'); | ||
| const userCode = this.fileSystem.readFileSync(handlerPath, 'utf8'); | ||
| // Create execution context | ||
| const contextData = { | ||
| eventId: payload.event.id || 'unknown', | ||
| eventType: payload.event.event_type || 'unknown', | ||
| }; | ||
| return await chargebee_apps_shared_1.sandboxContext.run(contextData, async () => { | ||
| const sandbox = this.createSandbox(userCodePath, payload, sessionLogger); | ||
| const vmContext = vm_1.default.createContext(sandbox); | ||
| // Execute user code and run handler with single payload argument | ||
| const executeCode = ` | ||
| "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(a,e,r,n){n===void 0&&(n=r);var t=Object.getOwnPropertyDescriptor(e,r);(!t||("get"in t?!e.__esModule:t.writable||t.configurable))&&(t={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(a,n,t)}):(function(a,e,r,n){n===void 0&&(n=r),a[n]=e[r]})),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(a,e){Object.defineProperty(a,"default",{enumerable:!0,value:e})}):function(a,e){a.default=e}),__importStar=this&&this.__importStar||(function(){var a=function(e){return a=Object.getOwnPropertyNames||function(r){var n=[];for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(n[n.length]=t);return n},a(e)};return function(e){if(e&&e.__esModule)return e;var r={};if(e!=null)for(var n=a(e),t=0;t<n.length;t++)n[t]!=="default"&&__createBinding(r,e,n[t]);return __setModuleDefault(r,e),r}})(),__importDefault=this&&this.__importDefault||function(a){return a&&a.__esModule?a:{default:a}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PublicSandboxWrapper=void 0;const chargebee_apps_shared_1=require("@chargebee/chargebee-apps-shared"),path_1=__importDefault(require("path")),vm_1=__importDefault(require("vm")),dotenv=__importStar(require("dotenv")),cb_public_logger_1=require("../logger/cb-public-logger");class PublicSandboxWrapper{constructor(e,r,n,t,s){this.fileSystem=r,this.packageValidator=n,this.dependencyManager=t,this.allowedModules=e,this.manifestValidator=s}createSafeRequire(e){return this.dependencyManager.createIsolatedRequire(e,this.allowedModules)}loadEnvironmentVariables(e){const r=path_1.default.join(e,".env"),n={};try{const t=dotenv.config({path:r});t.parsed&&(t.parsed.MKPLC_CB_READ_ONLY_API&&(n.MKPLC_CB_READ_ONLY_API=t.parsed.MKPLC_CB_READ_ONLY_API),t.parsed.MKPLC_CB_READ_WRITE_API&&(n.MKPLC_CB_READ_WRITE_API=t.parsed.MKPLC_CB_READ_WRITE_API),t.parsed.MKPLC_SITE_DOMAIN?n.MKPLC_SITE_DOMAIN=t.parsed.MKPLC_SITE_DOMAIN:n.MKPLC_SITE_DOMAIN="")}catch(t){chargebee_apps_shared_1.__logger.debug(`Failed to load .env file from ${r}: ${t}`)}return n}createSandbox(e,r,n){const t={exports:{}},s=t.exports,o=this.loadEnvironmentVariables(e),i=Object.prototype.hasOwnProperty.call(r,"iparams"),c=Object.freeze(i?{event:r.event,iparams:r.iparams??{}}:{event:r.event});return{console:(0,cb_public_logger_1.createSafeConsole)(n),payload:c,setTimeout,clearTimeout,setImmediate,clearImmediate,module:t,exports:s,require:this.createSafeRequire(e),process:{cwd:()=>process.cwd(),env:o,nextTick:process.nextTick},global:void 0,Buffer:void 0,__dirname:void 0,__filename:void 0}}async execute(e,r,n){try{chargebee_apps_shared_1.__logger.debug(`Executing user code from: ${e}`),this.packageValidator.validateHandlerExists(e),this.packageValidator.validateManifestExists(e);const t=path_1.default.join(e,"manifest.json"),s=this.manifestValidator.validateAndGetManifestFile(t),o=r.event.event_type,i=s.events[o];if(!i)throw new Error(`No handler configured for event type: ${o}`);const c=i.handler,u=path_1.default.join(e,"handler","handler.js"),l=this.fileSystem.readFileSync(u,"utf8"),d={eventId:r.event.id||"unknown",eventType:r.event.event_type||"unknown"};return await chargebee_apps_shared_1.sandboxContext.run(d,async()=>{const f=this.createSandbox(e,r,n),_=vm_1.default.createContext(f),p=` | ||
| (async function() { | ||
| "use strict"; | ||
| try { | ||
| ${userCode} | ||
| const handler = module.exports["${handler}"]; | ||
| ${l} | ||
| const handler = module.exports["${c}"]; | ||
| if (typeof handler !== 'function') { | ||
| throw new Error('Handler function "${handler}" not found in handler.js'); | ||
| throw new Error('Handler function "${c}" not found in handler.js'); | ||
| } | ||
@@ -190,20 +16,2 @@ return await handler(payload); | ||
| })() | ||
| `; | ||
| await vm_1.default.runInContext(executeCode, vmContext, { | ||
| timeout: 15000, // 15 second timeout | ||
| displayErrors: true | ||
| }); | ||
| return { success: true, statusCode: 200 }; | ||
| }); | ||
| } | ||
| catch (error) { | ||
| const err = error; | ||
| return { | ||
| success: false, | ||
| error: `${err.message}`, | ||
| stack: err.stack || undefined | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| exports.PublicSandboxWrapper = PublicSandboxWrapper; | ||
| `;return await vm_1.default.runInContext(p,_,{timeout:15e3,displayErrors:!0}),{success:!0,statusCode:200}})}catch(t){const s=t;return{success:!1,error:`${s.message}`,stack:s.stack||void 0}}}}exports.PublicSandboxWrapper=PublicSandboxWrapper; |
+2
-2
| { | ||
| "name": "@chargebee/chargebee-apps-libs", | ||
| "version": "0.0.1", | ||
| "version": "0.0.3", | ||
| "description": "Public library implementations for Chargebee Apps CLI", | ||
@@ -25,3 +25,3 @@ "main": "dist/index.js", | ||
| "dependencies": { | ||
| "@chargebee/chargebee-apps-shared": "0.0.1", | ||
| "@chargebee/chargebee-apps-shared": "0.0.3", | ||
| "dotenv": "^16.3.1" | ||
@@ -28,0 +28,0 @@ }, |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
173486
-6.5%3222
-12.42%6
200%+ Added
- Removed