chargebee 3.26.0 → 3.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +131 -0
  3. package/cjs/RequestWrapper.js +130 -12
  4. package/cjs/chargebee.cjs.js +5 -0
  5. package/cjs/chargebee.cjs.worker.js +2 -0
  6. package/cjs/chargebeeZodValidationError.js +18 -0
  7. package/cjs/createChargebee.js +23 -2
  8. package/cjs/environment.js +1 -1
  9. package/cjs/schema/addon.schema.js +269 -0
  10. package/cjs/schema/address.schema.js +35 -0
  11. package/cjs/schema/alert.schema.js +74 -0
  12. package/cjs/schema/alert_status.schema.js +31 -0
  13. package/cjs/schema/attached_item.schema.js +144 -0
  14. package/cjs/schema/business_entity.schema.js +46 -0
  15. package/cjs/schema/card.schema.js +165 -0
  16. package/cjs/schema/comment.schema.js +69 -0
  17. package/cjs/schema/coupon.schema.js +323 -0
  18. package/cjs/schema/coupon_code.schema.js +49 -0
  19. package/cjs/schema/coupon_set.schema.js +88 -0
  20. package/cjs/schema/credit_note.schema.js +502 -0
  21. package/cjs/schema/currency.schema.js +32 -0
  22. package/cjs/schema/customer.schema.js +1201 -0
  23. package/cjs/schema/customer_entitlement.schema.js +14 -0
  24. package/cjs/schema/differential_price.schema.js +106 -0
  25. package/cjs/schema/entitlement.schema.js +54 -0
  26. package/cjs/schema/entitlement_override.schema.js +35 -0
  27. package/cjs/schema/estimate.schema.js +1535 -0
  28. package/cjs/schema/event.schema.js +1060 -0
  29. package/cjs/schema/export.schema.js +3385 -0
  30. package/cjs/schema/feature.schema.js +78 -0
  31. package/cjs/schema/gift.schema.js +293 -0
  32. package/cjs/schema/grant_block.schema.js +47 -0
  33. package/cjs/schema/hosted_page.schema.js +1777 -0
  34. package/cjs/schema/in_app_subscription.schema.js +68 -0
  35. package/cjs/schema/index.js +88 -0
  36. package/cjs/schema/invoice.schema.js +1685 -0
  37. package/cjs/schema/item.schema.js +195 -0
  38. package/cjs/schema/item_entitlement.schema.js +45 -0
  39. package/cjs/schema/item_family.schema.js +57 -0
  40. package/cjs/schema/item_price.schema.js +335 -0
  41. package/cjs/schema/ledger_account_balance.schema.js +21 -0
  42. package/cjs/schema/ledger_operation.schema.js +104 -0
  43. package/cjs/schema/meter.schema.js +13 -0
  44. package/cjs/schema/metered_feature.schema.js +20 -0
  45. package/cjs/schema/non_subscription.schema.js +28 -0
  46. package/cjs/schema/offer_event.schema.js +13 -0
  47. package/cjs/schema/offer_fulfillment.schema.js +20 -0
  48. package/cjs/schema/omnichannel_one_time_order.schema.js +26 -0
  49. package/cjs/schema/omnichannel_subscription.schema.js +122 -0
  50. package/cjs/schema/omnichannel_subscription_item.schema.js +13 -0
  51. package/cjs/schema/order.schema.js +441 -0
  52. package/cjs/schema/payment_intent.schema.js +127 -0
  53. package/cjs/schema/payment_schedule_scheme.schema.js +20 -0
  54. package/cjs/schema/payment_source.schema.js +630 -0
  55. package/cjs/schema/payment_voucher.schema.js +57 -0
  56. package/cjs/schema/personalized_offer.schema.js +28 -0
  57. package/cjs/schema/plan.schema.js +363 -0
  58. package/cjs/schema/portal_session.schema.js +22 -0
  59. package/cjs/schema/price_variant.schema.js +93 -0
  60. package/cjs/schema/pricing_page_session.schema.js +135 -0
  61. package/cjs/schema/promotional_credit.schema.js +78 -0
  62. package/cjs/schema/promotional_grant.schema.js +17 -0
  63. package/cjs/schema/purchase.schema.js +277 -0
  64. package/cjs/schema/quote.schema.js +1667 -0
  65. package/cjs/schema/ramp.schema.js +245 -0
  66. package/cjs/schema/recorded_purchase.schema.js +32 -0
  67. package/cjs/schema/resource_migration.schema.js +14 -0
  68. package/cjs/schema/site_migration_detail.schema.js +81 -0
  69. package/cjs/schema/subscription.schema.js +3344 -0
  70. package/cjs/schema/subscription_entitlement.schema.js +25 -0
  71. package/cjs/schema/time_machine.schema.js +17 -0
  72. package/cjs/schema/transaction.schema.js +744 -0
  73. package/cjs/schema/unbilled_charge.schema.js +139 -0
  74. package/cjs/schema/usage.schema.js +93 -0
  75. package/cjs/schema/usage_charge.schema.js +17 -0
  76. package/cjs/schema/usage_event.schema.js +28 -0
  77. package/cjs/schema/usage_file.schema.js +13 -0
  78. package/cjs/schema/usage_summary.schema.js +17 -0
  79. package/cjs/schema/virtual_bank_account.schema.js +71 -0
  80. package/cjs/schema/webhook_endpoint.schema.js +508 -0
  81. package/cjs/telemetry/TelemetryAdapter.js +145 -0
  82. package/cjs/telemetry/index.js +28 -0
  83. package/cjs/telemetry/otel.js +66 -0
  84. package/cjs/telemetry/types.js +47 -0
  85. package/cjs/validationLoader.js +59 -0
  86. package/esm/RequestWrapper.js +130 -12
  87. package/esm/chargebee.esm.js +3 -0
  88. package/esm/chargebee.esm.worker.js +1 -0
  89. package/esm/chargebeeZodValidationError.js +14 -0
  90. package/esm/createChargebee.js +23 -2
  91. package/esm/environment.js +1 -1
  92. package/esm/schema/addon.schema.js +266 -0
  93. package/esm/schema/address.schema.js +32 -0
  94. package/esm/schema/alert.schema.js +71 -0
  95. package/esm/schema/alert_status.schema.js +28 -0
  96. package/esm/schema/attached_item.schema.js +141 -0
  97. package/esm/schema/business_entity.schema.js +43 -0
  98. package/esm/schema/card.schema.js +162 -0
  99. package/esm/schema/comment.schema.js +66 -0
  100. package/esm/schema/coupon.schema.js +320 -0
  101. package/esm/schema/coupon_code.schema.js +46 -0
  102. package/esm/schema/coupon_set.schema.js +85 -0
  103. package/esm/schema/credit_note.schema.js +499 -0
  104. package/esm/schema/currency.schema.js +29 -0
  105. package/esm/schema/customer.schema.js +1198 -0
  106. package/esm/schema/customer_entitlement.schema.js +11 -0
  107. package/esm/schema/differential_price.schema.js +103 -0
  108. package/esm/schema/entitlement.schema.js +51 -0
  109. package/esm/schema/entitlement_override.schema.js +32 -0
  110. package/esm/schema/estimate.schema.js +1532 -0
  111. package/esm/schema/event.schema.js +1057 -0
  112. package/esm/schema/export.schema.js +3382 -0
  113. package/esm/schema/feature.schema.js +75 -0
  114. package/esm/schema/gift.schema.js +290 -0
  115. package/esm/schema/grant_block.schema.js +44 -0
  116. package/esm/schema/hosted_page.schema.js +1774 -0
  117. package/esm/schema/in_app_subscription.schema.js +65 -0
  118. package/esm/schema/index.js +72 -0
  119. package/esm/schema/invoice.schema.js +1682 -0
  120. package/esm/schema/item.schema.js +192 -0
  121. package/esm/schema/item_entitlement.schema.js +42 -0
  122. package/esm/schema/item_family.schema.js +54 -0
  123. package/esm/schema/item_price.schema.js +332 -0
  124. package/esm/schema/ledger_account_balance.schema.js +18 -0
  125. package/esm/schema/ledger_operation.schema.js +101 -0
  126. package/esm/schema/meter.schema.js +10 -0
  127. package/esm/schema/metered_feature.schema.js +17 -0
  128. package/esm/schema/non_subscription.schema.js +25 -0
  129. package/esm/schema/offer_event.schema.js +10 -0
  130. package/esm/schema/offer_fulfillment.schema.js +17 -0
  131. package/esm/schema/omnichannel_one_time_order.schema.js +23 -0
  132. package/esm/schema/omnichannel_subscription.schema.js +119 -0
  133. package/esm/schema/omnichannel_subscription_item.schema.js +10 -0
  134. package/esm/schema/order.schema.js +438 -0
  135. package/esm/schema/payment_intent.schema.js +124 -0
  136. package/esm/schema/payment_schedule_scheme.schema.js +17 -0
  137. package/esm/schema/payment_source.schema.js +627 -0
  138. package/esm/schema/payment_voucher.schema.js +54 -0
  139. package/esm/schema/personalized_offer.schema.js +25 -0
  140. package/esm/schema/plan.schema.js +360 -0
  141. package/esm/schema/portal_session.schema.js +19 -0
  142. package/esm/schema/price_variant.schema.js +90 -0
  143. package/esm/schema/pricing_page_session.schema.js +132 -0
  144. package/esm/schema/promotional_credit.schema.js +75 -0
  145. package/esm/schema/promotional_grant.schema.js +14 -0
  146. package/esm/schema/purchase.schema.js +274 -0
  147. package/esm/schema/quote.schema.js +1664 -0
  148. package/esm/schema/ramp.schema.js +242 -0
  149. package/esm/schema/recorded_purchase.schema.js +29 -0
  150. package/esm/schema/resource_migration.schema.js +11 -0
  151. package/esm/schema/site_migration_detail.schema.js +78 -0
  152. package/esm/schema/subscription.schema.js +3341 -0
  153. package/esm/schema/subscription_entitlement.schema.js +22 -0
  154. package/esm/schema/time_machine.schema.js +14 -0
  155. package/esm/schema/transaction.schema.js +741 -0
  156. package/esm/schema/unbilled_charge.schema.js +136 -0
  157. package/esm/schema/usage.schema.js +90 -0
  158. package/esm/schema/usage_charge.schema.js +14 -0
  159. package/esm/schema/usage_event.schema.js +25 -0
  160. package/esm/schema/usage_file.schema.js +10 -0
  161. package/esm/schema/usage_summary.schema.js +14 -0
  162. package/esm/schema/virtual_bank_account.schema.js +68 -0
  163. package/esm/schema/webhook_endpoint.schema.js +505 -0
  164. package/esm/telemetry/TelemetryAdapter.js +132 -0
  165. package/esm/telemetry/index.js +8 -0
  166. package/esm/telemetry/otel.js +62 -0
  167. package/esm/telemetry/types.js +44 -0
  168. package/esm/validationLoader.js +56 -0
  169. package/package.json +43 -24
  170. package/types/core.d.ts +2 -0
  171. package/types/index.d.ts +85 -0
  172. package/types/telemetry/otel.d.ts +22 -0
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /*
3
+ * This file is auto-generated by Chargebee.
4
+ * For more information on how to make changes to this file, please see the README.
5
+ * Reach out to dx@chargebee.com for any questions.
6
+ * Copyright 2026 Chargebee Inc.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.OtelTelemetryAdapter = void 0;
10
+ const api_1 = require("@opentelemetry/api");
11
+ const types_js_1 = require("./types.js");
12
+ const tracer = api_1.trace.getTracer(types_js_1.CHARGEBEE_SDK_NAME);
13
+ function toRecordedException(error) {
14
+ var _a;
15
+ const exception = new Error(error.message);
16
+ exception.name = (_a = error.chargebeeErrorCode) !== null && _a !== void 0 ? _a : 'ChargebeeAPIError';
17
+ return exception;
18
+ }
19
+ /**
20
+ * Ready-to-use OpenTelemetry adapter for the Chargebee SDK.
21
+ *
22
+ * Each SDK request becomes a CLIENT span attached to the active OpenTelemetry
23
+ * context (or a root span when none is active), and the W3C trace context is
24
+ * propagated to Chargebee so the trace continues server-side.
25
+ *
26
+ * Exporting (endpoint, service name, credentials) is configured by your own
27
+ * OpenTelemetry runtime via the standard `OTEL_*` environment variables — this
28
+ * adapter only uses the globally registered tracer from `@opentelemetry/api`.
29
+ *
30
+ * `@opentelemetry/api` is an optional peer dependency; install it to use this
31
+ * adapter. A default-exported, ready-to-use instance is provided.
32
+ */
33
+ class OtelTelemetryAdapter {
34
+ onRequestStart(ctx, requestHeaders) {
35
+ // startSpan adopts the active context's span as parent (or starts a root span if none).
36
+ const span = tracer.startSpan(ctx.spanName, {
37
+ kind: api_1.SpanKind.CLIENT,
38
+ attributes: ctx.startAttributes,
39
+ });
40
+ // Propagate W3C trace context to Chargebee so the trace continues server-side.
41
+ api_1.propagation.inject(api_1.trace.setSpan(api_1.context.active(), span), requestHeaders);
42
+ return span;
43
+ }
44
+ onRequestEnd(span, result) {
45
+ if (!span) {
46
+ return;
47
+ }
48
+ for (const [key, value] of Object.entries(result.endAttributes)) {
49
+ span.setAttribute(key, value);
50
+ }
51
+ if (result.error) {
52
+ span.recordException(toRecordedException(result.error));
53
+ span.setStatus({
54
+ code: api_1.SpanStatusCode.ERROR,
55
+ message: result.error.message,
56
+ });
57
+ }
58
+ else {
59
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
60
+ }
61
+ span.end();
62
+ }
63
+ }
64
+ exports.OtelTelemetryAdapter = OtelTelemetryAdapter;
65
+ const otelDefaultAdapter = new OtelTelemetryAdapter();
66
+ exports.default = otelDefaultAdapter;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /*
3
+ * This file is auto-generated by Chargebee.
4
+ * For more information on how to make changes to this file, please see the README.
5
+ * Reach out to dx@chargebee.com for any questions.
6
+ * Copyright 2026 Chargebee Inc.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.TelemetryAttributeKeys = exports.CHARGEBEE_TELEMETRY_HEADER_EXCLUDE_PREFIX = exports.CHARGEBEE_TELEMETRY_HEADER_PREFIX = exports.HTTP_REQUEST_HEADER_ATTRIBUTE_PREFIX = exports.TELEMETRY_SPAN_NAME_PREFIX = exports.CHARGEBEE_SDK_NAME = void 0;
10
+ /** SDK identifier recorded on telemetry spans. */
11
+ exports.CHARGEBEE_SDK_NAME = 'chargebee-node';
12
+ /** Standard span name prefix: chargebee.{resource}.{operation} */
13
+ exports.TELEMETRY_SPAN_NAME_PREFIX = 'chargebee';
14
+ /**
15
+ * OTel HTTP semantic-convention prefix for request-header attributes:
16
+ * `http.request.header.<lowercased-name>` with string[] values.
17
+ */
18
+ exports.HTTP_REQUEST_HEADER_ATTRIBUTE_PREFIX = 'http.request.header.';
19
+ /**
20
+ * Request headers whose (lowercased) name starts with this prefix are captured as span
21
+ * attributes. Using a prefix instead of a fixed list means any future `chargebee-*` header
22
+ * is picked up automatically, with no SDK upgrade required.
23
+ */
24
+ exports.CHARGEBEE_TELEMETRY_HEADER_PREFIX = 'chargebee-';
25
+ /**
26
+ * Headers under this sub-prefix carry end-user PII (origin IP, email, device) and are
27
+ * excluded from spans by default. Chargebee namespaces such headers under
28
+ * `chargebee-request-origin-*`, so future PII headers stay excluded automatically.
29
+ */
30
+ exports.CHARGEBEE_TELEMETRY_HEADER_EXCLUDE_PREFIX = 'chargebee-request-origin-';
31
+ /** Span attribute keys — shared across Chargebee SDKs. */
32
+ exports.TelemetryAttributeKeys = {
33
+ URL_FULL: 'url.full',
34
+ HTTP_REQUEST_METHOD: 'http.request.method',
35
+ HTTP_RESPONSE_STATUS_CODE: 'http.response.status_code',
36
+ SERVER_ADDRESS: 'server.address',
37
+ ERROR_TYPE: 'error.type',
38
+ CHARGEBEE_SITE: 'chargebee.site',
39
+ CHARGEBEE_API_VERSION: 'chargebee.api_version',
40
+ CHARGEBEE_RESOURCE: 'chargebee.resource',
41
+ CHARGEBEE_OPERATION: 'chargebee.operation',
42
+ CHARGEBEE_SDK_NAME: 'chargebee.sdk.name',
43
+ CHARGEBEE_SDK_VERSION: 'chargebee.sdk.version',
44
+ CHARGEBEE_ERROR_CODE: 'chargebee.error.code',
45
+ CHARGEBEE_ERROR_TYPE: 'chargebee.error.type',
46
+ CHARGEBEE_ERROR_PARAM: 'chargebee.error.param',
47
+ };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * Lazy schema loader for opt-in Zod validation.
4
+ *
5
+ * Schemas are loaded on first use. Node.js automatically caches imported modules,
6
+ * so repeated imports of the same schema file are efficient.
7
+ *
8
+ * Each resource module lives at {@code schema/<resource_snake>.schema.ts}
9
+ * and exports one body schema per action.
10
+ *
11
+ * The body schema const name follows {@code ZodNamingStrategy.bodySchemaName} in sdk-generator:
12
+ * {@code {PascalAction}{PascalResource}BodySchema}
13
+ *
14
+ * Uses native dynamic import() - TypeScript transpiles appropriately for ESM/CJS targets.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.getSchema = getSchema;
18
+ function toCamel(s) {
19
+ return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
20
+ }
21
+ function toPascal(s) {
22
+ const camel = toCamel(s);
23
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
24
+ }
25
+ /** Matches ZodNamingStrategy.bodySchemaName() in sdk-generator. */
26
+ function schemaConstName(resourceKey, actionName) {
27
+ return toPascal(actionName) + toPascal(resourceKey) + 'BodySchema';
28
+ }
29
+ /** camelCase resource key → snake_case module basename (e.g. virtualBankAccount → virtual_bank_account). */
30
+ function resourceSchemaBasename(resourceKey) {
31
+ return resourceKey
32
+ .replace(/([A-Z])/g, '_$1')
33
+ .toLowerCase()
34
+ .replace(/^_/, '');
35
+ }
36
+ /**
37
+ * Load the Zod schema for a given resource + action.
38
+ * Returns null if no schema file exists for this combination.
39
+ *
40
+ * Node.js automatically caches the imported modules, so repeated calls
41
+ * for the same resource will reuse the cached module.
42
+ *
43
+ * TypeScript compiler handles module system differences:
44
+ * - ESM build: keeps await import() as-is
45
+ * - CJS build: transpiles to require() or Promise-based equivalent
46
+ */
47
+ async function getSchema(resourceKey, actionName) {
48
+ var _a;
49
+ const base = resourceSchemaBasename(resourceKey);
50
+ const constName = schemaConstName(resourceKey, actionName);
51
+ try {
52
+ const mod = await Promise.resolve(`${`./schema/${base}.schema.js`}`).then(s => require(s));
53
+ const schema = (_a = mod[constName]) !== null && _a !== void 0 ? _a : null;
54
+ return schema;
55
+ }
56
+ catch (_b) {
57
+ return null;
58
+ }
59
+ }
@@ -1,6 +1,9 @@
1
1
  import { extend, callbackifyPromise, getApiURL, encodeListParams, encodeParams, serialize, getHost, log, generateUUIDv4 as uuidv4, } from './util.js';
