@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.
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011-2024 Chargebee, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation
7
+ files (the "Software"), to deal in the Software without
8
+ restriction, including without limitation the rights to use,
9
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following
12
+ conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,297 @@
1
+ # Chargebee Apps CLI Developer Guide
2
+
3
+ The Chargebee Apps CLI is a command-line tool for building private serverless applications that extend Chargebee Billing. Use it to scaffold a new app, implement and test event handlers locally, and package the app into a ZIP file. When your app is ready, upload it to the Apps portal in Chargebee Billing to publish it privately to your site.
4
+
5
+ In Chargebee, a serverless application (also called an app) is a set of Node.js event handlers that run in Chargebee's hosted environment in response to Chargebee events. You write only the handler logic; Chargebee runs it automatically when a matching event occurs, so there is no server or infrastructure for you to provision, scale, or maintain.
6
+
7
+ With the Apps CLI, you can:
8
+
9
+ - Generate a ready-to-run app template.
10
+ - Implement and test event handlers locally.
11
+ - Trigger events interactively through a built-in web testing UI.
12
+ - Package your app into a deployable artifact.
13
+
14
+ ## Prerequisites
15
+
16
+ - Node.js 22 is required.
17
+
18
+ ## Install and verify the CLI
19
+
20
+ Install the CLI globally:
21
+
22
+ ```bash
23
+ npm install -g @chargebee/chargebee-apps
24
+ ```
25
+
26
+ Verify the installation by confirming that the version and help commands run successfully:
27
+
28
+ ```bash
29
+ chargebee-apps --version
30
+ chargebee-apps --help
31
+ ```
32
+
33
+ If both commands display the version and the list of `chargebee-apps` commands, your setup is complete.
34
+
35
+ ## Create a new application
36
+
37
+ Scaffold a new project with the `create` command. Choose the template that matches your app's requirements.
38
+
39
+ ### Standard template
40
+
41
+ Use the default template, `serverless-node-starter-app`, if your app performs pure event processing without user-configurable settings.
42
+
43
+ ```bash
44
+ # Create in the current directory
45
+ chargebee-apps create <app_name>
46
+
47
+ # Create within a specific subdirectory path
48
+ chargebee-apps create <subdirectory_path>/<app_name>
49
+ ```
50
+
51
+ ### iParams template
52
+
53
+ Use the iParams template if your app needs installation parameters (iParams) — user-configurable settings such as API keys, URLs, fee rules, or feature flags that users supply when they install the app.
54
+
55
+ ```bash
56
+ chargebee-apps create <app_name> --template serverless-node-starter-app-with-iparams
57
+ ```
58
+
59
+ ## Understand the app structure
60
+
61
+ The files in your project depend on the template you chose. Files marked as packaged are included in the deployable artifact; the rest are used only for local development.
62
+
63
+ | File or folder | Standard template | iParams template | Packaged | Purpose |
64
+ | --- | --- | --- | --- | --- |
65
+ | `manifest.json` | Yes | Yes | Yes | Maps Chargebee events to handler functions and declares npm dependencies. |
66
+ | `handler/handler.js` | Yes | Yes | Yes | Contains your core event-handling logic. |
67
+ | `iparams.json` | No | Yes | Yes | iParams template only. Defines the installation parameter schema. |
68
+ | `iparams.local.json` | No | Yes | No | iParams template only. Stores local test values, keyed by section name. |
69
+ | `test_data/` | Yes | Yes | No | Mock JSON event payloads used only for local testing. |
70
+ | `.env` | Yes | Yes | No | Local system environment variables. |
71
+ | `logs/cb.log` | Yes | Yes | No | Local development log file. |
72
+
73
+ ### manifest.json — App configuration
74
+
75
+ The `manifest.json` file defines your app's metadata, maps event subscriptions to their handler functions, and declares required third-party package dependencies.
76
+
77
+ ```json
78
+ {
79
+ "name": "your_app_name",
80
+ "description": "A clear description of what your serverless app does",
81
+ "events": {
82
+ "customer_created": {
83
+ "handler": "customerCreateHandler"
84
+ },
85
+ "invoice_generated": {
86
+ "handler": "invoiceGeneratedHandler"
87
+ }
88
+ },
89
+ "dependencies": {
90
+ "chargebee": "3.14.0"
91
+ }
92
+ }
93
+ ```
94
+
95
+ - **Event names:** Each key under `events` must exactly match a valid Chargebee webhook event type.
96
+ - **Handler names:** Each `handler` value must match a function exported from `handler/handler.js`.
97
+ - **Dependencies:** Only `chargebee` and `axios` are currently supported. For any additional npm packages, [contact the Chargebee support team](https://www.chargebee.com/docs/billing/2.0/kb/getting-started/how-to-contact-chargebees-support-team).
98
+
99
+ ### handler/handler.js — Application logic
100
+
101
+ Write your event-handling logic in `handler/handler.js`. Each handler receives a single `payload` argument. Use `payload.event` to access the event data. If you use the iParams template, access installation parameters through `payload.iparams.<section_name>.<param_name>`.
102
+
103
+ ```javascript
104
+ module.exports = {
105
+ customerCreateHandler: function (payload) {
106
+ console.log("Processing customer_created event");
107
+ console.log("Customer created for email:", payload.event.content.customer.email);
108
+
109
+ // iParams template only: read configuration if present
110
+ if (payload.iparams && payload.iparams.processing_fee_configuration) {
111
+ const fees = payload.iparams.processing_fee_configuration;
112
+ console.log("Processing fee (%):", fees.fee_percentage);
113
+ console.log("Processing fee limit:", fees.fee_limit);
114
+ }
115
+ },
116
+
117
+ invoiceGeneratedHandler: function (payload) {
118
+ console.log("Processing invoice_generated event");
119
+ console.log("Invoice status:", payload.event.content.invoice.status);
120
+
121
+ // iParams template only: read configuration if present
122
+ if (payload.iparams && payload.iparams.late_payment_fee_configuration) {
123
+ const lateFees = payload.iparams.late_payment_fee_configuration;
124
+ console.log("Late payment fee (%):", lateFees.fee_percentage);
125
+ }
126
+ }
127
+ };
128
+ ```
129
+
130
+ ### .env — Environment variables
131
+
132
+ Define your Chargebee API keys and site domain in a `.env` file. The CLI supports only these three variables:
133
+
134
+ ```plain text
135
+ MKPLC_CB_READ_ONLY_API=your_read_only_api_key_here
136
+ MKPLC_CB_READ_WRITE_API=your_read_write_api_key_here
137
+ MKPLC_SITE_DOMAIN=your_site_domain_here
138
+ ```
139
+
140
+ Access these values in your handler code through `process.env`, for example `process.env.MKPLC_CB_READ_ONLY_API`. The `.env` file is used for local development only and is not included when you package your app. In the hosted environment, Chargebee injects these variables automatically.
141
+
142
+ <Note>
143
+ These environment variables are different from installation parameters (iParams). Environment variables are standard system values that Chargebee injects automatically and require no user action. iParams are user-defined settings that an installer provides when they install or update the app.
144
+ </Note>
145
+
146
+ ## Define installation parameters (iParams)
147
+
148
+ This section applies only to apps built with the iParams template. Installation parameters let users configure your app when they install it — for example, API keys, endpoints, fee rules, or feature flags. An empty object (`{}`) in `iparams.json` means no installation parameters are defined.
149
+
150
+ ### Schema structure
151
+
152
+ Parameters are grouped into named sections in `iparams.json`. A maximum of 20 parameters is allowed in total across all sections.
153
+
154
+ Each section supports the following properties:
155
+
156
+ - `name` (required): Unique section identifier. Maximum 50 characters.
157
+ - `display_name` (required): Human-readable section title shown in the UI. Maximum 50 characters.
158
+ - `description` (required): Explains what the section configures. Maximum 250 characters.
159
+ - `parameters` (required): A non-empty array of parameter definitions.
160
+
161
+ Each parameter supports the following attributes:
162
+
163
+ - `name` (required): Unique parameter key within the section. Maximum 50 characters.
164
+ - `display_name` (required): Human-readable input label. Maximum 50 characters.
165
+ - `description` (required): Explains what the parameter is used for. Maximum 250 characters.
166
+ - `type` (required): One of the supported types listed below.
167
+ - `required` (optional): Defaults to `false`.
168
+ - `default` (optional): Default fallback value. Not allowed for the `SECRET` type.
169
+ - `options` (conditional): Required only for `DROPDOWN` and `MULTISELECT_DROPDOWN`.
170
+
171
+ ### Supported parameter types
172
+
173
+ | Type | Input or use case |
174
+ | --- | --- |
175
+ | `TEXT` | String (maximum 250 characters) for names, labels, and non-sensitive keys. |
176
+ | `SECRET` | String (maximum 250 characters) for passwords and API tokens. Encrypted at rest. Never log these values. |
177
+ | `URL` | Enforces valid `http://` or `https://` webhook and API endpoints. |
178
+ | `NUMBER` | Integer or decimal values for percentages, limits, and counts. |
179
+ | `BOOLEAN` | `true` or `false` toggles for feature flags. |
180
+ | `DROPDOWN` | Single selection from the choices in the `options` array. |
181
+ | `MULTISELECT_DROPDOWN` | Multiple selections from the choices in the `options` array. |
182
+ | `DATE` | Enforces `YYYY-MM-DD` formatting for expiry or start dates. |
183
+
184
+ ### Example: CRM schema with URL and SECRET
185
+
186
+ The following `iparams.json` defines a section with a URL endpoint and a secret token:
187
+
188
+ ```json
189
+ {
190
+ "installation_parameters": {
191
+ "sections": [
192
+ {
193
+ "name": "crm_integration",
194
+ "display_name": "CRM Integration",
195
+ "description": "HubSpot contacts API credentials and endpoint.",
196
+ "parameters": [
197
+ {
198
+ "name": "crm_webhook_url",
199
+ "display_name": "HubSpot contacts API URL",
200
+ "description": "Example: https://api.hubapi.com/crm/v3/objects/contacts",
201
+ "type": "URL",
202
+ "required": true
203
+ },
204
+ {
205
+ "name": "crm_auth_token",
206
+ "display_name": "HubSpot private app token",
207
+ "description": "Sent as Authorization: Bearer <token>.",
208
+ "type": "SECRET",
209
+ "required": true
210
+ }
211
+ ]
212
+ }
213
+ ]
214
+ }
215
+ }
216
+ ```
217
+
218
+ ### Provide local test inputs
219
+
220
+ To test your parametrized handlers locally, supply mock values in `iparams.local.json`, keyed by section name:
221
+
222
+ ```json
223
+ {
224
+ "crm_integration": {
225
+ "crm_webhook_url": "https://api.hubapi.com/crm/v3/objects/contacts",
226
+ "crm_auth_token": "pat-your-test-token"
227
+ }
228
+ }
229
+ ```
230
+
231
+ <Note>
232
+ `iparams.local.json` is never packaged. In production, users provide these values when they install or update the app.
233
+ </Note>
234
+
235
+ ## Run and test locally
236
+
237
+ Start the local development server:
238
+
239
+ ```bash
240
+ chargebee-apps run <app_directory>
241
+ ```
242
+
243
+ To run the server on a custom port, add the `--port` option:
244
+
245
+ ```bash
246
+ chargebee-apps run <app_directory> --port 16000
247
+ ```
248
+
249
+ Then open the local development UI in your browser:
250
+
251
+ - Default URL: `http://localhost:15000` (or your custom port).
252
+
253
+ If you use the iParams template, the CLI validates your `iparams.json` schema on startup. Fix any schema errors before you execute handlers.
254
+
255
+ ### Use the local web UI
256
+
257
+ - **Event testing:** Select an event type from the dropdown, for example `customer_created`. Review or edit the mock JSON payload loaded from `test_data/`, then click **Execute Handler**.
258
+ - **iParams tab (iParams template only):** Edit your parameter schema fields interactively. Saving writes directly to `iparams.json`.
259
+ - **iParams inputs tab (iParams template only):** Provide test values through a form or a raw JSON editor. Saving writes directly to `iparams.local.json`.
260
+ - **Logs:** Console output appears in the terminal running the server and is appended to `logs/cb.log`.
261
+
262
+ ## Package your application
263
+
264
+ After testing, bundle your application directory into a production-ready ZIP file:
265
+
266
+ ```bash
267
+ chargebee-apps package <app_directory>
268
+ ```
269
+
270
+ To set a custom version name, use the `--name` option:
271
+
272
+ ```bash
273
+ chargebee-apps package <app_directory> --name my-app-v1.0.0
274
+ ```
275
+
276
+ The package includes `manifest.json`, the `handler/` folder, and `iparams.json` (iParams template only). It excludes `test_data/`, `iparams.local.json`, `.env`, `logs/`, and `node_modules/`.
277
+
278
+ The command compiles the deployable artifact into the `dist/` folder:
279
+
280
+ ```plain text
281
+ my-first-app/
282
+ └── dist/
283
+ └── app.zip
284
+ ```
285
+
286
+ ## Publish your app
287
+
288
+ After you package your app, upload the ZIP file to the Apps portal in Chargebee Billing.
289
+
290
+ 1. In Chargebee Billing, go to **Apps** to open the Apps portal.
291
+ 2. Click **Create App**.
292
+ 3. On the **Upload Package** step, upload your app's `.zip` file. Click the upload area to browse, or drag and drop the file.
293
+ 4. On the **Review Details** step, review your app's details.
294
+ 5. Submit the app. Its status changes to **Under Review**.
295
+ 6. When the review is complete, the **Result** step shows the outcome.
296
+
297
+ After your app is published, it appears in the Apps portal list, where you can track each app's type (private or public) and status, and manage updates.
package/SECURITY.md ADDED
@@ -0,0 +1,8 @@
1
+ # Security Policy
2
+
3
+ At Chargebee, we take data integrity and security very seriously. Due to the nature of the product and service we provide, we are committed to working with individuals to stay updated on the latest security techniques and fix any security weakness in our application or infrastructure reported to us responsibly by external parties.
4
+
5
+ https://www.chargebee.com/security/responsible-disclosure-policy/
6
+
7
+ ## Reporting a vulnerability
8
+ Reach out to us at security@chargebee.com. Please do not open GitHub issues or pull requests as this makes the problem immediately visible to everyone, including malicious actors. Chargebee's security team will triage your report and respond according to its impact.
package/bin/index.js ADDED
@@ -0,0 +1 @@
1
+ require("../dist/index.js");
@@ -0,0 +1,6 @@
1
+ import { CBFileSystem } from '@chargebee/chargebee-apps-shared';
2
+ import { Application } from 'express';
3
+ /**
4
+ * Sets up all iparams-related API routes
5
+ */
6
+ export declare function setupIparamsRoutes(app: Application, userCodeDir: string, fileSystem: CBFileSystem): void;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupIparamsRoutes = setupIparamsRoutes;
4
+ const chargebee_apps_shared_1 = require("@chargebee/chargebee-apps-shared");
5
+ const registry_1 = require("../registry");
6
+ const REGISTRY = registry_1.PublicCliRegistry.getInstance();
7
+ const __logger = REGISTRY.logger;
8
+ /**
9
+ * Sets up all iparams-related API routes
10
+ */
11
+ function setupIparamsRoutes(app, userCodeDir, fileSystem) {
12
+ const service = new chargebee_apps_shared_1.IparamsService(fileSystem);
13
+ app.get('/api/iparams', (_req, res) => {
14
+ try {
15
+ return res.json({ iparams: service.loadIparamDefns(userCodeDir) });
16
+ }
17
+ catch (error) {
18
+ __logger.error('Error: Failed to load iparams.json', error);
19
+ const rawContent = error.rawContent ?? null;
20
+ return res.status(400).json({
21
+ error: 'Failed to load iparams.json',
22
+ message: error instanceof Error ? error.message : 'Unknown error',
23
+ rawContent
24
+ });
25
+ }
26
+ });
27
+ app.post('/api/iparams', (req, res) => {
28
+ try {
29
+ const iparamDefns = req.body.iparams;
30
+ service.saveIparamDefns(userCodeDir, iparamDefns);
31
+ return res.json({ success: true, message: 'Iparams saved successfully' });
32
+ }
33
+ catch (error) {
34
+ __logger.error('Error: Failed to save iparams', error);
35
+ return res.status(400).json({
36
+ error: 'Failed to save iparams',
37
+ message: error instanceof Error ? error.message : 'Unknown error'
38
+ });
39
+ }
40
+ });
41
+ app.get('/api/iparams/inputs', (_req, res) => {
42
+ try {
43
+ return res.json({ inputs: service.loadInputs(userCodeDir) });
44
+ }
45
+ catch (error) {
46
+ __logger.error('Error: Failed to load iparams.local.json', error);
47
+ return res.status(400).json({
48
+ error: 'Failed to load iparams.local.json',
49
+ message: error instanceof Error ? error.message : 'Unknown error'
50
+ });
51
+ }
52
+ });
53
+ app.post('/api/iparams/inputs', (req, res) => {
54
+ try {
55
+ service.saveInputs(userCodeDir, req.body.inputs);
56
+ return res.json({ success: true, message: 'Inputs saved successfully' });
57
+ }
58
+ catch (error) {
59
+ if (error instanceof chargebee_apps_shared_1.MissingRequiredParamsError) {
60
+ return res.status(400).json({
61
+ valid: false,
62
+ missing: error.missing,
63
+ message: error.message
64
+ });
65
+ }
66
+ __logger.error('Error: Failed to save iparams inputs', error);
67
+ return res.status(400).json({
68
+ error: 'Failed to save iparams inputs',
69
+ message: error instanceof Error ? error.message : 'Unknown error'
70
+ });
71
+ }
72
+ });
73
+ }
@@ -0,0 +1,39 @@
1
+ import { CBFileSystem, CBProcess, DependencyManager, EventRecord, ICBLogger } from '@chargebee/chargebee-apps-shared';
2
+ import { Application } from 'express';
3
+ import * as http from "http";
4
+ /**
5
+ * Sets up and start an Express server for the serverless app tester
6
+ * @param {number} port - The port number to run the server on
7
+ * @param {string} userCodeDir - The user code directory where logs should be stored
8
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
9
+ * @param {CBProcess} processService - The process implementation to use
10
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
11
+ */
12
+ export declare function setupServer(port: number, userCodeDir: string, fileSystem?: CBFileSystem, processService?: CBProcess, dependencyManager?: DependencyManager): http.Server;
13
+ /**
14
+ * Invokes an event handler based on the event data
15
+ * @param {EventRecord} eventData - The event data containing event_type and payload
16
+ * @param {ICBLogger} sessionLogger - The logger instance for this server session
17
+ * @param {string} userCodeDir - The user code directory
18
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
19
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
20
+ * @returns {Promise<any>} The result from the handler function
21
+ * @throws {Error} If handler file, manifest, or handler function is not found
22
+ */
23
+ export declare function invokeEventHandler(eventData: EventRecord, sessionLogger: ICBLogger, userCodeDir: string, fileSystem: CBFileSystem, dependencyManager: DependencyManager): Promise<any>;
24
+ /**
25
+ * Sets up all API routes for the serverless app tester
26
+ * @param {Application} app - Express application instance
27
+ * @param {ICBLogger} sessionLogger - The logger instance for this server session
28
+ * @param {string} userCodeDir - The user code directory
29
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
30
+ * @param {CBProcess} process - The process implementation to use
31
+ * @param {DependencyManager} dependencyManager - The dependency manager implementation to use
32
+ */
33
+ export declare function setupApiRoutes(app: Application, sessionLogger: ICBLogger, userCodeDir: string, fileSystem: CBFileSystem, process: CBProcess, dependencyManager: DependencyManager): void;
34
+ /**
35
+ * Sets up application routes for serving the web UI
36
+ * @param {Application} app - Express application instance
37
+ * @param {CBFileSystem} fileSystem - The filesystem implementation to use
38
+ */
39
+ export declare function setupAppRoutes(app: Application, fileSystem: CBFileSystem): void;