@stripe/extensibility-dev-tools 0.23.5

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 (253) hide show
  1. package/LICENSE.md +19 -0
  2. package/dist/bin/build-custom-object-definitions.cjs +2111 -0
  3. package/dist/bin/build-custom-object-definitions.d.ts +11 -0
  4. package/dist/bin/build-custom-object-definitions.d.ts.map +1 -0
  5. package/dist/bin/build-custom-object-definitions.js +2088 -0
  6. package/dist/bin/create-upload-image.cjs +2136 -0
  7. package/dist/bin/create-upload-image.d.ts +17 -0
  8. package/dist/bin/create-upload-image.d.ts.map +1 -0
  9. package/dist/bin/create-upload-image.js +2113 -0
  10. package/dist/bin/dev-tools-rpc.cjs +3874 -0
  11. package/dist/bin/dev-tools-rpc.d.ts +3 -0
  12. package/dist/bin/dev-tools-rpc.d.ts.map +1 -0
  13. package/dist/bin/dev-tools-rpc.js +3864 -0
  14. package/dist/bin/gen-schemas.cjs +20739 -0
  15. package/dist/bin/gen-schemas.d.ts +8 -0
  16. package/dist/bin/gen-schemas.d.ts.map +1 -0
  17. package/dist/bin/gen-schemas.js +20715 -0
  18. package/dist/bin/gen-workspace.cjs +3847 -0
  19. package/dist/bin/gen-workspace.d.ts +8 -0
  20. package/dist/bin/gen-workspace.d.ts.map +1 -0
  21. package/dist/bin/gen-workspace.js +3841 -0
  22. package/dist/bin/manifest.cjs +686 -0
  23. package/dist/bin/manifest.d.ts +10 -0
  24. package/dist/bin/manifest.d.ts.map +1 -0
  25. package/dist/bin/manifest.js +663 -0
  26. package/dist/bin/rpc/dispatch.d.ts +10 -0
  27. package/dist/bin/rpc/dispatch.d.ts.map +1 -0
  28. package/dist/bin/rpc/handlers.d.ts +4 -0
  29. package/dist/bin/rpc/handlers.d.ts.map +1 -0
  30. package/dist/bin/rpc/types.d.ts +29 -0
  31. package/dist/bin/rpc/types.d.ts.map +1 -0
  32. package/dist/bin/template-info.cjs +1511 -0
  33. package/dist/bin/template-info.d.ts +9 -0
  34. package/dist/bin/template-info.d.ts.map +1 -0
  35. package/dist/bin/template-info.js +1488 -0
  36. package/dist/custom-objects/build-definitions.d.ts +98 -0
  37. package/dist/custom-objects/build-definitions.d.ts.map +1 -0
  38. package/dist/custom-objects/generated/proto/custom_objects/pub/api/app_api/object_definitions_app_service.pb.d.ts +191 -0
  39. package/dist/custom-objects/generated/proto/custom_objects/pub/api/app_api/object_definitions_app_service.pb.d.ts.map +1 -0
  40. package/dist/custom-objects/generated/proto/custom_objects/pub/api/common/schema.pb.d.ts +131 -0
  41. package/dist/custom-objects/generated/proto/custom_objects/pub/api/common/schema.pb.d.ts.map +1 -0
  42. package/dist/custom-objects/generated/proto/google/protobuf/descriptor.pb.d.ts +1482 -0
  43. package/dist/custom-objects/generated/proto/google/protobuf/descriptor.pb.d.ts.map +1 -0
  44. package/dist/custom-objects/generated/proto/google/protobuf/timestamp.pb.d.ts +167 -0
  45. package/dist/custom-objects/generated/proto/google/protobuf/timestamp.pb.d.ts.map +1 -0
  46. package/dist/custom-objects/generated/proto/proto/annotations.pb.d.ts +64 -0
  47. package/dist/custom-objects/generated/proto/proto/annotations.pb.d.ts.map +1 -0
  48. package/dist/custom-objects/generated/proto/proto/extensions.pb.d.ts +657 -0
  49. package/dist/custom-objects/generated/proto/proto/extensions.pb.d.ts.map +1 -0
  50. package/dist/custom-objects/generated/proto/vendor/metadata/pub/api/api_metadata.pb.d.ts +105 -0
  51. package/dist/custom-objects/generated/proto/vendor/metadata/pub/api/api_metadata.pb.d.ts.map +1 -0
  52. package/dist/custom-objects/generated/proto/vendor/net/idempotency/idempotency_model.pb.d.ts +79 -0
  53. package/dist/custom-objects/generated/proto/vendor/net/idempotency/idempotency_model.pb.d.ts.map +1 -0
  54. package/dist/custom-objects/generated/proto/vendor/publicapi/api_group_enum.pb.d.ts +129 -0
  55. package/dist/custom-objects/generated/proto/vendor/publicapi/api_group_enum.pb.d.ts.map +1 -0
  56. package/dist/custom-objects/generated/proto/vendor/publicapi/api_visibility.pb.d.ts +76 -0
  57. package/dist/custom-objects/generated/proto/vendor/publicapi/api_visibility.pb.d.ts.map +1 -0
  58. package/dist/custom-objects/generated/proto/vendor/publicapi/customize_dispatch_middleware_enum.pb.d.ts +78 -0
  59. package/dist/custom-objects/generated/proto/vendor/publicapi/customize_dispatch_middleware_enum.pb.d.ts.map +1 -0
  60. package/dist/custom-objects/generated/proto/vendor/publicapi/docs_namespace_group_enum.pb.d.ts +146 -0
  61. package/dist/custom-objects/generated/proto/vendor/publicapi/docs_namespace_group_enum.pb.d.ts.map +1 -0
  62. package/dist/custom-objects/generated/proto/vendor/publicapi/documented_enum.pb.d.ts +76 -0
  63. package/dist/custom-objects/generated/proto/vendor/publicapi/documented_enum.pb.d.ts.map +1 -0
  64. package/dist/custom-objects/generated/proto/vendor/publicapi/event_scope_enum.pb.d.ts +92 -0
  65. package/dist/custom-objects/generated/proto/vendor/publicapi/event_scope_enum.pb.d.ts.map +1 -0
  66. package/dist/custom-objects/generated/proto/vendor/publicapi/extension_interface.pb.d.ts +124 -0
  67. package/dist/custom-objects/generated/proto/vendor/publicapi/extension_interface.pb.d.ts.map +1 -0
  68. package/dist/custom-objects/generated/proto/vendor/publicapi/feature_enum.pb.d.ts +1070 -0
  69. package/dist/custom-objects/generated/proto/vendor/publicapi/feature_enum.pb.d.ts.map +1 -0
  70. package/dist/custom-objects/generated/proto/vendor/publicapi/field_validation_rules.pb.d.ts +279 -0
  71. package/dist/custom-objects/generated/proto/vendor/publicapi/field_validation_rules.pb.d.ts.map +1 -0
  72. package/dist/custom-objects/generated/proto/vendor/publicapi/flavor_enum.pb.d.ts +78 -0
  73. package/dist/custom-objects/generated/proto/vendor/publicapi/flavor_enum.pb.d.ts.map +1 -0
  74. package/dist/custom-objects/generated/proto/vendor/publicapi/http_error_status.pb.d.ts +102 -0
  75. package/dist/custom-objects/generated/proto/vendor/publicapi/http_error_status.pb.d.ts.map +1 -0
  76. package/dist/custom-objects/generated/proto/vendor/publicapi/method_kind_enum.pb.d.ts +86 -0
  77. package/dist/custom-objects/generated/proto/vendor/publicapi/method_kind_enum.pb.d.ts.map +1 -0
  78. package/dist/custom-objects/generated/proto/vendor/publicapi/method_priority.pb.d.ts +80 -0
  79. package/dist/custom-objects/generated/proto/vendor/publicapi/method_priority.pb.d.ts.map +1 -0
  80. package/dist/custom-objects/generated/proto/vendor/publicapi/permission_check_enum.pb.d.ts +74 -0
  81. package/dist/custom-objects/generated/proto/vendor/publicapi/permission_check_enum.pb.d.ts.map +1 -0
  82. package/dist/custom-objects/generated/proto/vendor/publicapi/redaction_enum.pb.d.ts +76 -0
  83. package/dist/custom-objects/generated/proto/vendor/publicapi/redaction_enum.pb.d.ts.map +1 -0
  84. package/dist/custom-objects/generated/proto/vendor/publicapi/region_routers.pb.d.ts +103 -0
  85. package/dist/custom-objects/generated/proto/vendor/publicapi/region_routers.pb.d.ts.map +1 -0
  86. package/dist/custom-objects/generated/proto/vendor/publicapi/rollout_configs.pb.d.ts +153 -0
  87. package/dist/custom-objects/generated/proto/vendor/publicapi/rollout_configs.pb.d.ts.map +1 -0
  88. package/dist/custom-objects/generated/proto/vendor/publicapi/v2ext.pb.d.ts +1111 -0
  89. package/dist/custom-objects/generated/proto/vendor/publicapi/v2ext.pb.d.ts.map +1 -0
  90. package/dist/custom-objects/generated/proto/vendor/vext/annotations.pb.d.ts +602 -0
  91. package/dist/custom-objects/generated/proto/vendor/vext/annotations.pb.d.ts.map +1 -0
  92. package/dist/custom-objects/generated/proto/vendor/vext/extensions.pb.d.ts +144 -0
  93. package/dist/custom-objects/generated/proto/vendor/vext/extensions.pb.d.ts.map +1 -0
  94. package/dist/custom-objects/generated/proto/vendor/vext/privacy_unified_annotations.pb.d.ts +851 -0
  95. package/dist/custom-objects/generated/proto/vendor/vext/privacy_unified_annotations.pb.d.ts.map +1 -0
  96. package/dist/custom-objects/generated/proto/vendor/vext/xml_annotations.pb.d.ts +125 -0
  97. package/dist/custom-objects/generated/proto/vendor/vext/xml_annotations.pb.d.ts.map +1 -0
  98. package/dist/custom-objects/to-proto-json.d.ts +17 -0
  99. package/dist/custom-objects/to-proto-json.d.ts.map +1 -0
  100. package/dist/dependencies/index.cjs +601 -0
  101. package/dist/dependencies/index.d.ts +320 -0
  102. package/dist/dependencies/index.d.ts.map +1 -0
  103. package/dist/dependencies/index.js +560 -0
  104. package/dist/extensibility-dev-tools-alpha.d.ts +199 -0
  105. package/dist/extensibility-dev-tools-beta.d.ts +199 -0
  106. package/dist/extensibility-dev-tools-dependencies-alpha.d.ts +51 -0
  107. package/dist/extensibility-dev-tools-dependencies-beta.d.ts +51 -0
  108. package/dist/extensibility-dev-tools-dependencies-internal.d.ts +372 -0
  109. package/dist/extensibility-dev-tools-dependencies-public.d.ts +51 -0
  110. package/dist/extensibility-dev-tools-internal.d.ts +1722 -0
  111. package/dist/extensibility-dev-tools-jsonschema-tools-alpha.d.ts +57 -0
  112. package/dist/extensibility-dev-tools-jsonschema-tools-beta.d.ts +57 -0
  113. package/dist/extensibility-dev-tools-jsonschema-tools-internal.d.ts +123 -0
  114. package/dist/extensibility-dev-tools-jsonschema-tools-public.d.ts +57 -0
  115. package/dist/extensibility-dev-tools-manifest-alpha.d.ts +31 -0
  116. package/dist/extensibility-dev-tools-manifest-beta.d.ts +31 -0
  117. package/dist/extensibility-dev-tools-manifest-internal.d.ts +461 -0
  118. package/dist/extensibility-dev-tools-manifest-public.d.ts +31 -0
  119. package/dist/extensibility-dev-tools-public.d.ts +199 -0
  120. package/dist/extensibility-dev-tools-schemas-alpha.d.ts +9 -0
  121. package/dist/extensibility-dev-tools-schemas-beta.d.ts +9 -0
  122. package/dist/extensibility-dev-tools-schemas-internal.d.ts +41 -0
  123. package/dist/extensibility-dev-tools-schemas-public.d.ts +9 -0
  124. package/dist/extensibility-dev-tools-templates-alpha.d.ts +67 -0
  125. package/dist/extensibility-dev-tools-templates-beta.d.ts +67 -0
  126. package/dist/extensibility-dev-tools-templates-internal.d.ts +554 -0
  127. package/dist/extensibility-dev-tools-templates-public.d.ts +67 -0
  128. package/dist/extensibility-dev-tools-workspace-alpha.d.ts +51 -0
  129. package/dist/extensibility-dev-tools-workspace-beta.d.ts +51 -0
  130. package/dist/extensibility-dev-tools-workspace-internal.d.ts +410 -0
  131. package/dist/extensibility-dev-tools-workspace-public.d.ts +51 -0
  132. package/dist/index.cjs +3810 -0
  133. package/dist/index.d.ts +18 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +3758 -0
  136. package/dist/jsonschema-tools.cjs +20451 -0
  137. package/dist/jsonschema-tools.d.ts +98 -0
  138. package/dist/jsonschema-tools.d.ts.map +1 -0
  139. package/dist/jsonschema-tools.js +20404 -0
  140. package/dist/manifest/index.cjs +610 -0
  141. package/dist/manifest/index.d.ts +8 -0
  142. package/dist/manifest/index.d.ts.map +1 -0
  143. package/dist/manifest/index.js +571 -0
  144. package/dist/manifest/manifest-v1.d.ts +102 -0
  145. package/dist/manifest/manifest-v1.d.ts.map +1 -0
  146. package/dist/manifest/manifest-v2.d.ts +253 -0
  147. package/dist/manifest/manifest-v2.d.ts.map +1 -0
  148. package/dist/manifest/stripe-app-manifest.d.ts +114 -0
  149. package/dist/manifest/stripe-app-manifest.d.ts.map +1 -0
  150. package/dist/schemas/index.cjs +20692 -0
  151. package/dist/schemas/index.d.ts +37 -0
  152. package/dist/schemas/index.d.ts.map +1 -0
  153. package/dist/schemas/index.js +20656 -0
  154. package/dist/templates/diff-viewer/diff-generator.d.ts +22 -0
  155. package/dist/templates/diff-viewer/diff-generator.d.ts.map +1 -0
  156. package/dist/templates/diff-viewer/diff-prompt.d.ts +13 -0
  157. package/dist/templates/diff-viewer/diff-prompt.d.ts.map +1 -0
  158. package/dist/templates/diff-viewer/index.d.ts +7 -0
  159. package/dist/templates/diff-viewer/index.d.ts.map +1 -0
  160. package/dist/templates/diff-viewer/terminal-renderer.d.ts +29 -0
  161. package/dist/templates/diff-viewer/terminal-renderer.d.ts.map +1 -0
  162. package/dist/templates/diff-viewer/types.d.ts +58 -0
  163. package/dist/templates/diff-viewer/types.d.ts.map +1 -0
  164. package/dist/templates/extensions/base.d.ts +23 -0
  165. package/dist/templates/extensions/base.d.ts.map +1 -0
  166. package/dist/templates/extensions/billing.bill.discount_calculation.d.ts +6 -0
  167. package/dist/templates/extensions/billing.bill.discount_calculation.d.ts.map +1 -0
  168. package/dist/templates/extensions/billing.customer_balance_application.d.ts +6 -0
  169. package/dist/templates/extensions/billing.customer_balance_application.d.ts.map +1 -0
  170. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts +6 -0
  171. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts.map +1 -0
  172. package/dist/templates/extensions/billing.prorations.d.ts +6 -0
  173. package/dist/templates/extensions/billing.prorations.d.ts.map +1 -0
  174. package/dist/templates/extensions/billing.recurring_billing_item_handling.d.ts +6 -0
  175. package/dist/templates/extensions/billing.recurring_billing_item_handling.d.ts.map +1 -0
  176. package/dist/templates/extensions/core.workflows.custom_action.d.ts +6 -0
  177. package/dist/templates/extensions/core.workflows.custom_action.d.ts.map +1 -0
  178. package/dist/templates/extensions/extend.objects.custom_objects.d.ts +6 -0
  179. package/dist/templates/extensions/extend.objects.custom_objects.d.ts.map +1 -0
  180. package/dist/templates/extensions/extend.workflows.custom_action.d.ts +6 -0
  181. package/dist/templates/extensions/extend.workflows.custom_action.d.ts.map +1 -0
  182. package/dist/templates/extensions/index.d.ts +13 -0
  183. package/dist/templates/extensions/index.d.ts.map +1 -0
  184. package/dist/templates/extensions/registry.d.ts +10 -0
  185. package/dist/templates/extensions/registry.d.ts.map +1 -0
  186. package/dist/templates/extensions/types.d.ts +104 -0
  187. package/dist/templates/extensions/types.d.ts.map +1 -0
  188. package/dist/templates/file-writer.d.ts +140 -0
  189. package/dist/templates/file-writer.d.ts.map +1 -0
  190. package/dist/templates/fs/_impl.d.ts +29 -0
  191. package/dist/templates/fs/_impl.d.ts.map +1 -0
  192. package/dist/templates/fs/filesystem.d.ts +8 -0
  193. package/dist/templates/fs/filesystem.d.ts.map +1 -0
  194. package/dist/templates/fs/in-memory.d.ts +9 -0
  195. package/dist/templates/fs/in-memory.d.ts.map +1 -0
  196. package/dist/templates/fs/index.d.ts +25 -0
  197. package/dist/templates/fs/index.d.ts.map +1 -0
  198. package/dist/templates/fs-utils.d.ts +17 -0
  199. package/dist/templates/fs-utils.d.ts.map +1 -0
  200. package/dist/templates/index.cjs +2248 -0
  201. package/dist/templates/index.d.ts +32 -0
  202. package/dist/templates/index.d.ts.map +1 -0
  203. package/dist/templates/index.js +2203 -0
  204. package/dist/templates/root/index.d.ts +60 -0
  205. package/dist/templates/root/index.d.ts.map +1 -0
  206. package/dist/templates/simple-templates.d.ts +8 -0
  207. package/dist/templates/simple-templates.d.ts.map +1 -0
  208. package/dist/templates/template-manager.d.ts +8 -0
  209. package/dist/templates/template-manager.d.ts.map +1 -0
  210. package/dist/templates/types.d.ts +9 -0
  211. package/dist/templates/types.d.ts.map +1 -0
  212. package/dist/tsconfig.build.tsbuildinfo +1 -0
  213. package/dist/workspace/index.cjs +3756 -0
  214. package/dist/workspace/index.d.ts +336 -0
  215. package/dist/workspace/index.d.ts.map +1 -0
  216. package/dist/workspace/index.js +3731 -0
  217. package/package.json +137 -0
  218. package/templates/extensions/billing.bill.discount_calculation/index.test.ts +15 -0
  219. package/templates/extensions/billing.bill.discount_calculation/index.ts +20 -0
  220. package/templates/extensions/billing.customer_balance_application/index.test.ts +15 -0
  221. package/templates/extensions/billing.customer_balance_application/index.ts +18 -0
  222. package/templates/extensions/billing.invoice_collection_setting/index.test.ts +15 -0
  223. package/templates/extensions/billing.invoice_collection_setting/index.ts +16 -0
  224. package/templates/extensions/billing.prorations/index.test.ts +15 -0
  225. package/templates/extensions/billing.prorations/index.ts +18 -0
  226. package/templates/extensions/billing.recurring_billing_item_handling/index.test.ts +15 -0
  227. package/templates/extensions/billing.recurring_billing_item_handling/index.ts +42 -0
  228. package/templates/extensions/common/.prettierignore +3 -0
  229. package/templates/extensions/common/eslint.config.mts.mustache +95 -0
  230. package/templates/extensions/common/package.json.mustache +26 -0
  231. package/templates/extensions/common/tsconfig.build.json.mustache +15 -0
  232. package/templates/extensions/common/tsconfig.json.mustache +16 -0
  233. package/templates/extensions/core.workflows.custom_action/custom_input.schema.json +6 -0
  234. package/templates/extensions/core.workflows.custom_action/index.test.ts +15 -0
  235. package/templates/extensions/core.workflows.custom_action/index.ts +31 -0
  236. package/templates/extensions/extend.workflows.custom_action/custom_input.schema.json +6 -0
  237. package/templates/extensions/extend.workflows.custom_action/index.test.ts +15 -0
  238. package/templates/extensions/extend.workflows.custom_action/index.ts +31 -0
  239. package/templates/root/.husky/pre-commit +1 -0
  240. package/templates/root/.prettierignore +5 -0
  241. package/templates/root/.prettierrc +7 -0
  242. package/templates/root/_gitignore +28 -0
  243. package/templates/root/custom-objects/package.json +20 -0
  244. package/templates/root/custom-objects/tsconfig.json +9 -0
  245. package/templates/root/eslint.config.mts +95 -0
  246. package/templates/root/package.json.mustache +32 -0
  247. package/templates/root/pnpm-workspace.yaml +7 -0
  248. package/templates/root/stripe-app.yaml.mustache +6 -0
  249. package/templates/root/tools/test.mts +38 -0
  250. package/templates/root/tsconfig.base.json +23 -0
  251. package/templates/root/tsconfig.json +15 -0
  252. package/templates/root/ui/package.json +17 -0
  253. package/templates/root/vitest.config.mts +47 -0