2
+ import { buildRequestTelemetryContext, buildRequestTelemetryResult, extractHttpStatusCode, extractRequestTelemetryError, resolveChargebeeApiVersion, } from './telemetry/index.js';
2
3
  import { handleResponse } from './coreCommon.js';
3
4
  import { Buffer } from 'node:buffer';
5
+ import { ChargebeeZodValidationError } from './chargebeeZodValidationError.js';
6
+ import { getSchema } from './validationLoader.js';
4
7
  export class RequestWrapper {
5
8
  constructor(args, apiCall, envArg) {
6
9
  this.getRequest = () => {
@@ -20,6 +23,17 @@ export class RequestWrapper {
20
23
  }
21
24
  return idParam;
22
25
  }
26
+ /**
27
+ * Validate parameters against the action's Zod schema when enableValidation is true.
28
+ * Query params are validated as `params ?? {}`; body params are validated when `params` is non-null.
29
+ * Throws a descriptive error listing every validation violation.
30
+ */
31
+ static _validateParams(params, schema, actionName) {
32
+ const result = schema.safeParse(params);
33
+ if (!result.success) {
34
+ throw new ChargebeeZodValidationError(actionName, result.error);
35
+ }
36
+ }
23
37
  static parseRetryAfter(retryAfter) {
24
38
  if (!retryAfter)
25
39
  return null;
@@ -29,9 +43,28 @@ export class RequestWrapper {
29
43
  }
30
44
  return null;
31
45
  }
46
+ _buildRequestUrl(env, urlIdParam, params) {
47
+ let path = getApiURL(env, this.apiCall.urlPrefix, this.apiCall.urlSuffix, urlIdParam);
48
+ if (this.apiCall.httpMethod === 'GET') {
49
+ let requestParams = params;
50
+ if (typeof requestParams === 'undefined' || requestParams === null) {
51
+ requestParams = {};
52
+ }
53
+ const queryParam = this.apiCall.isListReq
54
+ ? encodeListParams(serialize(requestParams))
55
+ : encodeParams(serialize(requestParams));
56
+ path += '?' + queryParam;
57
+ }
58
+ return new URL(path, `${env.protocol}://${getHost(env, this.apiCall.subDomain)}${env.port ? `:${env.port}` : ''}`);
59
+ }
32
60
  async request() {
33
61
  let _env = {};
34
62
  extend(true, _env, this.envArg);
63
+ // Class-based adapters (e.g. OpenTelemetry) keep methods on the prototype;
64
+ // deep extend only copies own enumerable properties, so preserve by reference.
65
+ if (this.envArg.telemetryAdapter !== undefined) {
66
+ _env.telemetryAdapter = this.envArg.telemetryAdapter;
67
+ }
35
68
  const env = _env;
36
69
  const retryConfig = Object.assign({ enabled: false, maxRetries: 3, delayMs: 200, retryOn: [500, 502, 503, 504] }, env.retryConfig);
37
70
  const urlIdParam = this.apiCall.hasIdInUrl ? this.args[0] : null;
@@ -39,6 +72,20 @@ export class RequestWrapper {
39
72
  ? this.args[1]
40
73
  : this.args[0];
41
74
  let headers = this.apiCall.hasIdInUrl ? this.args[2] : this.args[1];
75
+ // Lazy-load Zod schema when enableValidation is true
76
+ if (env.enableValidation &&
77
+ this.apiCall.resourceKey &&
78
+ this.apiCall.actionName) {
79
+ const schema = await getSchema(this.apiCall.resourceKey, this.apiCall.actionName);
80
+ if (schema) {
81
+ if (this.apiCall.httpMethod === 'GET') {
82
+ RequestWrapper._validateParams(params !== null && params !== void 0 ? params : {}, schema, this.apiCall.methodName);
83
+ }
84
+ else if (params != null) {
85
+ RequestWrapper._validateParams(params, schema, this.apiCall.methodName);
86
+ }
87
+ }
88
+ }
42
89
  Object.assign(this.httpHeaders, headers);
43
90
  if (this.apiCall.httpMethod === 'POST' &&
44
91
  !this.httpHeaders['chargebee-idempotency-key'] &&
@@ -47,19 +94,43 @@ export class RequestWrapper {
47
94
  retryConfig.enabled) {
48
95
  this.httpHeaders['chargebee-idempotency-key'] = uuidv4();
49
96
  }
97
+ const telemetryAdapter = env.telemetryAdapter;
98
+ const telemetryHeaders = {};
99
+ const requestStartTime = Date.now();
100
+ const requestUrl = this._buildRequestUrl(env, urlIdParam, params);
101
+ // No telemetry adapter configured => skip all telemetry work (zero overhead).
102
+ let telemetryHandle;
103
+ if (telemetryAdapter !== undefined) {
104
+ const telemetryContext = buildRequestTelemetryContext({
105
+ resource: this.apiCall.resource,
106
+ operation: this.apiCall.methodName,
107
+ httpMethod: this.apiCall.httpMethod,
108
+ httpUrl: `${requestUrl.origin}${requestUrl.pathname}`,
109
+ serverAddress: requestUrl.hostname,
110
+ chargebeeSite: env.site,
111
+ chargebeeApiVersion: resolveChargebeeApiVersion(env.apiPath),
112
+ sdkVersion: env.clientVersion,
113
+ requestHeaders: this.httpHeaders,
114
+ });
115
+ try {
116
+ telemetryHandle = telemetryAdapter.onRequestStart(telemetryContext, telemetryHeaders);
117
+ }
118
+ catch (err) {
119
+ const message = err instanceof Error
120
+ ? err.message
121
+ : 'Unknown telemetry adapter error';
122
+ log(env, {
123
+ level: 'ERROR',
124
+ message: `Telemetry adapter onRequestStart failed: ${message}. Continuing without telemetry.`,
125
+ });
126
+ telemetryHandle = undefined;
127
+ }
128
+ }
50
129
  const makeRequest = async (attempt = 0) => {
51
- let path = getApiURL(env, this.apiCall.urlPrefix, this.apiCall.urlSuffix, urlIdParam);
52
130
  let requestParams = params;
53
131
  if (typeof requestParams === 'undefined' || requestParams === null) {
54
132
  requestParams = {};
55
133
  }
56
- if (this.apiCall.httpMethod === 'GET') {
57
- const queryParam = this.apiCall.isListReq
58
- ? encodeListParams(serialize(requestParams))
59
- : encodeParams(serialize(requestParams));
60
- path += '?' + queryParam;
61
- requestParams = {};
62
- }
63
134
  const jsonKeys = this.apiCall.jsonKeys;
64
135
  let data = null;
65
136
  if (this.apiCall.httpMethod !== 'GET') {
@@ -67,7 +138,7 @@ export class RequestWrapper {
67
138
  ? JSON.stringify(requestParams)
68
139
  : encodeParams(requestParams, undefined, undefined, undefined, jsonKeys);
69
140
  }
70
- const requestHeaders = Object.assign({}, this.httpHeaders);
141
+ const requestHeaders = Object.assign(Object.assign({}, this.httpHeaders), telemetryHeaders);
71
142
  if (data && data.length) {
72
143
  extend(true, requestHeaders, {
73
144
  'Content-Length': Buffer.byteLength(data, 'utf8'),
@@ -87,8 +158,7 @@ export class RequestWrapper {
87
158
  if (attempt > 0) {
88
159
  requestHeaders['X-CB-Retry-Attempt'] = attempt.toString();
89
160
  }
90
- const url = new URL(path, `${env.protocol}://${getHost(env, this.apiCall.subDomain)}${env.port ? `:${env.port}` : ''}`);
91
- const request = new Request(url, {
161
+ const request = new Request(requestUrl, {
92
162
  method: this.apiCall.httpMethod,
93
163
  body: data || undefined,
94
164
  headers: this._createHeaders(requestHeaders),
@@ -150,7 +220,55 @@ export class RequestWrapper {
150
220
  return await withRetry(retryCount + 1, startTime);
151
221
  }
152
222
  };
153
- const promise = withRetry(0, Date.now());
223
+ const runWithTelemetry = async (adapter) => {
224
+ var _a;
225
+ try {
226
+ const result = await withRetry(0, requestStartTime);
227
+ const httpStatusCode = typeof (result === null || result === void 0 ? void 0 : result.httpStatusCode) === 'number'
228
+ ? result.httpStatusCode
229
+ : 200;
230
+ try {
231
+ adapter.onRequestEnd(telemetryHandle, buildRequestTelemetryResult({
232
+ httpStatusCode,
233
+ durationMs: Date.now() - requestStartTime,
234
+ }));
235
+ }
236
+ catch (err) {
237
+ const message = err instanceof Error
238
+ ? err.message
239
+ : 'Unknown telemetry adapter error';
240
+ log(env, {
241
+ level: 'ERROR',
242
+ message: `Telemetry adapter onRequestEnd failed: ${message}.`,
243
+ });
244
+ }
245
+ return result;
246
+ }
247
+ catch (err) {
248
+ const httpStatusCode = (_a = extractHttpStatusCode(err)) !== null && _a !== void 0 ? _a : 500;
249
+ const telemetryError = extractRequestTelemetryError(err);
250
+ try {
251
+ adapter.onRequestEnd(telemetryHandle, buildRequestTelemetryResult({
252
+ httpStatusCode,
253
+ durationMs: Date.now() - requestStartTime,
254
+ error: telemetryError,
255
+ }));
256
+ }
257
+ catch (telemetryErr) {
258
+ const message = telemetryErr instanceof Error
259
+ ? telemetryErr.message
260
+ : 'Unknown telemetry adapter error';
261
+ log(env, {
262
+ level: 'ERROR',
263
+ message: `Telemetry adapter onRequestEnd failed: ${message}.`,
264
+ });
265
+ }
266
+ throw err;
267
+ }
268
+ };
269
+ const promise = telemetryAdapter !== undefined
270
+ ? runWithTelemetry(telemetryAdapter)
271
+ : withRetry(0, requestStartTime);
154
272
  return callbackifyPromise(promise);
155
273
  }
156
274
  _createHeaders(httpHeaders) {
@@ -7,3 +7,6 @@ export default Chargebee;
7
7
  export { WebhookEventType, WebhookContentType, } from './resources/webhook/handler.js';
8
8
  export { basicAuthValidator } from './resources/webhook/auth.js';
9
9
  export { WebhookError, WebhookAuthenticationError, WebhookPayloadValidationError, WebhookPayloadParseError, } from './resources/webhook/handler.js';
10
+ export { TelemetryAttributeKeys } from './telemetry/index.js';
11
+ // Export validation error class
12
+ export { ChargebeeZodValidationError } from './chargebeeZodValidationError.js';
@@ -7,3 +7,4 @@ export default Chargebee;
7
7
  export { WebhookEventType, WebhookContentType, } from './resources/webhook/handler.js';
8
8
  export { basicAuthValidator } from './resources/webhook/auth.js';
9
9
  export { WebhookError, WebhookAuthenticationError, WebhookPayloadValidationError, WebhookPayloadParseError, } from './resources/webhook/handler.js';
10
+ export { ChargebeeZodValidationError } from './chargebeeZodValidationError.js';
@@ -0,0 +1,14 @@
1
+ export class ChargebeeZodValidationError extends Error {
2
+ constructor(actionName, zodError) {
3
+ var _a;
4
+ const messages = zodError.issues
5
+ .map((e) => `${e.path.join('.')}: ${e.message}`)
6
+ .join('; ');
7
+ super(`[Chargebee] Validation failed for '${actionName}': ${messages}`);
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ this.name = 'ChargebeeZodValidationError';
10
+ this.actionName = actionName;
11
+ this.zodError = zodError;
12
+ (_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
13
+ }
14
+ }
@@ -1,3 +1,14 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { RequestWrapper } from './RequestWrapper.js';
2
13
  import { Environment } from './environment.js';
3
14
  import { Endpoints } from './resources/api_endpoints.js';
@@ -7,10 +18,14 @@ import { WebhookHandler, createDefaultHandler, } from './resources/webhook/handl
7
18
  export const CreateChargebee = (httpClient) => {
8
19
  const Chargebee = function (conf) {
9
20
  this._env = Object.assign({}, Environment);
10
- extend(true, this._env, conf);
21
+ const { telemetryAdapter, httpClient: configHttpClient } = conf, confToMerge = __rest(conf, ["telemetryAdapter", "httpClient"]);
22
+ extend(true, this._env, confToMerge);
11
23
  // @ts-ignore
12
24
  this._env.httpClient =
13
- conf.httpClient != null ? conf.httpClient : httpClient;
25
+ configHttpClient != null ? configHttpClient : httpClient;
26
+ if (telemetryAdapter !== undefined) {
27
+ this._env.telemetryAdapter = telemetryAdapter;
28
+ }
14
29
  this._buildResources();
15
30
  this._endpoints = Endpoints;
16
31
  // Initialize webhooks handler with auto-configured Basic Auth (if env vars are set)
@@ -82,6 +97,7 @@ export const CreateChargebee = (httpClient) => {
82
97
  for (let apiIdx = 0; apiIdx < apiCalls.length; apiIdx++) {
83
98
  const metaArr = apiCalls[apiIdx];
84
99
  const apiCall = {
100
+ resource: res,
85
101
  methodName: metaArr[0],
86
102
  httpMethod: metaArr[1],
87
103
  urlPrefix: metaArr[2],
@@ -93,6 +109,11 @@ export const CreateChargebee = (httpClient) => {
93
109
  jsonKeys: metaArr[7],
94
110
  options: metaArr[8],
95
111
  };
112
+ if (this._env.enableValidation) {
113
+ // Store resource and action for lazy schema loading in RequestWrapper
114
+ apiCall.resourceKey = res;
115
+ apiCall.actionName = metaArr[0];
116
+ }
96
117
  this[res][apiCall.methodName] = this._createApiFunc(apiCall, this._env);
97
118
  }
98
119
  }
@@ -8,7 +8,7 @@ export const Environment = {
8
8
  hostSuffix: '.chargebee.com',
9
9
  apiPath: '/api/v2',
10
10
  timeout: DEFAULT_TIME_OUT,
11
- clientVersion: 'v3.26.0',
11
+ clientVersion: 'v3.28.0',
12
12
  port: DEFAULT_PORT,
13
13
  timemachineWaitInMillis: DEFAULT_TIME_MACHINE_WAIT,
14
14
  exportWaitInMillis: DEFAULT_EXPORT_WAIT,