@chargebee/chargebee-apps 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,339 @@
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.setupServer = setupServer;
7
+ exports.invokeEventHandler = invokeEventHandler;
8
+ exports.setupApiRoutes = setupApiRoutes;
9
+ exports.setupAppRoutes = setupAppRoutes;
10
+ const chargebee_apps_libs_1 = require("@chargebee/chargebee-apps-libs");
11
+ const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared");
12
+ const express_1 = __importDefault(require("express"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const registry_1 = require("../registry");
15
+ const iparams_routes_1 = require("./iparams.routes");
16
+ // Create a singleton instance of PathResolver
17
+ const pathResolver = new chargebee_apps_shared_1.PathResolver();
18
+ // Get UI directory paths using centralized path resolver
19
+ const WEB_STATIC_DIR = pathResolver.getPublicLibsUiWebDir();
20
+ // Configurable path variables
21
+ const PATHS = {
22
+ WEB_STATIC_DIR,
23
+ MAIN_HTML_FILE: 'index.html',
24
+ HANDLER_FILE: 'handler/handler.js',
25
+ MANIFEST_FILE: 'manifest.json',
26
+ TEST_DATA_DIR: 'test_data',
27
+ };
28
+ const REGISTRY = registry_1.PublicCliRegistry.getInstance();
29
+ const __logger = REGISTRY.logger;
30
+ /**
31
+ * Sets up and start an Express server for the serverless app tester
32
+ * @param {number} port - The port number to run the server on
33
+ * @param {string} userCodeDir - The user code directory where logs should be stored
34
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
35
+ * @param {CBProcess} processService - The process implementation to use
36
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
37
+ */
38
+ function setupServer(port, userCodeDir, fileSystem = REGISTRY.fileSystem, processService = REGISTRY.process, dependencyManager = REGISTRY.dependencyManager) {
39
+ const app = (0, express_1.default)();
40
+ app.disable('x-powered-by');
41
+ // Create a single CBLogger instance for the entire server session
42
+ const sessionLogger = (0, chargebee_apps_libs_1.createCBPublicLogger)(fileSystem, processService, userCodeDir);
43
+ // CORS middleware
44
+ app.use((_req, res, next) => {
45
+ res.header('Access-Control-Allow-Origin', '*');
46
+ res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
47
+ res.header('Access-Control-Allow-Headers', 'Content-Type');
48
+ next();
49
+ });
50
+ // JSON parsing
51
+ app.use(express_1.default.json());
52
+ // Static files
53
+ app.use(express_1.default.static(PATHS.WEB_STATIC_DIR));
54
+ // API Routes
55
+ setupApiRoutes(app, sessionLogger, userCodeDir, fileSystem, processService, dependencyManager);
56
+ // Iparams Routes
57
+ (0, iparams_routes_1.setupIparamsRoutes)(app, userCodeDir, fileSystem);
58
+ // App Routes
59
+ setupAppRoutes(app, fileSystem);
60
+ // Start server
61
+ const server = app.listen(port, () => {
62
+ __logger.info(`Server is running on \x1b[4mhttp://localhost:${port}\x1b[0m`);
63
+ });
64
+ // Graceful shutdown
65
+ processService.on('SIGINT', () => {
66
+ __logger.info('Shutting down server...');
67
+ server.close(() => {
68
+ __logger.info('Server stopped!');
69
+ processService.exit(0);
70
+ });
71
+ });
72
+ processService.on('uncaughtException', async (err) => {
73
+ __logger.error(`Uncaught exception thrown: ${err.message}`);
74
+ if (err && err.stack) {
75
+ __logger.error(`Stack Trace: ${err.stack}`);
76
+ }
77
+ processService.exit(1);
78
+ });
79
+ // Handle server errors
80
+ server.on('error', (error) => {
81
+ if (error.code === 'EADDRINUSE') {
82
+ __logger.error(`Port ${port} is already in use. Try a different port with --port option.`);
83
+ }
84
+ else {
85
+ __logger.error('Server error:', error);
86
+ }
87
+ processService.exit(1);
88
+ });
89
+ return server;
90
+ }
91
+ /**
92
+ * Invokes an event handler based on the event data
93
+ * @param {EventRecord} eventData - The event data containing event_type and payload
94
+ * @param {ICBLogger} sessionLogger - The logger instance for this server session
95
+ * @param {string} userCodeDir - The user code directory
96
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
97
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
98
+ * @returns {Promise<any>} The result from the handler function
99
+ * @throws {Error} If handler file, manifest, or handler function is not found
100
+ */
101
+ async function invokeEventHandler(eventData, sessionLogger, userCodeDir, fileSystem, dependencyManager) {
102
+ const iparamsService = new chargebee_apps_shared_1.IparamsService(fileSystem);
103
+ const hasIparamsFile = iparamsService.iparamsFileExists(userCodeDir);
104
+ let iparams;
105
+ if (hasIparamsFile) {
106
+ try {
107
+ iparams = iparamsService.validateAndGetInputsForExecution(userCodeDir);
108
+ }
109
+ catch (error) {
110
+ if (error instanceof chargebee_apps_shared_1.MissingRequiredParamsError) {
111
+ throw error;
112
+ }
113
+ const err = error;
114
+ return {
115
+ success: false,
116
+ error: `Parameters validation failed: ${err.message}`,
117
+ stack: err.stack
118
+ };
119
+ }
120
+ }
121
+ const configLoader = new chargebee_apps_libs_1.ConfigLoader(fileSystem);
122
+ const allowedModules = configLoader.loadAllowedModules();
123
+ const packageValidator = new chargebee_apps_shared_1.PackageValidator(fileSystem);
124
+ const manifestValidator = new chargebee_apps_shared_1.ManifestValidator(allowedModules, fileSystem);
125
+ const sandbox = new chargebee_apps_libs_1.PublicSandboxWrapper(allowedModules, fileSystem, packageValidator, dependencyManager, manifestValidator);
126
+ const payload = hasIparamsFile
127
+ ? { event: eventData, iparams: iparams ?? {} }
128
+ : { event: eventData };
129
+ return await sandbox.execute(userCodeDir, payload, sessionLogger);
130
+ }
131
+ /**
132
+ * Sets up all API routes for the serverless app tester
133
+ * @param {Application} app - Express application instance
134
+ * @param {ICBLogger} sessionLogger - The logger instance for this server session
135
+ * @param {string} userCodeDir - The user code directory
136
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
137
+ * @param {CBProcess} process - The process implementation to use
138
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
139
+ */
140
+ function setupApiRoutes(app, sessionLogger, userCodeDir, fileSystem, process, dependencyManager) {
141
+ // Get list of available test data files
142
+ app.get('/api/manifest', (_req, res, next) => {
143
+ const testDataDir = path_1.default.join(process.cwd(), PATHS.TEST_DATA_DIR);
144
+ const manifestPath = path_1.default.join(process.cwd(), PATHS.MANIFEST_FILE);
145
+ const handlerPath = path_1.default.join(process.cwd(), PATHS.HANDLER_FILE);
146
+ try {
147
+ // Check if manifest.json exists
148
+ const configLoader = new chargebee_apps_libs_1.ConfigLoader(fileSystem);
149
+ const allowedModules = configLoader.loadAllowedModules();
150
+ const manifestValidator = new chargebee_apps_shared_1.ManifestValidator(allowedModules, fileSystem);
151
+ const manifestData = manifestValidator.validateAndGetManifestFile(manifestPath);
152
+ // Load manifest to get configured events
153
+ const configuredEvents = Object.keys(manifestData.events || {});
154
+ // Check if handler.js exists
155
+ const handlerExists = fileSystem.existsSync(handlerPath);
156
+ // Check if test data directory exists
157
+ const testDataExists = fileSystem.existsSync(testDataDir);
158
+ let testDataFiles = [];
159
+ if (testDataExists) {
160
+ testDataFiles = fileSystem.readdirSync(testDataDir)
161
+ .filter((file) => file.endsWith('.json'))
162
+ .map((file) => file.replace('.json', ''));
163
+ }
164
+ // Analyze each configured event
165
+ const events = configuredEvents.map(eventType => {
166
+ const eventConfig = manifestData.events[eventType];
167
+ const handlerName = eventConfig ? eventConfig.handler : null;
168
+ const hasTestData = testDataFiles.includes(eventType);
169
+ // Check if handler function exists in handler.js
170
+ let hasHandlerFunction = false;
171
+ if (handlerExists && handlerName) {
172
+ try {
173
+ delete require.cache[require.resolve(handlerPath)];
174
+ const handlerModule = require(handlerPath);
175
+ hasHandlerFunction = typeof handlerModule[handlerName] === 'function';
176
+ }
177
+ catch (error) {
178
+ __logger.error(`Error checking handler function ${handlerName}:`, error.message);
179
+ hasHandlerFunction = false;
180
+ }
181
+ }
182
+ else {
183
+ __logger.info(`Handler check skipped for ${eventType}: handlerExists=${handlerExists}, handlerName=${handlerName}`);
184
+ }
185
+ return {
186
+ event_type: eventType,
187
+ handler: {
188
+ name: handlerName,
189
+ exists: hasHandlerFunction,
190
+ },
191
+ has_test_data: hasTestData,
192
+ };
193
+ });
194
+ // Return all configured events with their status
195
+ const response = {
196
+ events: events,
197
+ dependencies: manifestData.dependencies || {}
198
+ };
199
+ res.json(response);
200
+ }
201
+ catch (error) {
202
+ __logger.error('Error: Failed to get manifest', error);
203
+ if (error instanceof Error && error.message && error.message.includes('manifest.json not found')) {
204
+ __logger.error(`Manifest file not found: ${manifestPath}`);
205
+ res.status(404).json({
206
+ error: 'Manifest file not found',
207
+ message: error.message
208
+ });
209
+ }
210
+ else {
211
+ res.status(500).json({
212
+ error: 'Internal server error',
213
+ message: error instanceof Error && error.message ? error.message : error
214
+ });
215
+ }
216
+ next(error);
217
+ res.status(500).json({ error: 'Failed to read test data directory' });
218
+ }
219
+ });
220
+ // Get specific test data file
221
+ app.get('/api/test-data/:eventType', (req, res) => {
222
+ const { eventType } = req.params;
223
+ if (!eventType) {
224
+ res.status(400).json({ error: 'Event type is required' });
225
+ return;
226
+ }
227
+ const sanitizedEventType = path_1.default.basename(eventType);
228
+ // Validate: ensure eventType doesn't contain path separators
229
+ if (sanitizedEventType !== eventType || /[\/\\]/.test(eventType)) {
230
+ res.status(400).json({
231
+ error: 'Invalid event type',
232
+ message: 'Event type must not contain path separators'
233
+ });
234
+ return;
235
+ }
236
+ // Construct paths
237
+ const testDataDir = path_1.default.resolve(process.cwd(), PATHS.TEST_DATA_DIR);
238
+ const testDataFile = path_1.default.resolve(testDataDir, `${sanitizedEventType}.json`);
239
+ // Security check: Verify the resolved path is within the test_data directory
240
+ if (!testDataFile.startsWith(testDataDir + path_1.default.sep)) {
241
+ res.status(400).json({
242
+ error: 'Invalid event type',
243
+ message: 'Access denied'
244
+ });
245
+ return;
246
+ }
247
+ try {
248
+ if (fileSystem.existsSync(testDataFile)) {
249
+ const data = fileSystem.readFileSync(testDataFile, 'utf8');
250
+ res.json(JSON.parse(data));
251
+ }
252
+ else {
253
+ res.status(404).json({
254
+ error: `Test data for event '${sanitizedEventType}' not found`,
255
+ path: testDataFile,
256
+ message: 'Check if the test_data directory exists in your app directory'
257
+ });
258
+ }
259
+ }
260
+ catch (error) {
261
+ res.status(500).json({ error: 'Failed to read test data file' });
262
+ }
263
+ });
264
+ // Invoke serverless function
265
+ app.post('/api/invoke', async (req, res) => {
266
+ try {
267
+ const eventData = req.body;
268
+ const result = await invokeEventHandler(eventData, sessionLogger, userCodeDir, fileSystem, dependencyManager);
269
+ if (result.success) {
270
+ return res.json({ status: 'success' });
271
+ }
272
+ __logger.error(`✗ Handler execution failed: ${result.error}`);
273
+ return res.status(500).json({ error: 'Uncaught exception thrown while invoking function', message: result.error, stack: result.stack });
274
+ }
275
+ catch (error) {
276
+ if (error instanceof chargebee_apps_shared_1.MissingRequiredParamsError) {
277
+ const paramText = error.missing.length > 1 ? 'parameters' : 'parameter';
278
+ __logger.error(`✗ Missing required ${paramText}: ${error.missing.join(', ')}. Please provide values for these parameters in iparams.local.json`);
279
+ return res.status(400).json({
280
+ error: 'Parameters validation failed',
281
+ message: error.message,
282
+ missingParams: error.missing,
283
+ showPopup: true
284
+ });
285
+ }
286
+ __logger.error('Error: Failed to invoke event handler', error);
287
+ const errMsg = error instanceof Error ? error.message : '';
288
+ const errorMap = {
289
+ 'Handler function': { status: 400, error: 'Handler function not found' },
290
+ 'No handler configured': { status: 400, error: 'No handler configured' },
291
+ 'handler.js not found': { status: 404, error: 'Handler file not found' },
292
+ 'manifest.json not found': { status: 404, error: 'Manifest file not found' }
293
+ };
294
+ for (const [key, { status, error: errorMsg }] of Object.entries(errorMap)) {
295
+ if (errMsg.includes(key)) {
296
+ return res.status(status).json({ error: errorMsg, message: errMsg });
297
+ }
298
+ }
299
+ return res.status(500).json({
300
+ error: 'Internal server error',
301
+ message: errMsg || error
302
+ });
303
+ }
304
+ });
305
+ // Handle 404 for API routes
306
+ app.all('/api', (_req, res) => {
307
+ __logger.info('API endpoint not found');
308
+ res.status(404).json({ error: 'API endpoint not found' });
309
+ });
310
+ }
311
+ /**
312
+ * Sets up application routes for serving the web UI
313
+ * @param {Application} app - Express application instance
314
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
315
+ */
316
+ function setupAppRoutes(app, fileSystem) {
317
+ // Serve index.html for all other routes (SPA support)
318
+ app.get('/', (_req, res) => {
319
+ const indexPath = path_1.default.join(PATHS.WEB_STATIC_DIR, PATHS.MAIN_HTML_FILE);
320
+ if (fileSystem.existsSync(indexPath)) {
321
+ res.sendFile(indexPath);
322
+ }
323
+ else {
324
+ res.status(404).send('Web UI not found. Please check the file path.');
325
+ }
326
+ });
327
+ // Error handling middleware
328
+ app.use((error, _req, res, _next) => {
329
+ // Only log and respond if headers haven't been sent yet
330
+ if (!res.headersSent) {
331
+ __logger.error('Error: Failed to handle middleware', error);
332
+ res.status(500).json({
333
+ error: 'Internal server error',
334
+ message: error.message
335
+ });
336
+ }
337
+ // If headers already sent, error was already handled - don't log again
338
+ });
339
+ }
@@ -0,0 +1,30 @@
1
+ import { CBFileSystem, CBProcess, CreateOptions } from '@chargebee/chargebee-apps-shared';
2
+ /**
3
+ * Main create command class
4
+ */
5
+ export declare class CreateCommand {
6
+ private templateService;
7
+ private fileSystem;
8
+ private process;
9
+ constructor(fileSystem?: CBFileSystem, process?: CBProcess);
10
+ /**
11
+ * Creates a new serverless application from a template
12
+ * @param {CreateOptions} options - The options for the create command
13
+ * @param {string} appDir - The directory where the app will be created
14
+ */
15
+ execute(options: CreateOptions, appDir: string): void;
16
+ /**
17
+ * Validates the app directory
18
+ * @param targetDir - The directory where the app will be created
19
+ * @param appDir - The original app directory argument
20
+ * @param template - The template name to use for scaffolding
21
+ */
22
+ private validate;
23
+ /**
24
+ * Creates a new serverless application from a template
25
+ * @param targetDir - The directory where the app will be created
26
+ * @param template - The template name to use for scaffolding
27
+ */
28
+ private createProject;
29
+ }
30
+ export declare const createCommand: CreateCommand;
@@ -0,0 +1,102 @@
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.createCommand = exports.CreateCommand = void 0;
7
+ const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared");
8
+ const path_1 = __importDefault(require("path"));
9
+ const registry_1 = require("../registry");
10
+ // Create a singleton instance of PathResolver
11
+ const pathResolver = new chargebee_apps_shared_1.PathResolver();
12
+ /**
13
+ * Main create command class
14
+ */
15
+ class CreateCommand {
16
+ constructor(fileSystem, process) {
17
+ const registry = registry_1.PublicCliRegistry.getInstance();
18
+ this.fileSystem = fileSystem || registry.fileSystem;
19
+ this.process = process || registry.process;
20
+ // Get templates directory path using centralized path resolver
21
+ const templatesPath = pathResolver.getPublicLibsTemplatesDir();
22
+ this.templateService = new chargebee_apps_shared_1.TemplateService(this.fileSystem, templatesPath);
23
+ }
24
+ /**
25
+ * Creates a new serverless application from a template
26
+ * @param {CreateOptions} options - The options for the create command
27
+ * @param {string} appDir - The directory where the app will be created
28
+ */
29
+ execute(options, appDir) {
30
+ const template = options.template;
31
+ chargebee_apps_shared_1.__logger.info('Creating new application...');
32
+ const targetDir = path_1.default.resolve(appDir);
33
+ // Validate app directory
34
+ this.validate(targetDir, appDir, template);
35
+ // Create project
36
+ this.createProject(targetDir, template);
37
+ }
38
+ /**
39
+ * Validates the app directory
40
+ * @param targetDir - The directory where the app will be created
41
+ * @param appDir - The original app directory argument
42
+ * @param template - The template name to use for scaffolding
43
+ */
44
+ validate(targetDir, appDir, template) {
45
+ const defaultTemplate = 'serverless-node-starter-app';
46
+ // Show which template is being used
47
+ if (template === defaultTemplate) {
48
+ chargebee_apps_shared_1.__logger.info(`Using default template: ${template}`);
49
+ }
50
+ else {
51
+ chargebee_apps_shared_1.__logger.info(`Using template: ${template}`);
52
+ }
53
+ // Validate template
54
+ if (!this.templateService.validateTemplate(template)) {
55
+ const availableTemplates = this.templateService.getAvailableTemplates();
56
+ chargebee_apps_shared_1.__logger.error(`Error: Template '${template}' not found.`);
57
+ chargebee_apps_shared_1.__logger.error(`Available templates: ${availableTemplates.join(', ')}`);
58
+ this.process.exit(1);
59
+ }
60
+ // Validate app directory
61
+ try {
62
+ const conflicts = this.templateService.validateAppDirectory(targetDir, appDir, template);
63
+ if (conflicts.length > 0) {
64
+ chargebee_apps_shared_1.__logger.error(`Error: The following files already exist in the current directory:`);
65
+ conflicts.forEach(file => chargebee_apps_shared_1.__logger.error(` - ${file}`));
66
+ chargebee_apps_shared_1.__logger.error(`Please remove these files or use a different directory.`);
67
+ this.process.exit(1);
68
+ }
69
+ }
70
+ catch (error) {
71
+ chargebee_apps_shared_1.__logger.error(`Error: ${error.message}`);
72
+ chargebee_apps_shared_1.__logger.error(`Use a different directory name or clear the existing directory first.`);
73
+ this.process.exit(1);
74
+ }
75
+ }
76
+ /**
77
+ * Creates a new serverless application from a template
78
+ * @param targetDir - The directory where the app will be created
79
+ * @param template - The template name to use for scaffolding
80
+ */
81
+ createProject(targetDir, template) {
82
+ try {
83
+ if (!this.fileSystem.existsSync(targetDir)) {
84
+ this.fileSystem.mkdirSync(targetDir, { recursive: true });
85
+ }
86
+ // Copy template files
87
+ const templatePath = this.templateService.getTemplatePath(template);
88
+ this.templateService.copyTemplateFiles(templatePath, targetDir);
89
+ chargebee_apps_shared_1.__logger.success(`Successfully created app in '${targetDir}' using template '${template}'`);
90
+ chargebee_apps_shared_1.__logger.info(`Directory: ${targetDir}`);
91
+ chargebee_apps_shared_1.__logger.info('Project structure:');
92
+ this.templateService.printProjectStructure(targetDir);
93
+ }
94
+ catch (error) {
95
+ chargebee_apps_shared_1.__logger.error(`Error creating app: ${error}`);
96
+ this.process.exit(1);
97
+ }
98
+ }
99
+ }
100
+ exports.CreateCommand = CreateCommand;
101
+ // Export for use in commands/index.ts
102
+ exports.createCommand = new CreateCommand();
@@ -0,0 +1,7 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Sets up the CLI program with all available commands
4
+ * @returns {Command} The configured CLI program
5
+ */
6
+ declare function setupCLI(): Command;
7
+ export { setupCLI };
@@ -0,0 +1,93 @@
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.setupCLI = setupCLI;
7
+ const commander_1 = require("commander");
8
+ const package_json_1 = __importDefault(require("../../package.json"));
9
+ const create_1 = require("./create");
10
+ const package_1 = require("./package");
11
+ const run_1 = require("./run");
12
+ const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared");
13
+ const registry_1 = require("../registry");
14
+ /**
15
+ * Sets up the CLI program with all available commands
16
+ * @returns {Command} The configured CLI program
17
+ */
18
+ function setupCLI() {
19
+ const registry = registry_1.PublicCliRegistry.getInstance();
20
+ const pathResolver = new chargebee_apps_shared_1.PathResolver();
21
+ const templatesPath = pathResolver.getPublicLibsTemplatesDir();
22
+ const templateService = new chargebee_apps_shared_1.TemplateService(registry.fileSystem, templatesPath);
23
+ const availableTemplates = templateService.getAvailableTemplates();
24
+ const program = new commander_1.Command();
25
+ program
26
+ .name('chargebee-apps')
27
+ .description('Chargebee Apps CLI - Create, test, and package serverless applications')
28
+ .version(package_json_1.default.version)
29
+ .usage('<command> <directory> [options]')
30
+ .showHelpAfterError()
31
+ .showSuggestionAfterError()
32
+ .addHelpCommand()
33
+ .configureHelp({
34
+ sortSubcommands: true,
35
+ sortOptions: true,
36
+ subcommandTerm: (cmd) => {
37
+ const args = cmd.registeredArguments.map(arg => {
38
+ return arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;
39
+ }).join(' ');
40
+ const hasOptions = cmd.options.length > 0;
41
+ return `${cmd.name()}${args ? ' ' + args : ''}${hasOptions ? ' [options]' : ''}`;
42
+ }
43
+ });
44
+ program
45
+ .command('create')
46
+ .usage('<directory> [options]')
47
+ .summary('Create a new application')
48
+ .description('Create a new application from a template')
49
+ .argument('<directory>', 'Path where the new application will be created')
50
+ .option('--template <template>', 'Template to scaffold from', package_json_1.default.config.defaultTemplate)
51
+ .addHelpText('after', '\n' + [
52
+ 'Available Templates:',
53
+ ...availableTemplates.map(t => ` - ${t}`),
54
+ '',
55
+ 'Examples:',
56
+ ' chargebee-apps create my-app',
57
+ ' chargebee-apps create ./projects/new-app --template serverless-node-starter-app',
58
+ ' chargebee-apps create ./projects/my-app-with-iparams --template serverless-node-starter-app-with-iparams'
59
+ ].join('\n'))
60
+ .action((directory, options) => create_1.createCommand.execute(options, directory));
61
+ program
62
+ .command('run')
63
+ .usage('<directory> [options]')
64
+ .summary('Start a local development server')
65
+ .description('Start a local development server to test your serverless application')
66
+ .argument('<directory>', 'Path to the application directory to run')
67
+ .option('-p, --port <port>', 'Port to run the server on', package_json_1.default.config.defaultPort.toString())
68
+ .addHelpText('after', '\n' + [
69
+ 'Examples:',
70
+ ' chargebee-apps run .',
71
+ ' chargebee-apps run ./my-app',
72
+ ' chargebee-apps run ./my-app --port 15001',
73
+ ' chargebee-apps run ./my-app -p 15001'
74
+ ].join('\n'))
75
+ .action(async (directory, options) => {
76
+ await run_1.runCommand.execute(options, directory);
77
+ });
78
+ program
79
+ .command('package')
80
+ .usage('<directory> [options]')
81
+ .summary('Package an application')
82
+ .description('Package a serverless application into a zip file')
83
+ .argument('<directory>', 'Path to the application directory to package')
84
+ .option('--name <name>', 'Custom name for the package (without extension)', package_json_1.default.config.defaultPackageName)
85
+ .addHelpText('after', '\n' + [
86
+ 'Examples:',
87
+ ' chargebee-apps package .',
88
+ ' chargebee-apps package ./my-app',
89
+ ' chargebee-apps package ./my-app --name my-app-v1.0.0'
90
+ ].join('\n'))
91
+ .action(async (directory, options) => await package_1.packageCommand.execute(directory, options));
92
+ return program;
93
+ }
@@ -0,0 +1,20 @@
1
+ import { ArchiveService, CBFileSystem, CBProcess, FileManagementService, PackageOptions, PackageValidator } from '@chargebee/chargebee-apps-shared';
2
+ /**
3
+ * Main package command class
4
+ */
5
+ export declare class PackageCommand {
6
+ private fileSystem;
7
+ private process;
8
+ private fileManagementService;
9
+ private packageValidator;
10
+ private archiveService;
11
+ constructor(fileSystem?: CBFileSystem, process?: CBProcess, fileManagementService?: FileManagementService, packageValidator?: PackageValidator, archiveService?: ArchiveService);
12
+ /**
13
+ * Packages a serverless application into a zip file
14
+ * @param {string} appDir - The application directory to package
15
+ * @param {string} packageName - The name of the package
16
+ */
17
+ execute(appDir: string, options: PackageOptions): Promise<void>;
18
+ private validate;
19
+ }
20
+ export declare const packageCommand: PackageCommand;