@@ -0,0 +1,1488 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/template-info.ts
4
+ import yargs from "yargs";
5
+ import { hideBin } from "yargs/helpers";
6
+ import { _createLogger, _writeJsonOutput } from "@stripe/extensibility-tool-utils";
7
+
8
+ // src/templates/template-manager.ts
9
+ import { _TemplateManager } from "@stripe/extensibility-tool-utils";
10
+
11
+ // src/templates/extensions/types.ts
12
+ var _ExtensionTemplateManager = class extends _TemplateManager {
13
+ /**
14
+ * Get summary info for all registered extension templates
15
+ */
16
+ getTemplateInfo() {
17
+ return this.getTemplateEntries().map(([key, t]) => ({
18
+ key,
19
+ description: t.description,
20
+ deprecated: t.deprecated ?? false,
21
+ hidden: t.hidden ?? false,
22
+ methods: t.methods
23
+ }));
24
+ }
25
+ };
26
+
27
+ // src/templates/fs/in-memory.ts
28
+ import { _createInMemoryTemplateFS } from "@stripe/extensibility-tool-utils";
29
+
30
+ // templates-virtual:./_impl.js
31
+ var TEMPLATE_FS_IMAGE = [
32
+ {
33
+ path: "extensions/billing.bill.discount_calculation/index.test.ts",
34
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
35
+
36
+ import MyDiscountCalculation from './index.js';
37
+
38
+ describe('MyDiscountCalculation', () => {
39
+ let instance: MyDiscountCalculation;
40
+
41
+ beforeEach(() => {
42
+ instance = new MyDiscountCalculation();
43
+ });
44
+
45
+ it('should be constructable', () => {
46
+ expect(instance).toBeInstanceOf(MyDiscountCalculation);
47
+ });
48
+ });
49
+ `
50
+ },
51
+ {
52
+ path: "extensions/billing.bill.discount_calculation/index.ts",
53
+ content: `import type { Billing } from '@stripe/extensibility-sdk/extensions';
54
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
55
+
56
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
57
+ interface MyDiscountCalculationConfig extends Record<string, unknown> {}
58
+
59
+ export default class MyDiscountCalculation implements Billing.Bill
60
+ .DiscountCalculation<MyDiscountCalculationConfig> {
61
+ computeDiscounts(
62
+ request: Billing.Bill.DiscountCalculation.DiscountableItem,
63
+ _config: MyDiscountCalculationConfig,
64
+ _context: Context
65
+ ) {
66
+ // TODO: implement your discount logic here
67
+
68
+ return {
69
+ discount: { amount: request.grossAmount },
70
+ };
71
+ }
72
+ }
73
+ `
74
+ },
75
+ {
76
+ path: "extensions/billing.customer_balance_application/index.test.ts",
77
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
78
+
79
+ import MyCustomerBalanceApplication from './index.js';
80
+
81
+ describe('MyCustomerBalanceApplication', () => {
82
+ let instance: MyCustomerBalanceApplication;
83
+
84
+ beforeEach(() => {
85
+ instance = new MyCustomerBalanceApplication();
86
+ });
87
+
88
+ it('should be constructable', () => {
89
+ expect(instance).toBeInstanceOf(MyCustomerBalanceApplication);
90
+ });
91
+ });
92
+ `
93
+ },
94
+ {
95
+ path: "extensions/billing.customer_balance_application/index.ts",
96
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
97
+
98
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
99
+ interface MyCustomerBalanceApplicationConfig extends Record<string, unknown> {}
100
+
101
+ export default class MyCustomerBalanceApplication implements Billing.CustomerBalanceApplication<MyCustomerBalanceApplicationConfig> {
102
+ computeAppliedCustomerBalance(
103
+ request: Billing.CustomerBalanceApplication.CustomerBalanceApplicationInput,
104
+ _config: MyCustomerBalanceApplicationConfig,
105
+ _context: Context
106
+ ) {
107
+ // TODO: implement your customer balance logic here
108
+
109
+ return {
110
+ appliedCustomerBalance: request.customerBalance,
111
+ };
112
+ }
113
+ }
114
+ `
115
+ },
116
+ {
117
+ path: "extensions/billing.invoice_collection_setting/index.test.ts",
118
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
119
+
120
+ import MyInvoiceCollectionSetting from './index.js';
121
+
122
+ describe('MyInvoiceCollectionSetting', () => {
123
+ let instance: MyInvoiceCollectionSetting;
124
+
125
+ beforeEach(() => {
126
+ instance = new MyInvoiceCollectionSetting();
127
+ });
128
+
129
+ it('should be constructable', () => {
130
+ expect(instance).toBeInstanceOf(MyInvoiceCollectionSetting);
131
+ });
132
+ });
133
+ `
134
+ },
135
+ {
136
+ path: "extensions/billing.invoice_collection_setting/index.ts",
137
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
138
+
139
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
140
+ interface MyInvoiceCollectionSettingConfig extends Record<string, unknown> {}
141
+
142
+ export default class MyInvoiceCollectionSetting implements Billing.InvoiceCollectionSetting<MyInvoiceCollectionSettingConfig> {
143
+ collectionOverride(
144
+ _request: Billing.InvoiceCollectionSetting.InvoiceCollectionRequest,
145
+ _config: MyInvoiceCollectionSettingConfig,
146
+ _context: Context
147
+ ) {
148
+ // TODO: implement your collection setting logic here
149
+
150
+ return {};
151
+ }
152
+ }
153
+ `
154
+ },
155
+ {
156
+ path: "extensions/billing.prorations/index.test.ts",
157
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
158
+
159
+ import MyProrations from './index.js';
160
+
161
+ describe('MyProrations', () => {
162
+ let instance: MyProrations;
163
+
164
+ beforeEach(() => {
165
+ instance = new MyProrations();
166
+ });
167
+
168
+ it('should be constructable', () => {
169
+ expect(instance).toBeInstanceOf(MyProrations);
170
+ });
171
+ });
172
+ `
173
+ },
174
+ {
175
+ path: "extensions/billing.prorations/index.ts",
176
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
177
+
178
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
179
+ interface MyProrationsConfig extends Record<string, unknown> {}
180
+
181
+ export default class MyProrations implements Billing.Prorations<MyProrationsConfig> {
182
+ prorateItems(
183
+ _request: Billing.Prorations.ProrateItemsInput,
184
+ _config: MyProrationsConfig,
185
+ _context: Context
186
+ ) {
187
+ // TODO: implement your proration logic here
188
+
189
+ return {
190
+ items: [],
191
+ };
192
+ }
193
+ }
194
+ `
195
+ },
196
+ {
197
+ path: "extensions/billing.recurring_billing_item_handling/index.test.ts",
198
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
199
+
200
+ import MyRecurringBillingItemHandling from './index.js';
201
+
202
+ describe('MyRecurringBillingItemHandling', () => {
203
+ let instance: MyRecurringBillingItemHandling;
204
+
205
+ beforeEach(() => {
206
+ instance = new MyRecurringBillingItemHandling();
207
+ });
208
+
209
+ it('should be constructable', () => {
210
+ expect(instance).toBeInstanceOf(MyRecurringBillingItemHandling);
211
+ });
212
+ });
213
+ `
214
+ },
215
+ {
216
+ path: "extensions/billing.recurring_billing_item_handling/index.ts",
217
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
218
+
219
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
220
+ interface MyRecurringBillingItemHandlingConfig extends Record<string, unknown> {}
221
+
222
+ export default class MyRecurringBillingItemHandling implements Billing.RecurringBillingItemHandling<MyRecurringBillingItemHandlingConfig> {
223
+ beforeItemCreation(
224
+ _request: Billing.RecurringBillingItemHandling.BeforeItemCreationInput,
225
+ _config: MyRecurringBillingItemHandlingConfig,
226
+ _context: Context
227
+ ) {
228
+ // TODO: implement your before-item-creation logic here
229
+
230
+ return {
231
+ items: [],
232
+ };
233
+ }
234
+
235
+ filterItems(
236
+ _request: Billing.RecurringBillingItemHandling.FilterItemsInput,
237
+ _config: MyRecurringBillingItemHandlingConfig,
238
+ _context: Context
239
+ ) {
240
+ // TODO: implement your filter-items logic here
241
+
242
+ return {
243
+ items: [],
244
+ };
245
+ }
246
+
247
+ groupItems(
248
+ _request: Billing.RecurringBillingItemHandling.GroupItemsInput,
249
+ _config: MyRecurringBillingItemHandlingConfig,
250
+ _context: Context
251
+ ) {
252
+ // TODO: implement your group-items logic here
253
+
254
+ return {
255
+ groups: [],
256
+ };
257
+ }
258
+ }
259
+ `
260
+ },
261
+ {
262
+ path: "extensions/common/.prettierignore",
263
+ content: `dist
264
+ generated
265
+ node_modules
266
+ `
267
+ },
268
+ {
269
+ path: "extensions/common/eslint.config.mts.mustache",
270
+ content: `import eslint from '@eslint/js';
271
+ import { defineConfig } from 'eslint/config';
272
+ import tseslint from 'typescript-eslint';
273
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
274
+
275
+ import globals from 'globals';
276
+
277
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
278
+ import extensionTypeConfig from '@stripe/extensibility-eslint-plugin/{{extensionInterfaceId}}';
279
+
280
+ export default defineConfig([
281
+ eslint.configs.recommended,
282
+ ...tseslint.configs.recommended,
283
+ ...stripeAppsConfig,
284
+ ...extensionTypeConfig,
285
+
286
+ // Global ignores
287
+ {
288
+ ignores: ['dist', 'generated', 'node_modules'],
289
+ },
290
+
291
+ // TypeScript source files (with type-checking)
292
+ {
293
+ name: 'sources',
294
+ files: ['src/**/*.ts'],
295
+ ignores: ['**/*.test.ts', '**/__tests__/**'],
296
+ languageOptions: {
297
+ globals: {
298
+ ...globals.node,
299
+ },
300
+ parserOptions: {
301
+ projectService: true,
302
+ tsconfigRootDir: import.meta.dirname,
303
+ },
304
+ },
305
+ },
306
+
307
+ // Test files (type-checking, relaxed rules)
308
+ {
309
+ name: 'tests',
310
+ files: ['src/**/*.test.ts', 'src/**/__tests__/**/*.ts'],
311
+ languageOptions: {
312
+ globals: {
313
+ ...globals.node,
314
+ },
315
+ parserOptions: {
316
+ projectService: true,
317
+ tsconfigRootDir: import.meta.dirname,
318
+ },
319
+ },
320
+ rules: {
321
+ '@typescript-eslint/no-explicit-any': 'off',
322
+ '@typescript-eslint/no-unused-vars': 'off',
323
+ 'no-console': 'off',
324
+ },
325
+ },
326
+
327
+ // Config files
328
+ {
329
+ name: 'ts-configs',
330
+ files: ['*.config.m?ts', 'eslint.config.mts'],
331
+ languageOptions: {
332
+ globals: {
333
+ ...globals.node,
334
+ },
335
+ parserOptions: {
336
+ projectService: false,
337
+ },
338
+ },
339
+ rules: {
340
+ '@typescript-eslint/no-unused-vars': 'off',
341
+ },
342
+ },
343
+
344
+ // JavaScript/MJS files (scripts, configs)
345
+ {
346
+ name: 'js-configs',
347
+ files: ['**/*.js', '**/*.mjs'],
348
+ languageOptions: {
349
+ globals: {
350
+ ...globals.node,
351
+ },
352
+ parserOptions: {
353
+ projectService: false,
354
+ },
355
+ },
356
+ rules: {
357
+ '@typescript-eslint/no-require-imports': 'off',
358
+ '@typescript-eslint/no-unused-vars': 'off',
359
+ 'no-unused-vars': 'off',
360
+ },
361
+ },
362
+
363
+ eslintConfigPrettier,
364
+ ]);
365
+ `
366
+ },
367
+ {
368
+ path: "extensions/common/package.json.mustache",
369
+ content: `{
370
+ "name": "{{id}}",
371
+ "version": "{{version}}",
372
+ "description": "{{name}}",
373
+ "private": true,
374
+ "license": "~~proprietary~~",
375
+ "type": "module",
376
+ "scripts": {
377
+ "build": "tsc -p tsconfig.build.json && pnpm build:schemas",
378
+ "build:schemas": "gen-schemas --root ../.. --extension-id \\"$npm_package_name\\" --out-dir generated --schema-name config",
379
+ "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
380
+ "lint:types": "tsc -p tsconfig.build.json --noEmit && tsc -p tsconfig.json --noEmit",
381
+ "lint:eslint": "eslint .",
382
+ "lint:format": "prettier --check .",
383
+ "fix:lint": "eslint --fix .",
384
+ "fix:format": "prettier --write .",
385
+ "test": "vitest --root ../.. run --project \\"$npm_package_name\\"",
386
+ "test:watch": "pnpm test --watch",
387
+ "dev": "concurrently -n build,lint,test -c blue,yellow,green 'tsc -p tsconfig.json -w --noEmit' 'chokidar \\"src/**/*.{ts,json}\\" -c \\"eslint .\\"' 'pnpm test --watch --no-clear-screen'",
388
+ "stripe:regen": "gen-workspace --root ../.. --package-dir . --template-id {{extensionInterfaceId}}"
389
+ },
390
+ "lint-staged": {
391
+ "*.{ts,mts,mjs,js}": ["eslint --fix", "prettier --write"],
392
+ "*.{json,md,yaml}": "prettier --write"
393
+ }
394
+ }
395
+ `
396
+ },
397
+ {
398
+ path: "extensions/common/tsconfig.build.json.mustache",
399
+ content: `{
400
+ "extends": "../../tsconfig.base.json",
401
+ "compilerOptions": {
402
+ "lib": null,
403
+ "noLib": true,
404
+ "outDir": "./dist",
405
+ "rootDir": "./src"
406
+ },
407
+ "include": [
408
+ "src/**/*.ts",
409
+ "node_modules/@stripe/extensibility-sdk/tslibs/5.9.3/lib.es2022.{{executionProfile}}.d.ts",
410
+ "node_modules/@stripe/extensibility-sdk/tslibs/lib.{{executionProfile}}.globals.d.ts"
411
+ ],
412
+ "exclude": ["src/**/*.test.ts", "src/**/__tests__"]
413
+ }
414
+ `
415
+ },
416
+ {
417
+ path: "extensions/common/tsconfig.json.mustache",
418
+ content: `{
419
+ "extends": "../../tsconfig.json",
420
+ "compilerOptions": {
421
+ "rootDir": ".",
422
+ "plugins": [
423
+ {
424
+ "name": "@stripe/extensibility-language-server/plugin"
425
+ }
426
+ ]
427
+ },
428
+ "include": [
429
+ "src/**/*.ts",
430
+ "node_modules/@stripe/extensibility-sdk/tslibs/lib.{{executionProfile}}.globals.d.ts"
431
+ ],
432
+ "exclude": ["dist"]
433
+ }
434
+ `
435
+ },
436
+ {
437
+ path: "extensions/core.workflows.custom_action/custom_input.schema.json",
438
+ content: `{
439
+ "$schema": "http://json-schema.org/draft-07/schema#",
440
+ "type": "object",
441
+ "properties": {},
442
+ "additionalProperties": false
443
+ }
444
+ `
445
+ },
446
+ {
447
+ path: "extensions/core.workflows.custom_action/index.test.ts",
448
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
449
+
450
+ import MyCustomAction from './index.js';
451
+
452
+ describe('MyCustomAction', () => {
453
+ let instance: MyCustomAction;
454
+
455
+ beforeEach(() => {
456
+ instance = new MyCustomAction();
457
+ });
458
+
459
+ it('should be constructable', () => {
460
+ expect(instance).toBeInstanceOf(MyCustomAction);
461
+ });
462
+ });
463
+ `
464
+ },
465
+ {
466
+ path: "extensions/core.workflows.custom_action/index.ts",
467
+ content: `import type { Core } from '@stripe/extensibility-sdk/extensions';
468
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
469
+
470
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
471
+ interface MyCustomActionConfig extends Record<string, unknown> {}
472
+
473
+ export default class MyCustomAction implements Core.Workflows
474
+ .CustomAction<MyCustomActionConfig> {
475
+ execute(
476
+ _request: Core.Workflows.CustomAction.ExecuteCustomActionRequest,
477
+ _config: MyCustomActionConfig,
478
+ _context: Context
479
+ ) {
480
+ // TODO: implement your action logic here
481
+
482
+ return {};
483
+ }
484
+
485
+ getFormState(
486
+ _request: Core.Workflows.CustomAction.GetFormStateRequest,
487
+ _config: MyCustomActionConfig,
488
+ _context: Context
489
+ ) {
490
+ // TODO: implement your logic here
491
+
492
+ return {
493
+ values: {},
494
+ config: {},
495
+ };
496
+ }
497
+ }
498
+ `
499
+ },
500
+ {
501
+ path: "extensions/extend.workflows.custom_action/custom_input.schema.json",
502
+ content: `{
503
+ "$schema": "http://json-schema.org/draft-07/schema#",
504
+ "type": "object",
505
+ "properties": {},
506
+ "additionalProperties": false
507
+ }
508
+ `
509
+ },
510
+ {
511
+ path: "extensions/extend.workflows.custom_action/index.test.ts",
512
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
513
+
514
+ import MyCustomAction from './index.js';
515
+
516
+ describe('MyCustomAction', () => {
517
+ let instance: MyCustomAction;
518
+
519
+ beforeEach(() => {
520
+ instance = new MyCustomAction();
521
+ });
522
+
523
+ it('should be constructable', () => {
524
+ expect(instance).toBeInstanceOf(MyCustomAction);
525
+ });
526
+ });
527
+ `
528
+ },
529
+ {
530
+ path: "extensions/extend.workflows.custom_action/index.ts",
531
+ content: `import type { Extend } from '@stripe/extensibility-sdk/extensions';
532
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
533
+
534
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
535
+ interface MyCustomActionConfig extends Record<string, unknown> {}
536
+
537
+ export default class MyCustomAction implements Extend.Workflows
538
+ .CustomAction<MyCustomActionConfig> {
539
+ execute(
540
+ _request: Extend.Workflows.CustomAction.ExecuteCustomActionRequest,
541
+ _config: MyCustomActionConfig,
542
+ _context: Context
543
+ ) {
544
+ // TODO: implement your action logic here
545
+
546
+ return {};
547
+ }
548
+
549
+ getFormState(
550
+ _request: Extend.Workflows.CustomAction.GetFormStateRequest,
551
+ _config: MyCustomActionConfig,
552
+ _context: Context
553
+ ) {
554
+ // TODO: implement your logic here
555
+
556
+ return {
557
+ values: {},
558
+ config: {},
559
+ };
560
+ }
561
+ }
562
+ `
563
+ },
564
+ {
565
+ path: "root/.husky/pre-commit",
566
+ content: `pnpm lint-staged
567
+ `
568
+ },
569
+ {
570
+ path: "root/.prettierignore",
571
+ content: `dist
572
+ generated
573
+ node_modules
574
+ pnpm-lock.yaml
575
+ .build
576
+ `
577
+ },
578
+ {
579
+ path: "root/.prettierrc",
580
+ content: `{
581
+ "semi": true,
582
+ "singleQuote": true,
583
+ "tabWidth": 2,
584
+ "trailingComma": "es5",
585
+ "printWidth": 90
586
+ }
587
+ `
588
+ },
589
+ {
590
+ path: "root/_gitignore",
591
+ content: `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
592
+
593
+ *~
594
+
595
+ # dependencies
596
+ node_modules
597
+ dist
598
+
599
+ # testing
600
+ /coverage
601
+
602
+ # production
603
+ /.build
604
+
605
+ # misc
606
+ .DS_Store
607
+ .env.local
608
+ .env.development.local
609
+ .env.test.local
610
+ .env.production.local
611
+
612
+ npm-debug.log*
613
+ yarn-debug.log*
614
+ yarn-error.log*
615
+ install-deps.log
616
+
617
+ # generated schemas
618
+ generated
619
+ `
620
+ },
621
+ {
622
+ path: "root/custom-objects/package.json",
623
+ content: `{
624
+ "name": "custom-objects",
625
+ "type": "module",
626
+ "version": "0.0.1",
627
+ "license": "UNLICENSED",
628
+ "private": true,
629
+ "scripts": {
630
+ "build": "test -d src && custom-objects-build --input src --output dist || true",
631
+ "lint:types": "test ! -d src || tsc --noEmit",
632
+ "test": "vitest run"
633
+ },
634
+ "dependencies": {
635
+ "@stripe/extensibility-custom-objects": "0.7.4",
636
+ "@stripe/extensibility-sdk": "0.22.4"
637
+ },
638
+ "devDependencies": {
639
+ "@stripe/extensibility-custom-objects-tools": "0.40.0",
640
+ "@stripe/extensibility-test-helpers": "0.2.7"
641
+ }
642
+ }
643
+ `
644
+ },
645
+ {
646
+ path: "root/custom-objects/tsconfig.json",
647
+ content: `{
648
+ "extends": "../tsconfig.base.json",
649
+ "compilerOptions": {
650
+ "module": "ESNext",
651
+ "moduleResolution": "bundler",
652
+ "types": ["vitest/globals"]
653
+ },
654
+ "exclude": ["dist"]
655
+ }
656
+ `
657
+ },
658
+ {
659
+ path: "root/eslint.config.mts",
660
+ content: `import { readFileSync } from 'node:fs';
661
+ import { dirname, resolve } from 'node:path';
662
+ import { fileURLToPath } from 'node:url';
663
+ import eslint from '@eslint/js';
664
+ import { defineConfig } from 'eslint/config';
665
+ import tseslint from 'typescript-eslint';
666
+ import workspaces from 'eslint-plugin-workspaces';
667
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
668
+
669
+ import globals from 'globals';
670
+
671
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
672
+
673
+ // Read additional ignore globs from package.json (written by the generate plugin
674
+ // to exclude generated SDK directories from linting).
675
+ let stripeGlobsToIgnore: string[] = [];
676
+ try {
677
+ const configDir = dirname(fileURLToPath(import.meta.url));
678
+ const packageJsonPath = resolve(configDir, './package.json');
679
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
680
+ const globs = pkg?.stripe?.eslintIgnoreGlobs;
681
+ if (Array.isArray(globs)) {
682
+ stripeGlobsToIgnore = globs.filter(
683
+ (g: unknown): g is string => typeof g === 'string'
684
+ );
685
+ }
686
+ } catch {
687
+ // package.json not found or unparseable \u2014 ignore
688
+ }
689
+
690
+ export default defineConfig([
691
+ eslint.configs.recommended,
692
+ ...tseslint.configs.recommended,
693
+ ...stripeAppsConfig,
694
+
695
+ // Global ignores
696
+ {
697
+ ignores: [
698
+ '.build',
699
+ '**/dist',
700
+ '**/generated',
701
+ '**/node_modules',
702
+ 'extensions/**',
703
+ 'custom-objects',
704
+ 'ui',
705
+ ...stripeGlobsToIgnore,
706
+ ],
707
+ },
708
+
709
+ // Common rules for all files
710
+ {
711
+ plugins: { workspaces },
712
+ rules: {
713
+ ...workspaces.configs.recommended.rules,
714
+ },
715
+ },
716
+
717
+ // Config files (vitest.config.ts, eslint.config.ts, etc.)
718
+ {
719
+ name: 'ts-configs',
720
+ files: ['extensions/*/*.config.m?ts', '*.config.m?ts', 'eslint.config.mts'],
721
+ languageOptions: {
722
+ globals: {
723
+ ...globals.node,
724
+ },
725
+ parserOptions: {
726
+ projectService: false,
727
+ },
728
+ },
729
+ rules: {
730
+ '@typescript-eslint/no-unused-vars': 'off',
731
+ },
732
+ },
733
+
734
+ // JavaScript/MJS files (scripts, configs)
735
+ {
736
+ name: 'js-configs',
737
+ files: ['**/*.js', '**/*.mjs'],
738
+ languageOptions: {
739
+ globals: {
740
+ ...globals.node,
741
+ },
742
+ parserOptions: {
743
+ projectService: false,
744
+ },
745
+ },
746
+ rules: {
747
+ '@typescript-eslint/no-require-imports': 'off',
748
+ '@typescript-eslint/no-unused-vars': 'off',
749
+ 'no-unused-vars': 'off',
750
+ },
751
+ },
752
+
753
+ eslintConfigPrettier,
754
+ ]);
755
+ `
756
+ },
757
+ {
758
+ path: "root/package.json.mustache",
759
+ content: `{
760
+ "name": "{{ appId }}",
761
+ "version": "{{ version }}",
762
+ "description": "{{ appName }}",
763
+ "private": true,
764
+ "license": "~~proprietary~~",
765
+ "engines": {
766
+ "node": ">=20.0.0"
767
+ },
768
+ "packageManager": "pnpm@10.30.3",
769
+ "scripts": {
770
+ "build": "pnpm -r --if-present build",
771
+ "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
772
+ "lint:types": "pnpm -r --if-present lint:types",
773
+ "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint",
774
+ "lint:format": "prettier --check .",
775
+ "fix:lint": "eslint --fix . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present fix:lint",
776
+ "fix:format": "prettier --write .",
777
+ "test": "tsx tools/test.mts",
778
+ "test:watch": "vitest watch",
779
+ "check": "pnpm build && pnpm lint && pnpm test",
780
+ "prepare": "husky",
781
+ "preimage": "pnpm install --lockfile-only && pnpm build && pnpm lint:types && pnpm lint:eslint && pnpm test",
782
+ "image": "rm -rf .build && create-upload-image .build",
783
+ "postimage": "cp pnpm-lock.yaml .build/",
784
+ "stripe:regen": "gen-workspace --package-dir ."
785
+ },
786
+ "lint-staged": {
787
+ "*.{ts,mts,mjs,js}": ["eslint --fix", "prettier --write"],
788
+ "*.{json,md,yaml}": "prettier --write"
789
+ }
790
+ }
791
+ `
792
+ },
793
+ {
794
+ path: "root/pnpm-workspace.yaml",
795
+ content: `packages:
796
+ - extensions/*
797
+ - custom-objects
798
+ - ui
799
+
800
+ overrides:
801
+ vite: ^6.0.0
802
+ `
803
+ },
804
+ {
805
+ path: "root/stripe-app.yaml.mustache",
806
+ content: `$schema: https://stripe.com/stripe-app/v2.0.0/schema
807
+ id: '{{ appId }}'
808
+ name: '{{ appName }}'
809
+ version: 0.0.1
810
+ declarations:
811
+ distribution_type: private
812
+ `
813
+ },
814
+ {
815
+ path: "root/tools/test.mts",
816
+ content: `#!/usr/bin/env tsx
817
+ /**
818
+ * Runs tests across the workspace:
819
+ * - vitest for script extensions and custom objects (extensions/*)
820
+ * - jest for UI extensions (ui/)
821
+ */
822
+ import { existsSync, readdirSync } from 'node:fs';
823
+ import { execSync } from 'node:child_process';
824
+
825
+ const hasExtensions =
826
+ existsSync('extensions') &&
827
+ readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
828
+
829
+ const hasUI = existsSync('ui/package.json');
830
+
831
+ let exitCode = 0;
832
+
833
+ function run(cmd: string): void {
834
+ try {
835
+ execSync(cmd, { stdio: 'inherit' });
836
+ } catch (e: unknown) {
837
+ exitCode = (e as NodeJS.ErrnoException & { status?: number }).status ?? 1;
838
+ }
839
+ }
840
+
841
+ if (hasExtensions) {
842
+ run('vitest run');
843
+ }
844
+
845
+ if (hasUI) {
846
+ try {
847
+ execSync('pnpm --filter "./ui" test', { stdio: 'inherit' });
848
+ } catch {
849
+ // UI test failures are non-fatal
850
+ }
851
+ }
852
+
853
+ process.exit(exitCode);
854
+ `
855
+ },
856
+ {
857
+ path: "root/tsconfig.base.json",
858
+ content: `{
859
+ "compilerOptions": {
860
+ "target": "ES2022",
861
+ "module": "NodeNext",
862
+ "moduleResolution": "NodeNext",
863
+ "lib": ["ES2022"],
864
+ "declaration": true,
865
+ "declarationMap": true,
866
+ "esModuleInterop": true,
867
+ "exactOptionalPropertyTypes": false,
868
+ "forceConsistentCasingInFileNames": true,
869
+ "isolatedModules": true,
870
+ "noFallthroughCasesInSwitch": true,
871
+ "noImplicitReturns": true,
872
+ "removeComments": false,
873
+ "resolveJsonModule": true,
874
+ "skipLibCheck": true,
875
+ "sourceMap": true,
876
+ "strict": true,
877
+ "types": [],
878
+ "verbatimModuleSyntax": true
879
+ }
880
+ }
881
+ `
882
+ },
883
+ {
884
+ path: "root/tsconfig.json",
885
+ content: `{
886
+ "extends": "./tsconfig.base.json",
887
+ "compilerOptions": {
888
+ "noEmit": true,
889
+ "plugins": [
890
+ {
891
+ "name": "@stripe/extensibility-language-server/plugin"
892
+ }
893
+ ],
894
+ "preserveWatchOutput": true,
895
+ "types": ["vitest/globals", "node"]
896
+ },
897
+ "include": ["**/*.ts"],
898
+ "exclude": ["**/node_modules", "**/dist"]
899
+ }
900
+ `
901
+ },
902
+ {
903
+ path: "root/ui/package.json",
904
+ content: `{
905
+ "name": "ui",
906
+ "version": "0.0.1",
907
+ "license": "UNLICENSED",
908
+ "private": true,
909
+ "scripts": {
910
+ "test": "jest --passWithNoTests"
911
+ },
912
+ "dependencies": {
913
+ "@stripe/ui-extension-sdk": "^9.1.0"
914
+ },
915
+ "devDependencies": {
916
+ "@stripe/ui-extension-tools": "^0.0.1",
917
+ "@types/jest": "^27.5.2",
918
+ "@types/react": "^17.0.2"
919
+ }
920
+ }
921
+ `
922
+ },
923
+ {
924
+ path: "root/vitest.config.mts",
925
+ content: `import { defineConfig } from 'vitest/config';
926
+ import { existsSync, readdirSync } from 'fs';
927
+ import { dirname, resolve } from 'path';
928
+ import { fileURLToPath } from 'url';
929
+
930
+ const rootDir = dirname(fileURLToPath(import.meta.url));
931
+ const extensionsDir = resolve(rootDir, 'extensions');
932
+
933
+ const extensionProjects = existsSync(extensionsDir)
934
+ ? readdirSync(extensionsDir)
935
+ .filter((name) => existsSync(resolve(extensionsDir, name, 'package.json')))
936
+ .map((name) => resolve(extensionsDir, name))
937
+ : [];
938
+
939
+ const coProjects = existsSync(resolve(rootDir, 'custom-objects/package.json'))
940
+ ? [resolve(rootDir, 'custom-objects')]
941
+ : [];
942
+
943
+ const projects = [...extensionProjects, ...coProjects];
944
+
945
+ if (projects.length === 0) {
946
+ console.debug(\`No vitest projects detected. This means either:
947
+ - You have no extension projects defined, in which case this warning is expected.
948
+ - There is an internal error detecting vitest projects relative to the project root
949
+ \${rootDir}.
950
+ \`);
951
+ }
952
+
953
+ export default projects.length > 0
954
+ ? defineConfig({
955
+ test: {
956
+ projects,
957
+ passWithNoTests: true,
958
+
959
+ // Only run tests from src, not compiled dist
960
+ exclude: ['**/node_modules', '**/dist'],
961
+ // Place snapshots alongside test files instead of in __snapshots__
962
+ snapshotFormat: {
963
+ escapeString: false,
964
+ printBasicPrototype: false,
965
+ },
966
+ resolveSnapshotPath: (testPath, snapExtension) => {
967
+ return testPath.replace(/\\.test\\.ts$/, \`.test\${snapExtension}\`);
968
+ },
969
+ },
970
+ })
971
+ : defineConfig({ test: { passWithNoTests: true, include: [] } });
972
+ `
973
+ }
974
+ ];
975
+ var _fs = _createInMemoryTemplateFS(TEMPLATE_FS_IMAGE);
976
+
977
+ // src/dependencies/index.ts
978
+ import path from "path";
979
+ import fs from "fs";
980
+ import os from "os";
981
+ import { execSync } from "child_process";
982
+ import PackageJson from "@npmcli/package-json";
983
+ import * as semver from "semver";
984
+ import { load as parseToml } from "js-toml";
985
+ import { _createCliContext } from "@stripe/extensibility-tool-utils";
986
+ function _npmDep(name, version) {
987
+ return { type: "npm", name, version };
988
+ }
989
+ function _devNpmDep(name, version) {
990
+ return { type: "dev-npm", name, version };
991
+ }
992
+
993
+ // src/templates/extensions/base.ts
994
+ import { _workspaceVersion } from "@stripe/extensibility-tool-utils";
995
+ var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
996
+ var LANGUAGE_SERVER_PACKAGE_NAME = "@stripe/extensibility-language-server";
997
+ var LANGUAGE_SERVER_PACKAGE_VERSION = "^0.2.0";
998
+ function _createExtensionEslintConfigFile(params, context) {
999
+ const { id, extensionInterfaceId } = params;
1000
+ const { fs: fs2 } = context;
1001
+ return {
1002
+ path: `extensions/${id}/eslint.config.mts`,
1003
+ content: fs2.mustache(
1004
+ { extensionInterfaceId },
1005
+ "common",
1006
+ "eslint.config.mts.mustache"
1007
+ ),
1008
+ precious: true
1009
+ };
1010
+ }
1011
+ function _createBaseOutput(params, context) {
1012
+ const { id } = params;
1013
+ const { fs: fs2 } = context;
1014
+ return {
1015
+ files: [
1016
+ {
1017
+ path: `extensions/${id}/package.json`,
1018
+ content: fs2.mustache(params, "common", "package.json.mustache")
1019
+ },
1020
+ {
1021
+ ..._createExtensionEslintConfigFile(params, context)
1022
+ },
1023
+ {
1024
+ path: `extensions/${id}/tsconfig.build.json`,
1025
+ content: fs2.mustache(params, "common", "tsconfig.build.json.mustache")
1026
+ },
1027
+ {
1028
+ path: `extensions/${id}/tsconfig.json`,
1029
+ content: fs2.mustache(params, "common", "tsconfig.json.mustache")
1030
+ },
1031
+ {
1032
+ path: `extensions/${id}/.prettierignore`,
1033
+ content: fs2.textFile("common", ".prettierignore")
1034
+ }
1035
+ ],
1036
+ methods: {},
1037
+ dependencies: {
1038
+ // Exact pin (no caret) — the SDK is tightly coupled to dev-tools and
1039
+ // must match the version that generated the extension scaffolding.
1040
+ runtime: [_npmDep(SDK_PACKAGE_NAME, _workspaceVersion(SDK_PACKAGE_NAME))],
1041
+ dev: [_devNpmDep(LANGUAGE_SERVER_PACKAGE_NAME, LANGUAGE_SERVER_PACKAGE_VERSION)]
1042
+ },
1043
+ postGenerationHooks: [
1044
+ {
1045
+ script: "build",
1046
+ description: "Build extension"
1047
+ },
1048
+ {
1049
+ exec: "prettier --write .",
1050
+ description: "Format generated files"
1051
+ }
1052
+ ]
1053
+ };
1054
+ }
1055
+
1056
+ // src/templates/extensions/core.workflows.custom_action.ts
1057
+ var EXTENSION_INTERFACE_ID = "core.workflows.custom_action";
1058
+ var customActionTemplate = {
1059
+ methods: {
1060
+ execute: { implementation_types: ["script", "remote-function"] },
1061
+ get_form_state: { implementation_types: ["script", "remote-function"] }
1062
+ },
1063
+ description: "Custom actions let your app define actions that users can add to their automated workflows. When a workflow triggers a custom action, Stripe calls your app to execute it.",
1064
+ generate: (params, context) => {
1065
+ const { id } = params;
1066
+ const { fs: fs2 } = context;
1067
+ const base = _createBaseOutput(
1068
+ {
1069
+ ...params,
1070
+ extensionInterfaceId: EXTENSION_INTERFACE_ID,
1071
+ executionProfile: "egress"
1072
+ },
1073
+ context
1074
+ );
1075
+ return {
1076
+ ...base,
1077
+ files: [
1078
+ {
1079
+ path: `extensions/${id}/src/index.ts`,
1080
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "index.ts"),
1081
+ precious: true
1082
+ },
1083
+ {
1084
+ path: `extensions/${id}/src/custom_input.schema.json`,
1085
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "custom_input.schema.json"),
1086
+ precious: true
1087
+ },
1088
+ {
1089
+ path: `extensions/${id}/src/index.test.ts`,
1090
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "index.test.ts"),
1091
+ precious: true
1092
+ },
1093
+ ...base.files
1094
+ ],
1095
+ methods: {
1096
+ execute: {
1097
+ implementation_type: "script",
1098
+ custom_input: {
1099
+ input_schema: {
1100
+ type: "json_schema",
1101
+ content: `extensions/${id}/src/custom_input.schema.json`
1102
+ }
1103
+ }
1104
+ },
1105
+ get_form_state: {
1106
+ implementation_type: "script"
1107
+ }
1108
+ }
1109
+ };
1110
+ }
1111
+ };
1112
+ var core_workflows_custom_action_default = {
1113
+ [EXTENSION_INTERFACE_ID]: customActionTemplate
1114
+ };
1115
+
1116
+ // src/templates/extensions/extend.objects.custom_objects.ts
1117
+ var EXTENSION_INTERFACE_ID2 = "extend.objects.custom_objects";
1118
+ var customObjectsTemplate = {
1119
+ methods: {
1120
+ execute_method: { implementation_types: ["script"] }
1121
+ },
1122
+ description: "Methods extension for custom object actions. Generated at build time \u2014 the transformed custom object class becomes the entry point.",
1123
+ hidden: true,
1124
+ generate: (params, context) => {
1125
+ const base = _createBaseOutput(
1126
+ {
1127
+ ...params,
1128
+ extensionInterfaceId: EXTENSION_INTERFACE_ID2,
1129
+ executionProfile: "egress"
1130
+ },
1131
+ context
1132
+ );
1133
+ return {
1134
+ ...base,
1135
+ methods: {
1136
+ execute_method: {
1137
+ implementation_type: "script"
1138
+ }
1139
+ }
1140
+ };
1141
+ }
1142
+ };
1143
+ var extend_objects_custom_objects_default = {
1144
+ [EXTENSION_INTERFACE_ID2]: customObjectsTemplate
1145
+ };
1146
+
1147
+ // src/templates/extensions/extend.workflows.custom_action.ts
1148
+ var EXTENSION_INTERFACE_ID3 = "extend.workflows.custom_action";
1149
+ var extendCustomActionTemplate = {
1150
+ methods: {
1151
+ execute: { implementation_types: ["script", "remote-function"] },
1152
+ get_form_state: { implementation_types: ["script", "remote-function"] }
1153
+ },
1154
+ description: "Custom actions let your app define actions that users can add to their automated workflows. When a workflow triggers a custom action, Stripe calls your app to execute it.",
1155
+ generate: (params, context) => {
1156
+ const { id } = params;
1157
+ const { fs: fs2 } = context;
1158
+ const base = _createBaseOutput(
1159
+ {
1160
+ ...params,
1161
+ extensionInterfaceId: EXTENSION_INTERFACE_ID3,
1162
+ executionProfile: "egress"
1163
+ },
1164
+ context
1165
+ );
1166
+ return {
1167
+ ...base,
1168
+ files: [
1169
+ {
1170
+ path: `extensions/${id}/src/index.ts`,
1171
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "index.ts"),
1172
+ precious: true
1173
+ },
1174
+ {
1175
+ path: `extensions/${id}/src/custom_input.schema.json`,
1176
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "custom_input.schema.json"),
1177
+ precious: true
1178
+ },
1179
+ {
1180
+ path: `extensions/${id}/src/index.test.ts`,
1181
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "index.test.ts"),
1182
+ precious: true
1183
+ },
1184
+ ...base.files
1185
+ ],
1186
+ methods: {
1187
+ execute: {
1188
+ implementation_type: "script",
1189
+ custom_input: {
1190
+ input_schema: {
1191
+ type: "json_schema",
1192
+ content: `extensions/${id}/src/custom_input.schema.json`
1193
+ }
1194
+ }
1195
+ },
1196
+ get_form_state: {
1197
+ implementation_type: "script"
1198
+ }
1199
+ }
1200
+ };
1201
+ }
1202
+ };
1203
+ var extend_workflows_custom_action_default = {
1204
+ [EXTENSION_INTERFACE_ID3]: extendCustomActionTemplate
1205
+ };
1206
+
1207
+ // src/templates/extensions/billing.customer_balance_application.ts
1208
+ var EXTENSION_INTERFACE_ID4 = "billing.customer_balance_application";
1209
+ var customerBalanceApplicationTemplate = {
1210
+ methods: {
1211
+ compute_applied_customer_balance: { implementation_types: ["script"] }
1212
+ },
1213
+ description: "Implement custom logic to control when and how much customer balance is applied to subscription invoices using scripts.",
1214
+ generate: (params, context) => {
1215
+ const { id } = params;
1216
+ const { fs: fs2 } = context;
1217
+ const base = _createBaseOutput(
1218
+ {
1219
+ ...params,
1220
+ extensionInterfaceId: EXTENSION_INTERFACE_ID4,
1221
+ executionProfile: "restricted"
1222
+ },
1223
+ context
1224
+ );
1225
+ return {
1226
+ ...base,
1227
+ files: [
1228
+ {
1229
+ path: `extensions/${id}/src/index.ts`,
1230
+ content: fs2.textFile(EXTENSION_INTERFACE_ID4, "index.ts"),
1231
+ precious: true
1232
+ },
1233
+ {
1234
+ path: `extensions/${id}/src/index.test.ts`,
1235
+ content: fs2.textFile(EXTENSION_INTERFACE_ID4, "index.test.ts"),
1236
+ precious: true
1237
+ },
1238
+ ...base.files
1239
+ ],
1240
+ methods: {
1241
+ compute_applied_customer_balance: {
1242
+ implementation_type: "script"
1243
+ }
1244
+ }
1245
+ };
1246
+ }
1247
+ };
1248
+ var billing_customer_balance_application_default = {
1249
+ [EXTENSION_INTERFACE_ID4]: customerBalanceApplicationTemplate
1250
+ };
1251
+
1252
+ // src/templates/extensions/billing.bill.discount_calculation.ts
1253
+ var EXTENSION_INTERFACE_ID5 = "billing.bill.discount_calculation";
1254
+ var discountCalculationTemplate = {
1255
+ hidden: true,
1256
+ methods: {
1257
+ compute_discounts: { implementation_types: ["script"] }
1258
+ },
1259
+ description: "Create coupons with custom scripting logic for dynamic discounts based on subscription attributes, customer metadata, and complex business rules.",
1260
+ generate: (params, context) => {
1261
+ const { id } = params;
1262
+ const { fs: fs2 } = context;
1263
+ const base = _createBaseOutput(
1264
+ {
1265
+ ...params,
1266
+ extensionInterfaceId: EXTENSION_INTERFACE_ID5,
1267
+ executionProfile: "restricted"
1268
+ },
1269
+ context
1270
+ );
1271
+ return {
1272
+ ...base,
1273
+ files: [
1274
+ {
1275
+ path: `extensions/${id}/src/index.ts`,
1276
+ content: fs2.textFile(EXTENSION_INTERFACE_ID5, "index.ts"),
1277
+ precious: true
1278
+ },
1279
+ {
1280
+ path: `extensions/${id}/src/index.test.ts`,
1281
+ content: fs2.textFile(EXTENSION_INTERFACE_ID5, "index.test.ts"),
1282
+ precious: true
1283
+ },
1284
+ ...base.files
1285
+ ],
1286
+ methods: {
1287
+ compute_discounts: {
1288
+ implementation_type: "script"
1289
+ }
1290
+ }
1291
+ };
1292
+ }
1293
+ };
1294
+ var billing_bill_discount_calculation_default = {
1295
+ [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
1296
+ };
1297
+
1298
+ // src/templates/extensions/billing.invoice_collection_setting.ts
1299
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
1300
+ var invoiceCollectionSettingTemplate = {
1301
+ hidden: true,
1302
+ methods: {
1303
+ collection_override: { implementation_types: ["script"] }
1304
+ },
1305
+ description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
1306
+ generate: (params, context) => {
1307
+ const { id } = params;
1308
+ const { fs: fs2 } = context;
1309
+ const base = _createBaseOutput(
1310
+ {
1311
+ ...params,
1312
+ extensionInterfaceId: EXTENSION_INTERFACE_ID6,
1313
+ executionProfile: "restricted"
1314
+ },
1315
+ context
1316
+ );
1317
+ return {
1318
+ ...base,
1319
+ files: [
1320
+ {
1321
+ path: `extensions/${id}/src/index.ts`,
1322
+ content: fs2.textFile(EXTENSION_INTERFACE_ID6, "index.ts"),
1323
+ precious: true
1324
+ },
1325
+ {
1326
+ path: `extensions/${id}/src/index.test.ts`,
1327
+ content: fs2.textFile(EXTENSION_INTERFACE_ID6, "index.test.ts"),
1328
+ precious: true
1329
+ },
1330
+ ...base.files
1331
+ ],
1332
+ methods: {
1333
+ collection_override: {
1334
+ implementation_type: "script"
1335
+ }
1336
+ }
1337
+ };
1338
+ }
1339
+ };
1340
+ var billing_invoice_collection_setting_default = {
1341
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
1342
+ };
1343
+
1344
+ // src/templates/extensions/billing.prorations.ts
1345
+ var EXTENSION_INTERFACE_ID7 = "billing.prorations";
1346
+ var prorationsTemplate = {
1347
+ methods: {
1348
+ prorate_items: { implementation_types: ["script"] }
1349
+ },
1350
+ description: "Create custom proration logic for subscriptions using scripts to handle upgrades, downgrades, and mid-cycle changes.",
1351
+ generate: (params, context) => {
1352
+ const { id } = params;
1353
+ const { fs: fs2 } = context;
1354
+ const base = _createBaseOutput(
1355
+ {
1356
+ ...params,
1357
+ extensionInterfaceId: EXTENSION_INTERFACE_ID7,
1358
+ executionProfile: "restricted"
1359
+ },
1360
+ context
1361
+ );
1362
+ return {
1363
+ ...base,
1364
+ files: [
1365
+ {
1366
+ path: `extensions/${id}/src/index.ts`,
1367
+ content: fs2.textFile(EXTENSION_INTERFACE_ID7, "index.ts"),
1368
+ precious: true
1369
+ },
1370
+ {
1371
+ path: `extensions/${id}/src/index.test.ts`,
1372
+ content: fs2.textFile(EXTENSION_INTERFACE_ID7, "index.test.ts"),
1373
+ precious: true
1374
+ },
1375
+ ...base.files
1376
+ ],
1377
+ methods: {
1378
+ prorate_items: {
1379
+ implementation_type: "script"
1380
+ }
1381
+ }
1382
+ };
1383
+ }
1384
+ };
1385
+ var billing_prorations_default = {
1386
+ [EXTENSION_INTERFACE_ID7]: prorationsTemplate
1387
+ };
1388
+
1389
+ // src/templates/extensions/billing.recurring_billing_item_handling.ts
1390
+ var EXTENSION_INTERFACE_ID8 = "billing.recurring_billing_item_handling";
1391
+ var template = {
1392
+ methods: {
1393
+ before_item_creation: { implementation_types: ["script"] },
1394
+ filter_items: { implementation_types: ["script"] },
1395
+ group_items: { implementation_types: ["script"] }
1396
+ },
1397
+ description: "Customize how recurring billing items are filtered, grouped, and created during subscription billing runs.",
1398
+ generate: (params, context) => {
1399
+ const { id } = params;
1400
+ const { fs: fs2 } = context;
1401
+ const base = _createBaseOutput(
1402
+ {
1403
+ ...params,
1404
+ extensionInterfaceId: EXTENSION_INTERFACE_ID8,
1405
+ executionProfile: "restricted"
1406
+ },
1407
+ context
1408
+ );
1409
+ return {
1410
+ ...base,
1411
+ files: [
1412
+ {
1413
+ path: `extensions/${id}/src/index.ts`,
1414
+ content: fs2.textFile(EXTENSION_INTERFACE_ID8, "index.ts"),
1415
+ precious: true
1416
+ },
1417
+ {
1418
+ path: `extensions/${id}/src/index.test.ts`,
1419
+ content: fs2.textFile(EXTENSION_INTERFACE_ID8, "index.test.ts"),
1420
+ precious: true
1421
+ },
1422
+ ...base.files
1423
+ ],
1424
+ methods: {
1425
+ before_item_creation: {
1426
+ implementation_type: "script"
1427
+ },
1428
+ filter_items: {
1429
+ implementation_type: "script"
1430
+ },
1431
+ group_items: {
1432
+ implementation_type: "script"
1433
+ }
1434
+ }
1435
+ };
1436
+ }
1437
+ };
1438
+ var billing_recurring_billing_item_handling_default = {
1439
+ [EXTENSION_INTERFACE_ID8]: template
1440
+ };
1441
+
1442
+ // src/templates/extensions/registry.ts
1443
+ var DEFAULT_TEMPLATES = {
1444
+ ...core_workflows_custom_action_default,
1445
+ ...extend_objects_custom_objects_default,
1446
+ ...extend_workflows_custom_action_default,
1447
+ ...billing_customer_balance_application_default,
1448
+ ...billing_bill_discount_calculation_default,
1449
+ ...billing_invoice_collection_setting_default,
1450
+ ...billing_prorations_default,
1451
+ ...billing_recurring_billing_item_handling_default
1452
+ };
1453
+ var registry_default = DEFAULT_TEMPLATES;
1454
+
1455
+ // src/templates/extensions/index.ts
1456
+ var _templateManager = new _ExtensionTemplateManager(
1457
+ registry_default,
1458
+ _fs.scope("extensions")
1459
+ );
1460
+
1461
+ // src/bin/template-info.ts
1462
+ var logger = _createLogger({ name: "template-info" });
1463
+ async function main() {
1464
+ await yargs(hideBin(process.argv)).usage("Show available extension templates").help().version(false).command(
1465
+ "$0",
1466
+ "List available extension templates",
1467
+ (y) => y.option("output-path", {
1468
+ type: "string",
1469
+ description: "Write JSON result to this file instead of stdout"
1470
+ }),
1471
+ (args) => {
1472
+ const templates = _templateManager.getTemplateInfo().filter((t) => !t.hidden);
1473
+ if (args.outputPath) {
1474
+ _writeJsonOutput(args.outputPath, templates);
1475
+ } else {
1476
+ for (const t of templates) {
1477
+ const suffix = t.deprecated ? " (deprecated)" : "";
1478
+ process.stdout.write(` ${t.key} \u2014 ${t.description}${suffix}
1479
+ `);
1480
+ }
1481
+ }
1482
+ }
1483
+ ).parse();
1484
+ }
1485
+ main().catch((err) => {
1486
+ logger.error({ err }, "Unexpected error");
1487
+ process.exit(1);
1488
+ });