@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,2248 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/templates/index.ts
31
+ var templates_exports = {};
32
+ __export(templates_exports, {
33
+ _ExtensionTemplateManager: () => _ExtensionTemplateManager,
34
+ _SingleTemplateManager: () => import_extensibility_tool_utils3._SingleTemplateManager,
35
+ _TemplateManager: () => import_extensibility_tool_utils._TemplateManager,
36
+ _advancedDiffPrompt: () => _advancedDiffPrompt,
37
+ _createExtensionEslintConfigFile: () => _createExtensionEslintConfigFile,
38
+ _createSimpleSingleFileTemplate: () => import_extensibility_tool_utils3._createSimpleSingleFileTemplate,
39
+ _createSimpleTemplate: () => import_extensibility_tool_utils3._createSimpleTemplate,
40
+ _fs: () => _fs,
41
+ _promptOverwrite: () => _promptOverwrite,
42
+ _rootTemplateManager: () => _rootTemplateManager,
43
+ _rootWorkspaceTemplate: () => _rootWorkspaceTemplate,
44
+ _templateManager: () => _templateManager,
45
+ _writeGeneratedFiles: () => _writeGeneratedFiles
46
+ });
47
+ module.exports = __toCommonJS(templates_exports);
48
+
49
+ // src/templates/template-manager.ts
50
+ var import_extensibility_tool_utils = require("@stripe/extensibility-tool-utils");
51
+
52
+ // src/templates/fs/in-memory.ts
53
+ var import_extensibility_tool_utils2 = require("@stripe/extensibility-tool-utils");
54
+
55
+ // templates-virtual:./_impl.js
56
+ var TEMPLATE_FS_IMAGE = [
57
+ {
58
+ path: "extensions/billing.bill.discount_calculation/index.test.ts",
59
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
60
+
61
+ import MyDiscountCalculation from './index.js';
62
+
63
+ describe('MyDiscountCalculation', () => {
64
+ let instance: MyDiscountCalculation;
65
+
66
+ beforeEach(() => {
67
+ instance = new MyDiscountCalculation();
68
+ });
69
+
70
+ it('should be constructable', () => {
71
+ expect(instance).toBeInstanceOf(MyDiscountCalculation);
72
+ });
73
+ });
74
+ `
75
+ },
76
+ {
77
+ path: "extensions/billing.bill.discount_calculation/index.ts",
78
+ content: `import type { Billing } from '@stripe/extensibility-sdk/extensions';
79
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
80
+
81
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
82
+ interface MyDiscountCalculationConfig extends Record<string, unknown> {}
83
+
84
+ export default class MyDiscountCalculation implements Billing.Bill
85
+ .DiscountCalculation<MyDiscountCalculationConfig> {
86
+ computeDiscounts(
87
+ request: Billing.Bill.DiscountCalculation.DiscountableItem,
88
+ _config: MyDiscountCalculationConfig,
89
+ _context: Context
90
+ ) {
91
+ // TODO: implement your discount logic here
92
+
93
+ return {
94
+ discount: { amount: request.grossAmount },
95
+ };
96
+ }
97
+ }
98
+ `
99
+ },
100
+ {
101
+ path: "extensions/billing.customer_balance_application/index.test.ts",
102
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
103
+
104
+ import MyCustomerBalanceApplication from './index.js';
105
+
106
+ describe('MyCustomerBalanceApplication', () => {
107
+ let instance: MyCustomerBalanceApplication;
108
+
109
+ beforeEach(() => {
110
+ instance = new MyCustomerBalanceApplication();
111
+ });
112
+
113
+ it('should be constructable', () => {
114
+ expect(instance).toBeInstanceOf(MyCustomerBalanceApplication);
115
+ });
116
+ });
117
+ `
118
+ },
119
+ {
120
+ path: "extensions/billing.customer_balance_application/index.ts",
121
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
122
+
123
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
124
+ interface MyCustomerBalanceApplicationConfig extends Record<string, unknown> {}
125
+
126
+ export default class MyCustomerBalanceApplication implements Billing.CustomerBalanceApplication<MyCustomerBalanceApplicationConfig> {
127
+ computeAppliedCustomerBalance(
128
+ request: Billing.CustomerBalanceApplication.CustomerBalanceApplicationInput,
129
+ _config: MyCustomerBalanceApplicationConfig,
130
+ _context: Context
131
+ ) {
132
+ // TODO: implement your customer balance logic here
133
+
134
+ return {
135
+ appliedCustomerBalance: request.customerBalance,
136
+ };
137
+ }
138
+ }
139
+ `
140
+ },
141
+ {
142
+ path: "extensions/billing.invoice_collection_setting/index.test.ts",
143
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
144
+
145
+ import MyInvoiceCollectionSetting from './index.js';
146
+
147
+ describe('MyInvoiceCollectionSetting', () => {
148
+ let instance: MyInvoiceCollectionSetting;
149
+
150
+ beforeEach(() => {
151
+ instance = new MyInvoiceCollectionSetting();
152
+ });
153
+
154
+ it('should be constructable', () => {
155
+ expect(instance).toBeInstanceOf(MyInvoiceCollectionSetting);
156
+ });
157
+ });
158
+ `
159
+ },
160
+ {
161
+ path: "extensions/billing.invoice_collection_setting/index.ts",
162
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
163
+
164
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
165
+ interface MyInvoiceCollectionSettingConfig extends Record<string, unknown> {}
166
+
167
+ export default class MyInvoiceCollectionSetting implements Billing.InvoiceCollectionSetting<MyInvoiceCollectionSettingConfig> {
168
+ collectionOverride(
169
+ _request: Billing.InvoiceCollectionSetting.InvoiceCollectionRequest,
170
+ _config: MyInvoiceCollectionSettingConfig,
171
+ _context: Context
172
+ ) {
173
+ // TODO: implement your collection setting logic here
174
+
175
+ return {};
176
+ }
177
+ }
178
+ `
179
+ },
180
+ {
181
+ path: "extensions/billing.prorations/index.test.ts",
182
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
183
+
184
+ import MyProrations from './index.js';
185
+
186
+ describe('MyProrations', () => {
187
+ let instance: MyProrations;
188
+
189
+ beforeEach(() => {
190
+ instance = new MyProrations();
191
+ });
192
+
193
+ it('should be constructable', () => {
194
+ expect(instance).toBeInstanceOf(MyProrations);
195
+ });
196
+ });
197
+ `
198
+ },
199
+ {
200
+ path: "extensions/billing.prorations/index.ts",
201
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
202
+
203
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
204
+ interface MyProrationsConfig extends Record<string, unknown> {}
205
+
206
+ export default class MyProrations implements Billing.Prorations<MyProrationsConfig> {
207
+ prorateItems(
208
+ _request: Billing.Prorations.ProrateItemsInput,
209
+ _config: MyProrationsConfig,
210
+ _context: Context
211
+ ) {
212
+ // TODO: implement your proration logic here
213
+
214
+ return {
215
+ items: [],
216
+ };
217
+ }
218
+ }
219
+ `
220
+ },
221
+ {
222
+ path: "extensions/billing.recurring_billing_item_handling/index.test.ts",
223
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
224
+
225
+ import MyRecurringBillingItemHandling from './index.js';
226
+
227
+ describe('MyRecurringBillingItemHandling', () => {
228
+ let instance: MyRecurringBillingItemHandling;
229
+
230
+ beforeEach(() => {
231
+ instance = new MyRecurringBillingItemHandling();
232
+ });
233
+
234
+ it('should be constructable', () => {
235
+ expect(instance).toBeInstanceOf(MyRecurringBillingItemHandling);
236
+ });
237
+ });
238
+ `
239
+ },
240
+ {
241
+ path: "extensions/billing.recurring_billing_item_handling/index.ts",
242
+ content: `import type { Billing, Context } from '@stripe/extensibility-sdk/extensions';
243
+
244
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
245
+ interface MyRecurringBillingItemHandlingConfig extends Record<string, unknown> {}
246
+
247
+ export default class MyRecurringBillingItemHandling implements Billing.RecurringBillingItemHandling<MyRecurringBillingItemHandlingConfig> {
248
+ beforeItemCreation(
249
+ _request: Billing.RecurringBillingItemHandling.BeforeItemCreationInput,
250
+ _config: MyRecurringBillingItemHandlingConfig,
251
+ _context: Context
252
+ ) {
253
+ // TODO: implement your before-item-creation logic here
254
+
255
+ return {
256
+ items: [],
257
+ };
258
+ }
259
+
260
+ filterItems(
261
+ _request: Billing.RecurringBillingItemHandling.FilterItemsInput,
262
+ _config: MyRecurringBillingItemHandlingConfig,
263
+ _context: Context
264
+ ) {
265
+ // TODO: implement your filter-items logic here
266
+
267
+ return {
268
+ items: [],
269
+ };
270
+ }
271
+
272
+ groupItems(
273
+ _request: Billing.RecurringBillingItemHandling.GroupItemsInput,
274
+ _config: MyRecurringBillingItemHandlingConfig,
275
+ _context: Context
276
+ ) {
277
+ // TODO: implement your group-items logic here
278
+
279
+ return {
280
+ groups: [],
281
+ };
282
+ }
283
+ }
284
+ `
285
+ },
286
+ {
287
+ path: "extensions/common/.prettierignore",
288
+ content: `dist
289
+ generated
290
+ node_modules
291
+ `
292
+ },
293
+ {
294
+ path: "extensions/common/eslint.config.mts.mustache",
295
+ content: `import eslint from '@eslint/js';
296
+ import { defineConfig } from 'eslint/config';
297
+ import tseslint from 'typescript-eslint';
298
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
299
+
300
+ import globals from 'globals';
301
+
302
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
303
+ import extensionTypeConfig from '@stripe/extensibility-eslint-plugin/{{extensionInterfaceId}}';
304
+
305
+ export default defineConfig([
306
+ eslint.configs.recommended,
307
+ ...tseslint.configs.recommended,
308
+ ...stripeAppsConfig,
309
+ ...extensionTypeConfig,
310
+
311
+ // Global ignores
312
+ {
313
+ ignores: ['dist', 'generated', 'node_modules'],
314
+ },
315
+
316
+ // TypeScript source files (with type-checking)
317
+ {
318
+ name: 'sources',
319
+ files: ['src/**/*.ts'],
320
+ ignores: ['**/*.test.ts', '**/__tests__/**'],
321
+ languageOptions: {
322
+ globals: {
323
+ ...globals.node,
324
+ },
325
+ parserOptions: {
326
+ projectService: true,
327
+ tsconfigRootDir: import.meta.dirname,
328
+ },
329
+ },
330
+ },
331
+
332
+ // Test files (type-checking, relaxed rules)
333
+ {
334
+ name: 'tests',
335
+ files: ['src/**/*.test.ts', 'src/**/__tests__/**/*.ts'],
336
+ languageOptions: {
337
+ globals: {
338
+ ...globals.node,
339
+ },
340
+ parserOptions: {
341
+ projectService: true,
342
+ tsconfigRootDir: import.meta.dirname,
343
+ },
344
+ },
345
+ rules: {
346
+ '@typescript-eslint/no-explicit-any': 'off',
347
+ '@typescript-eslint/no-unused-vars': 'off',
348
+ 'no-console': 'off',
349
+ },
350
+ },
351
+
352
+ // Config files
353
+ {
354
+ name: 'ts-configs',
355
+ files: ['*.config.m?ts', 'eslint.config.mts'],
356
+ languageOptions: {
357
+ globals: {
358
+ ...globals.node,
359
+ },
360
+ parserOptions: {
361
+ projectService: false,
362
+ },
363
+ },
364
+ rules: {
365
+ '@typescript-eslint/no-unused-vars': 'off',
366
+ },
367
+ },
368
+
369
+ // JavaScript/MJS files (scripts, configs)
370
+ {
371
+ name: 'js-configs',
372
+ files: ['**/*.js', '**/*.mjs'],
373
+ languageOptions: {
374
+ globals: {
375
+ ...globals.node,
376
+ },
377
+ parserOptions: {
378
+ projectService: false,
379
+ },
380
+ },
381
+ rules: {
382
+ '@typescript-eslint/no-require-imports': 'off',
383
+ '@typescript-eslint/no-unused-vars': 'off',
384
+ 'no-unused-vars': 'off',
385
+ },
386
+ },
387
+
388
+ eslintConfigPrettier,
389
+ ]);
390
+ `
391
+ },
392
+ {
393
+ path: "extensions/common/package.json.mustache",
394
+ content: `{
395
+ "name": "{{id}}",
396
+ "version": "{{version}}",
397
+ "description": "{{name}}",
398
+ "private": true,
399
+ "license": "~~proprietary~~",
400
+ "type": "module",
401
+ "scripts": {
402
+ "build": "tsc -p tsconfig.build.json && pnpm build:schemas",
403
+ "build:schemas": "gen-schemas --root ../.. --extension-id \\"$npm_package_name\\" --out-dir generated --schema-name config",
404
+ "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
405
+ "lint:types": "tsc -p tsconfig.build.json --noEmit && tsc -p tsconfig.json --noEmit",
406
+ "lint:eslint": "eslint .",
407
+ "lint:format": "prettier --check .",
408
+ "fix:lint": "eslint --fix .",
409
+ "fix:format": "prettier --write .",
410
+ "test": "vitest --root ../.. run --project \\"$npm_package_name\\"",
411
+ "test:watch": "pnpm test --watch",
412
+ "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'",
413
+ "stripe:regen": "gen-workspace --root ../.. --package-dir . --template-id {{extensionInterfaceId}}"
414
+ },
415
+ "lint-staged": {
416
+ "*.{ts,mts,mjs,js}": ["eslint --fix", "prettier --write"],
417
+ "*.{json,md,yaml}": "prettier --write"
418
+ }
419
+ }
420
+ `
421
+ },
422
+ {
423
+ path: "extensions/common/tsconfig.build.json.mustache",
424
+ content: `{
425
+ "extends": "../../tsconfig.base.json",
426
+ "compilerOptions": {
427
+ "lib": null,
428
+ "noLib": true,
429
+ "outDir": "./dist",
430
+ "rootDir": "./src"
431
+ },
432
+ "include": [
433
+ "src/**/*.ts",
434
+ "node_modules/@stripe/extensibility-sdk/tslibs/5.9.3/lib.es2022.{{executionProfile}}.d.ts",
435
+ "node_modules/@stripe/extensibility-sdk/tslibs/lib.{{executionProfile}}.globals.d.ts"
436
+ ],
437
+ "exclude": ["src/**/*.test.ts", "src/**/__tests__"]
438
+ }
439
+ `
440
+ },
441
+ {
442
+ path: "extensions/common/tsconfig.json.mustache",
443
+ content: `{
444
+ "extends": "../../tsconfig.json",
445
+ "compilerOptions": {
446
+ "rootDir": ".",
447
+ "plugins": [
448
+ {
449
+ "name": "@stripe/extensibility-language-server/plugin"
450
+ }
451
+ ]
452
+ },
453
+ "include": [
454
+ "src/**/*.ts",
455
+ "node_modules/@stripe/extensibility-sdk/tslibs/lib.{{executionProfile}}.globals.d.ts"
456
+ ],
457
+ "exclude": ["dist"]
458
+ }
459
+ `
460
+ },
461
+ {
462
+ path: "extensions/core.workflows.custom_action/custom_input.schema.json",
463
+ content: `{
464
+ "$schema": "http://json-schema.org/draft-07/schema#",
465
+ "type": "object",
466
+ "properties": {},
467
+ "additionalProperties": false
468
+ }
469
+ `
470
+ },
471
+ {
472
+ path: "extensions/core.workflows.custom_action/index.test.ts",
473
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
474
+
475
+ import MyCustomAction from './index.js';
476
+
477
+ describe('MyCustomAction', () => {
478
+ let instance: MyCustomAction;
479
+
480
+ beforeEach(() => {
481
+ instance = new MyCustomAction();
482
+ });
483
+
484
+ it('should be constructable', () => {
485
+ expect(instance).toBeInstanceOf(MyCustomAction);
486
+ });
487
+ });
488
+ `
489
+ },
490
+ {
491
+ path: "extensions/core.workflows.custom_action/index.ts",
492
+ content: `import type { Core } from '@stripe/extensibility-sdk/extensions';
493
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
494
+
495
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
496
+ interface MyCustomActionConfig extends Record<string, unknown> {}
497
+
498
+ export default class MyCustomAction implements Core.Workflows
499
+ .CustomAction<MyCustomActionConfig> {
500
+ execute(
501
+ _request: Core.Workflows.CustomAction.ExecuteCustomActionRequest,
502
+ _config: MyCustomActionConfig,
503
+ _context: Context
504
+ ) {
505
+ // TODO: implement your action logic here
506
+
507
+ return {};
508
+ }
509
+
510
+ getFormState(
511
+ _request: Core.Workflows.CustomAction.GetFormStateRequest,
512
+ _config: MyCustomActionConfig,
513
+ _context: Context
514
+ ) {
515
+ // TODO: implement your logic here
516
+
517
+ return {
518
+ values: {},
519
+ config: {},
520
+ };
521
+ }
522
+ }
523
+ `
524
+ },
525
+ {
526
+ path: "extensions/extend.workflows.custom_action/custom_input.schema.json",
527
+ content: `{
528
+ "$schema": "http://json-schema.org/draft-07/schema#",
529
+ "type": "object",
530
+ "properties": {},
531
+ "additionalProperties": false
532
+ }
533
+ `
534
+ },
535
+ {
536
+ path: "extensions/extend.workflows.custom_action/index.test.ts",
537
+ content: `import { beforeEach, describe, it, expect } from 'vitest';
538
+
539
+ import MyCustomAction from './index.js';
540
+
541
+ describe('MyCustomAction', () => {
542
+ let instance: MyCustomAction;
543
+
544
+ beforeEach(() => {
545
+ instance = new MyCustomAction();
546
+ });
547
+
548
+ it('should be constructable', () => {
549
+ expect(instance).toBeInstanceOf(MyCustomAction);
550
+ });
551
+ });
552
+ `
553
+ },
554
+ {
555
+ path: "extensions/extend.workflows.custom_action/index.ts",
556
+ content: `import type { Extend } from '@stripe/extensibility-sdk/extensions';
557
+ import type { Context } from '@stripe/extensibility-sdk/extensions';
558
+
559
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
560
+ interface MyCustomActionConfig extends Record<string, unknown> {}
561
+
562
+ export default class MyCustomAction implements Extend.Workflows
563
+ .CustomAction<MyCustomActionConfig> {
564
+ execute(
565
+ _request: Extend.Workflows.CustomAction.ExecuteCustomActionRequest,
566
+ _config: MyCustomActionConfig,
567
+ _context: Context
568
+ ) {
569
+ // TODO: implement your action logic here
570
+
571
+ return {};
572
+ }
573
+
574
+ getFormState(
575
+ _request: Extend.Workflows.CustomAction.GetFormStateRequest,
576
+ _config: MyCustomActionConfig,
577
+ _context: Context
578
+ ) {
579
+ // TODO: implement your logic here
580
+
581
+ return {
582
+ values: {},
583
+ config: {},
584
+ };
585
+ }
586
+ }
587
+ `
588
+ },
589
+ {
590
+ path: "root/.husky/pre-commit",
591
+ content: `pnpm lint-staged
592
+ `
593
+ },
594
+ {
595
+ path: "root/.prettierignore",
596
+ content: `dist
597
+ generated
598
+ node_modules
599
+ pnpm-lock.yaml
600
+ .build
601
+ `
602
+ },
603
+ {
604
+ path: "root/.prettierrc",
605
+ content: `{
606
+ "semi": true,
607
+ "singleQuote": true,
608
+ "tabWidth": 2,
609
+ "trailingComma": "es5",
610
+ "printWidth": 90
611
+ }
612
+ `
613
+ },
614
+ {
615
+ path: "root/_gitignore",
616
+ content: `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
617
+
618
+ *~
619
+
620
+ # dependencies
621
+ node_modules
622
+ dist
623
+
624
+ # testing
625
+ /coverage
626
+
627
+ # production
628
+ /.build
629
+
630
+ # misc
631
+ .DS_Store
632
+ .env.local
633
+ .env.development.local
634
+ .env.test.local
635
+ .env.production.local
636
+
637
+ npm-debug.log*
638
+ yarn-debug.log*
639
+ yarn-error.log*
640
+ install-deps.log
641
+
642
+ # generated schemas
643
+ generated
644
+ `
645
+ },
646
+ {
647
+ path: "root/custom-objects/package.json",
648
+ content: `{
649
+ "name": "custom-objects",
650
+ "type": "module",
651
+ "version": "0.0.1",
652
+ "license": "UNLICENSED",
653
+ "private": true,
654
+ "scripts": {
655
+ "build": "test -d src && custom-objects-build --input src --output dist || true",
656
+ "lint:types": "test ! -d src || tsc --noEmit",
657
+ "test": "vitest run"
658
+ },
659
+ "dependencies": {
660
+ "@stripe/extensibility-custom-objects": "0.7.4",
661
+ "@stripe/extensibility-sdk": "0.22.4"
662
+ },
663
+ "devDependencies": {
664
+ "@stripe/extensibility-custom-objects-tools": "0.40.0",
665
+ "@stripe/extensibility-test-helpers": "0.2.7"
666
+ }
667
+ }
668
+ `
669
+ },
670
+ {
671
+ path: "root/custom-objects/tsconfig.json",
672
+ content: `{
673
+ "extends": "../tsconfig.base.json",
674
+ "compilerOptions": {
675
+ "module": "ESNext",
676
+ "moduleResolution": "bundler",
677
+ "types": ["vitest/globals"]
678
+ },
679
+ "exclude": ["dist"]
680
+ }
681
+ `
682
+ },
683
+ {
684
+ path: "root/eslint.config.mts",
685
+ content: `import { readFileSync } from 'node:fs';
686
+ import { dirname, resolve } from 'node:path';
687
+ import { fileURLToPath } from 'node:url';
688
+ import eslint from '@eslint/js';
689
+ import { defineConfig } from 'eslint/config';
690
+ import tseslint from 'typescript-eslint';
691
+ import workspaces from 'eslint-plugin-workspaces';
692
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
693
+
694
+ import globals from 'globals';
695
+
696
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
697
+
698
+ // Read additional ignore globs from package.json (written by the generate plugin
699
+ // to exclude generated SDK directories from linting).
700
+ let stripeGlobsToIgnore: string[] = [];
701
+ try {
702
+ const configDir = dirname(fileURLToPath(import.meta.url));
703
+ const packageJsonPath = resolve(configDir, './package.json');
704
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
705
+ const globs = pkg?.stripe?.eslintIgnoreGlobs;
706
+ if (Array.isArray(globs)) {
707
+ stripeGlobsToIgnore = globs.filter(
708
+ (g: unknown): g is string => typeof g === 'string'
709
+ );
710
+ }
711
+ } catch {
712
+ // package.json not found or unparseable \u2014 ignore
713
+ }
714
+
715
+ export default defineConfig([
716
+ eslint.configs.recommended,
717
+ ...tseslint.configs.recommended,
718
+ ...stripeAppsConfig,
719
+
720
+ // Global ignores
721
+ {
722
+ ignores: [
723
+ '.build',
724
+ '**/dist',
725
+ '**/generated',
726
+ '**/node_modules',
727
+ 'extensions/**',
728
+ 'custom-objects',
729
+ 'ui',
730
+ ...stripeGlobsToIgnore,
731
+ ],
732
+ },
733
+
734
+ // Common rules for all files
735
+ {
736
+ plugins: { workspaces },
737
+ rules: {
738
+ ...workspaces.configs.recommended.rules,
739
+ },
740
+ },
741
+
742
+ // Config files (vitest.config.ts, eslint.config.ts, etc.)
743
+ {
744
+ name: 'ts-configs',
745
+ files: ['extensions/*/*.config.m?ts', '*.config.m?ts', 'eslint.config.mts'],
746
+ languageOptions: {
747
+ globals: {
748
+ ...globals.node,
749
+ },
750
+ parserOptions: {
751
+ projectService: false,
752
+ },
753
+ },
754
+ rules: {
755
+ '@typescript-eslint/no-unused-vars': 'off',
756
+ },
757
+ },
758
+
759
+ // JavaScript/MJS files (scripts, configs)
760
+ {
761
+ name: 'js-configs',
762
+ files: ['**/*.js', '**/*.mjs'],
763
+ languageOptions: {
764
+ globals: {
765
+ ...globals.node,
766
+ },
767
+ parserOptions: {
768
+ projectService: false,
769
+ },
770
+ },
771
+ rules: {
772
+ '@typescript-eslint/no-require-imports': 'off',
773
+ '@typescript-eslint/no-unused-vars': 'off',
774
+ 'no-unused-vars': 'off',
775
+ },
776
+ },
777
+
778
+ eslintConfigPrettier,
779
+ ]);
780
+ `
781
+ },
782
+ {
783
+ path: "root/package.json.mustache",
784
+ content: `{
785
+ "name": "{{ appId }}",
786
+ "version": "{{ version }}",
787
+ "description": "{{ appName }}",
788
+ "private": true,
789
+ "license": "~~proprietary~~",
790
+ "engines": {
791
+ "node": ">=20.0.0"
792
+ },
793
+ "packageManager": "pnpm@10.30.3",
794
+ "scripts": {
795
+ "build": "pnpm -r --if-present build",
796
+ "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
797
+ "lint:types": "pnpm -r --if-present lint:types",
798
+ "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint",
799
+ "lint:format": "prettier --check .",
800
+ "fix:lint": "eslint --fix . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present fix:lint",
801
+ "fix:format": "prettier --write .",
802
+ "test": "tsx tools/test.mts",
803
+ "test:watch": "vitest watch",
804
+ "check": "pnpm build && pnpm lint && pnpm test",
805
+ "prepare": "husky",
806
+ "preimage": "pnpm install --lockfile-only && pnpm build && pnpm lint:types && pnpm lint:eslint && pnpm test",
807
+ "image": "rm -rf .build && create-upload-image .build",
808
+ "postimage": "cp pnpm-lock.yaml .build/",
809
+ "stripe:regen": "gen-workspace --package-dir ."
810
+ },
811
+ "lint-staged": {
812
+ "*.{ts,mts,mjs,js}": ["eslint --fix", "prettier --write"],
813
+ "*.{json,md,yaml}": "prettier --write"
814
+ }
815
+ }
816
+ `
817
+ },
818
+ {
819
+ path: "root/pnpm-workspace.yaml",
820
+ content: `packages:
821
+ - extensions/*
822
+ - custom-objects
823
+ - ui
824
+
825
+ overrides:
826
+ vite: ^6.0.0
827
+ `
828
+ },
829
+ {
830
+ path: "root/stripe-app.yaml.mustache",
831
+ content: `$schema: https://stripe.com/stripe-app/v2.0.0/schema
832
+ id: '{{ appId }}'
833
+ name: '{{ appName }}'
834
+ version: 0.0.1
835
+ declarations:
836
+ distribution_type: private
837
+ `
838
+ },
839
+ {
840
+ path: "root/tools/test.mts",
841
+ content: `#!/usr/bin/env tsx
842
+ /**
843
+ * Runs tests across the workspace:
844
+ * - vitest for script extensions and custom objects (extensions/*)
845
+ * - jest for UI extensions (ui/)
846
+ */
847
+ import { existsSync, readdirSync } from 'node:fs';
848
+ import { execSync } from 'node:child_process';
849
+
850
+ const hasExtensions =
851
+ existsSync('extensions') &&
852
+ readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
853
+
854
+ const hasUI = existsSync('ui/package.json');
855
+
856
+ let exitCode = 0;
857
+
858
+ function run(cmd: string): void {
859
+ try {
860
+ execSync(cmd, { stdio: 'inherit' });
861
+ } catch (e: unknown) {
862
+ exitCode = (e as NodeJS.ErrnoException & { status?: number }).status ?? 1;
863
+ }
864
+ }
865
+
866
+ if (hasExtensions) {
867
+ run('vitest run');
868
+ }
869
+
870
+ if (hasUI) {
871
+ try {
872
+ execSync('pnpm --filter "./ui" test', { stdio: 'inherit' });
873
+ } catch {
874
+ // UI test failures are non-fatal
875
+ }
876
+ }
877
+
878
+ process.exit(exitCode);
879
+ `
880
+ },
881
+ {
882
+ path: "root/tsconfig.base.json",
883
+ content: `{
884
+ "compilerOptions": {
885
+ "target": "ES2022",
886
+ "module": "NodeNext",
887
+ "moduleResolution": "NodeNext",
888
+ "lib": ["ES2022"],
889
+ "declaration": true,
890
+ "declarationMap": true,
891
+ "esModuleInterop": true,
892
+ "exactOptionalPropertyTypes": false,
893
+ "forceConsistentCasingInFileNames": true,
894
+ "isolatedModules": true,
895
+ "noFallthroughCasesInSwitch": true,
896
+ "noImplicitReturns": true,
897
+ "removeComments": false,
898
+ "resolveJsonModule": true,
899
+ "skipLibCheck": true,
900
+ "sourceMap": true,
901
+ "strict": true,
902
+ "types": [],
903
+ "verbatimModuleSyntax": true
904
+ }
905
+ }
906
+ `
907
+ },
908
+ {
909
+ path: "root/tsconfig.json",
910
+ content: `{
911
+ "extends": "./tsconfig.base.json",
912
+ "compilerOptions": {
913
+ "noEmit": true,
914
+ "plugins": [
915
+ {
916
+ "name": "@stripe/extensibility-language-server/plugin"
917
+ }
918
+ ],
919
+ "preserveWatchOutput": true,
920
+ "types": ["vitest/globals", "node"]
921
+ },
922
+ "include": ["**/*.ts"],
923
+ "exclude": ["**/node_modules", "**/dist"]
924
+ }
925
+ `
926
+ },
927
+ {
928
+ path: "root/ui/package.json",
929
+ content: `{
930
+ "name": "ui",
931
+ "version": "0.0.1",
932
+ "license": "UNLICENSED",
933
+ "private": true,
934
+ "scripts": {
935
+ "test": "jest --passWithNoTests"
936
+ },
937
+ "dependencies": {
938
+ "@stripe/ui-extension-sdk": "^9.1.0"
939
+ },
940
+ "devDependencies": {
941
+ "@stripe/ui-extension-tools": "^0.0.1",
942
+ "@types/jest": "^27.5.2",
943
+ "@types/react": "^17.0.2"
944
+ }
945
+ }
946
+ `
947
+ },
948
+ {
949
+ path: "root/vitest.config.mts",
950
+ content: `import { defineConfig } from 'vitest/config';
951
+ import { existsSync, readdirSync } from 'fs';
952
+ import { dirname, resolve } from 'path';
953
+ import { fileURLToPath } from 'url';
954
+
955
+ const rootDir = dirname(fileURLToPath(import.meta.url));
956
+ const extensionsDir = resolve(rootDir, 'extensions');
957
+
958
+ const extensionProjects = existsSync(extensionsDir)
959
+ ? readdirSync(extensionsDir)
960
+ .filter((name) => existsSync(resolve(extensionsDir, name, 'package.json')))
961
+ .map((name) => resolve(extensionsDir, name))
962
+ : [];
963
+
964
+ const coProjects = existsSync(resolve(rootDir, 'custom-objects/package.json'))
965
+ ? [resolve(rootDir, 'custom-objects')]
966
+ : [];
967
+
968
+ const projects = [...extensionProjects, ...coProjects];
969
+
970
+ if (projects.length === 0) {
971
+ console.debug(\`No vitest projects detected. This means either:
972
+ - You have no extension projects defined, in which case this warning is expected.
973
+ - There is an internal error detecting vitest projects relative to the project root
974
+ \${rootDir}.
975
+ \`);
976
+ }
977
+
978
+ export default projects.length > 0
979
+ ? defineConfig({
980
+ test: {
981
+ projects,
982
+ passWithNoTests: true,
983
+
984
+ // Only run tests from src, not compiled dist
985
+ exclude: ['**/node_modules', '**/dist'],
986
+ // Place snapshots alongside test files instead of in __snapshots__
987
+ snapshotFormat: {
988
+ escapeString: false,
989
+ printBasicPrototype: false,
990
+ },
991
+ resolveSnapshotPath: (testPath, snapExtension) => {
992
+ return testPath.replace(/\\.test\\.ts$/, \`.test\${snapExtension}\`);
993
+ },
994
+ },
995
+ })
996
+ : defineConfig({ test: { passWithNoTests: true, include: [] } });
997
+ `
998
+ }
999
+ ];
1000
+ var _fs = (0, import_extensibility_tool_utils2._createInMemoryTemplateFS)(TEMPLATE_FS_IMAGE);
1001
+
1002
+ // src/templates/simple-templates.ts
1003
+ var import_extensibility_tool_utils3 = require("@stripe/extensibility-tool-utils");
1004
+
1005
+ // src/templates/file-writer.ts
1006
+ var import_path = __toESM(require("path"), 1);
1007
+ var import_promises2 = require("fs/promises");
1008
+ var import_node_readline = require("readline");
1009
+ var import_extensibility_tool_utils4 = require("@stripe/extensibility-tool-utils");
1010
+
1011
+ // src/templates/fs-utils.ts
1012
+ var import_promises = require("fs/promises");
1013
+ async function pathExists(filePath, predicate) {
1014
+ try {
1015
+ const stats = await (0, import_promises.stat)(filePath);
1016
+ return predicate(stats);
1017
+ } catch (error) {
1018
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
1019
+ return false;
1020
+ }
1021
+ throw error;
1022
+ }
1023
+ }
1024
+ async function fileExists(filePath) {
1025
+ return pathExists(filePath, (stats) => stats.isFile());
1026
+ }
1027
+ async function directoryExists(dirPath) {
1028
+ return pathExists(dirPath, (stats) => stats.isDirectory());
1029
+ }
1030
+
1031
+ // src/templates/file-writer.ts
1032
+ var logger = (0, import_extensibility_tool_utils4._createLogger)({ name: "file-writer" });
1033
+ async function _promptOverwrite(filePath) {
1034
+ const prompt = `${filePath} exists. Overwrite [yNaq]? `;
1035
+ if (!process.stdin.isTTY) {
1036
+ const rl = (0, import_node_readline.createInterface)({
1037
+ input: process.stdin,
1038
+ output: process.stdout
1039
+ });
1040
+ return new Promise((resolve) => {
1041
+ rl.question(prompt, (answer) => {
1042
+ rl.close();
1043
+ const normalized = answer.toLowerCase().trim();
1044
+ switch (normalized) {
1045
+ case "y":
1046
+ case "yes":
1047
+ resolve("overwrite");
1048
+ break;
1049
+ case "n":
1050
+ case "no":
1051
+ case "":
1052
+ resolve("skip");
1053
+ break;
1054
+ case "a":
1055
+ case "all":
1056
+ resolve("overwrite-all");
1057
+ break;
1058
+ case "q":
1059
+ case "quit":
1060
+ resolve("abort");
1061
+ break;
1062
+ default:
1063
+ logger.warn("Invalid input '%s', treating as 'no'", answer);
1064
+ resolve("skip");
1065
+ }
1066
+ });
1067
+ });
1068
+ }
1069
+ process.stdout.write(prompt);
1070
+ return new Promise((resolve) => {
1071
+ const stdin = process.stdin;
1072
+ const wasRaw = stdin.isRaw;
1073
+ stdin.setRawMode(true);
1074
+ stdin.resume();
1075
+ const onData = (buffer) => {
1076
+ stdin.setRawMode(wasRaw || false);
1077
+ stdin.pause();
1078
+ stdin.removeListener("data", onData);
1079
+ const key = buffer.toString();
1080
+ const code = buffer[0];
1081
+ if (code === 3) {
1082
+ process.stdout.write("\nCancelled.\n");
1083
+ setTimeout(() => process.exit(0), 100);
1084
+ return;
1085
+ }
1086
+ if (code === 13 || code === 10) {
1087
+ process.stdout.write("n\n");
1088
+ resolve("skip");
1089
+ return;
1090
+ }
1091
+ const normalized = key.toLowerCase();
1092
+ let decision;
1093
+ switch (normalized) {
1094
+ case "y":
1095
+ process.stdout.write("y\n");
1096
+ decision = "overwrite";
1097
+ break;
1098
+ case "n":
1099
+ process.stdout.write("n\n");
1100
+ decision = "skip";
1101
+ break;
1102
+ case "a":
1103
+ process.stdout.write("a\n");
1104
+ decision = "overwrite-all";
1105
+ break;
1106
+ case "q":
1107
+ process.stdout.write("q\n");
1108
+ decision = "abort";
1109
+ break;
1110
+ default:
1111
+ process.stdout.write(`${key}
1112
+ `);
1113
+ logger.warn("Invalid input '%s', treating as 'no'", key);
1114
+ decision = "skip";
1115
+ }
1116
+ resolve(decision);
1117
+ };
1118
+ stdin.on("data", onData);
1119
+ });
1120
+ }
1121
+ async function _writeGeneratedFiles(files, options = {}) {
1122
+ const { cwd = process.cwd(), onFileWritten, onFileSkipped, onFileIdentical } = options;
1123
+ let write = options.write ?? "abort-if-existing";
1124
+ const existing = [];
1125
+ for (const file of files) {
1126
+ const fullPath = import_path.default.join(cwd, file.path);
1127
+ if (await fileExists(fullPath)) {
1128
+ existing.push(file.path);
1129
+ }
1130
+ }
1131
+ if (existing.length > 0 && write === "abort-if-existing") {
1132
+ if (onFileSkipped) {
1133
+ for (const file of files) {
1134
+ if (existing.includes(file.path)) {
1135
+ onFileSkipped(file);
1136
+ }
1137
+ }
1138
+ }
1139
+ return {
1140
+ written: [],
1141
+ existing,
1142
+ skipped: true,
1143
+ aborted: false
1144
+ };
1145
+ }
1146
+ const written = [];
1147
+ for (const file of files) {
1148
+ const fullPath = import_path.default.join(cwd, file.path);
1149
+ const fileDir = import_path.default.dirname(fullPath);
1150
+ const isExisting = existing.includes(file.path);
1151
+ if (isExisting) {
1152
+ const existingContent = await (0, import_promises2.readFile)(fullPath, "utf-8");
1153
+ if (existingContent === file.content) {
1154
+ if (onFileIdentical) {
1155
+ onFileIdentical(file);
1156
+ }
1157
+ continue;
1158
+ }
1159
+ }
1160
+ if (isExisting && (write === "if-missing" || file.precious)) {
1161
+ if (onFileSkipped) {
1162
+ onFileSkipped(file);
1163
+ }
1164
+ continue;
1165
+ }
1166
+ if (isExisting && typeof write === "function") {
1167
+ const decision = await write(file.path, cwd, file.content);
1168
+ switch (decision) {
1169
+ case "skip":
1170
+ if (onFileSkipped) {
1171
+ onFileSkipped(file);
1172
+ }
1173
+ continue;
1174
+ case "overwrite":
1175
+ break;
1176
+ case "overwrite-all":
1177
+ write = "overwrite-all";
1178
+ break;
1179
+ case "abort":
1180
+ return {
1181
+ written,
1182
+ existing,
1183
+ skipped: false,
1184
+ aborted: true
1185
+ };
1186
+ }
1187
+ }
1188
+ if (!await directoryExists(fileDir)) {
1189
+ await (0, import_promises2.mkdir)(fileDir, { recursive: true });
1190
+ }
1191
+ await (0, import_promises2.writeFile)(fullPath, file.content, "utf-8");
1192
+ if (onFileWritten) {
1193
+ onFileWritten(file, isExisting);
1194
+ }
1195
+ written.push(file.path);
1196
+ }
1197
+ return {
1198
+ written,
1199
+ existing,
1200
+ // Always populated; write='abort-if-existing' returns early above
1201
+ skipped: false,
1202
+ aborted: false
1203
+ };
1204
+ }
1205
+
1206
+ // src/templates/diff-viewer/diff-prompt.ts
1207
+ var import_node_path = __toESM(require("path"), 1);
1208
+
1209
+ // src/templates/diff-viewer/diff-generator.ts
1210
+ var import_diff = require("diff");
1211
+ var import_promises3 = require("fs/promises");
1212
+ async function generateDiff(filePath, oldContent, newContent, contextLines = 3) {
1213
+ if (isBinary(oldContent) || isBinary(newContent)) {
1214
+ return {
1215
+ lines: [{ type: "header", text: "Binary file changed" }],
1216
+ oldFileName: filePath,
1217
+ newFileName: filePath,
1218
+ isBinary: true
1219
+ };
1220
+ }
1221
+ const patch = (0, import_diff.createPatch)(filePath, oldContent, newContent, "existing", "new", {
1222
+ context: contextLines
1223
+ });
1224
+ const lines = parsePatch(patch);
1225
+ return {
1226
+ lines,
1227
+ oldFileName: filePath,
1228
+ newFileName: filePath,
1229
+ isBinary: false
1230
+ };
1231
+ }
1232
+ function parsePatch(patch) {
1233
+ const lines = [];
1234
+ const patchLines = patch.split("\n");
1235
+ let oldLine = 0;
1236
+ let newLine = 0;
1237
+ for (const line of patchLines) {
1238
+ if (line.startsWith("@@")) {
1239
+ const match = line.match(/@@ -(\d+),?\d* \+(\d+),?\d* @@/);
1240
+ if (match !== null) {
1241
+ oldLine = parseInt(match[1], 10);
1242
+ newLine = parseInt(match[2], 10);
1243
+ lines.push({ type: "header", text: line });
1244
+ }
1245
+ } else if (line.startsWith("+")) {
1246
+ lines.push({ type: "add", text: line, newLine: newLine++ });
1247
+ } else if (line.startsWith("-")) {
1248
+ lines.push({ type: "remove", text: line, oldLine: oldLine++ });
1249
+ } else if (line.startsWith(" ")) {
1250
+ lines.push({
1251
+ type: "context",
1252
+ text: line,
1253
+ oldLine: oldLine++,
1254
+ newLine: newLine++
1255
+ });
1256
+ } else if (line.startsWith("\\")) {
1257
+ lines.push({ type: "context", text: line });
1258
+ }
1259
+ }
1260
+ return lines;
1261
+ }
1262
+ function isBinary(content) {
1263
+ return content.includes("\0");
1264
+ }
1265
+ async function readExistingFile(resolvedPath) {
1266
+ try {
1267
+ return await (0, import_promises3.readFile)(resolvedPath, "utf-8");
1268
+ } catch (err) {
1269
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
1270
+ return "";
1271
+ }
1272
+ throw err;
1273
+ }
1274
+ }
1275
+
1276
+ // src/templates/diff-viewer/terminal-renderer.ts
1277
+ var import_child_process = require("child_process");
1278
+ var import_string_width = __toESM(require("string-width"), 1);
1279
+ var ANSI = {
1280
+ // Colors
1281
+ RED: "\x1B[31m",
1282
+ GREEN: "\x1B[32m",
1283
+ CYAN: "\x1B[36m",
1284
+ GRAY: "\x1B[90m",
1285
+ RESET: "\x1B[0m",
1286
+ // Text styles
1287
+ BOLD: "\x1B[1m",
1288
+ DIM: "\x1B[2m"
1289
+ };
1290
+ var BOX_HORIZONTAL = "\u2500";
1291
+ function render(state, filePath, clearPrevious = false) {
1292
+ const maxTotalHeight = Math.floor(state.terminalHeight * 0.75);
1293
+ const maxContentHeight = maxTotalHeight - 3;
1294
+ const contentHeight = state.diffLines.length;
1295
+ const windowHeight = Math.min(contentHeight, maxContentHeight);
1296
+ const visibleLines = state.diffLines.slice(
1297
+ state.scrollOffset,
1298
+ state.scrollOffset + windowHeight
1299
+ );
1300
+ const totalLines = state.diffLines.length;
1301
+ const startLine = state.scrollOffset + 1;
1302
+ const endLine = state.scrollOffset + visibleLines.length;
1303
+ if (clearPrevious && state.renderedHeight > 0) {
1304
+ clearPreviousRender(state.renderedHeight - 1);
1305
+ }
1306
+ let output = "";
1307
+ output += renderTopBar(filePath, state.terminalWidth) + "\n";
1308
+ for (const line of visibleLines) {
1309
+ output += colorize(line, state.terminalWidth) + "\n";
1310
+ }
1311
+ output += renderBottomBar(startLine, endLine, totalLines, state, state.terminalWidth) + "\n";
1312
+ output += "\n";
1313
+ output += `overwrite ${filePath} [yNaqd]? `;
1314
+ state.renderedHeight = 1 + visibleLines.length + 1 + 1 + 1;
1315
+ process.stdout.write(output);
1316
+ }
1317
+ function clearPreviousRender(lines) {
1318
+ process.stdout.write(`\x1B[${lines}A`);
1319
+ process.stdout.write("\r");
1320
+ process.stdout.write("\x1B[0J");
1321
+ }
1322
+ function renderTopBar(filePath, width) {
1323
+ const prefix = BOX_HORIZONTAL.repeat(3) + " ";
1324
+ const suffix = " " + BOX_HORIZONTAL.repeat(3);
1325
+ const availableWidth = width - (0, import_string_width.default)(prefix) - (0, import_string_width.default)(suffix);
1326
+ let displayName = filePath;
1327
+ if ((0, import_string_width.default)(displayName) + 1 > availableWidth) {
1328
+ while ((0, import_string_width.default)("..." + displayName) + 1 > availableWidth && displayName.length > 0) {
1329
+ displayName = displayName.slice(1);
1330
+ }
1331
+ displayName = "..." + displayName;
1332
+ }
1333
+ const paddingLength = Math.max(0, availableWidth - (0, import_string_width.default)(displayName) - 1);
1334
+ const padding = BOX_HORIZONTAL.repeat(paddingLength);
1335
+ return ANSI.CYAN + prefix + ANSI.BOLD + displayName + ANSI.RESET + " " + ANSI.CYAN + padding + suffix + ANSI.RESET;
1336
+ }
1337
+ function renderBottomBar(startLine, endLine, totalLines, _state, width) {
1338
+ const prefix = BOX_HORIZONTAL.repeat(3) + " ";
1339
+ const positionIndicator = `${startLine}-${endLine}/${totalLines}`;
1340
+ const content = positionIndicator;
1341
+ const suffix = " " + BOX_HORIZONTAL.repeat(3);
1342
+ const availableWidth = width - (0, import_string_width.default)(prefix) - (0, import_string_width.default)(suffix);
1343
+ const paddingLength = Math.max(0, availableWidth - (0, import_string_width.default)(content));
1344
+ const padding = BOX_HORIZONTAL.repeat(paddingLength);
1345
+ return ANSI.CYAN + prefix + ANSI.RESET + ANSI.DIM + content + ANSI.RESET + ANSI.CYAN + padding + suffix + ANSI.RESET;
1346
+ }
1347
+ function clearDiffWindow() {
1348
+ process.stdout.write("\n");
1349
+ }
1350
+ function colorize(line, terminalWidth) {
1351
+ const maxWidth = Math.max(10, terminalWidth - 3);
1352
+ const text = truncateLine(line.text, maxWidth);
1353
+ switch (line.type) {
1354
+ case "add":
1355
+ return ANSI.GREEN + text + ANSI.RESET;
1356
+ case "remove":
1357
+ return ANSI.RED + text + ANSI.RESET;
1358
+ case "header":
1359
+ return ANSI.CYAN + text + ANSI.RESET;
1360
+ case "context":
1361
+ return ANSI.GRAY + text + ANSI.RESET;
1362
+ default:
1363
+ return text;
1364
+ }
1365
+ }
1366
+ function truncateLine(text, maxWidth) {
1367
+ if ((0, import_string_width.default)(text) <= maxWidth) {
1368
+ return text;
1369
+ }
1370
+ let truncated = text;
1371
+ while ((0, import_string_width.default)(truncated + "...") > maxWidth && truncated.length > 0) {
1372
+ truncated = truncated.slice(0, -1);
1373
+ }
1374
+ return truncated + "...";
1375
+ }
1376
+ function getTerminalSize() {
1377
+ let columns = 80;
1378
+ let rows = 24;
1379
+ try {
1380
+ const sttyOutput = (0, import_child_process.execSync)("stty size </dev/tty", {
1381
+ encoding: "utf-8",
1382
+ stdio: ["ignore", "pipe", "ignore"],
1383
+ timeout: 200,
1384
+ shell: "/bin/bash"
1385
+ }).trim();
1386
+ const parts = sttyOutput.split(/\s+/);
1387
+ if (parts.length === 2) {
1388
+ const sttyRows = parseInt(parts[0], 10);
1389
+ const sttyCols = parseInt(parts[1], 10);
1390
+ if (!isNaN(sttyRows) && sttyRows > 0) {
1391
+ rows = sttyRows;
1392
+ }
1393
+ if (!isNaN(sttyCols) && sttyCols > 0) {
1394
+ columns = sttyCols;
1395
+ }
1396
+ }
1397
+ } catch {
1398
+ try {
1399
+ const tputCols = (0, import_child_process.execSync)("tput cols </dev/tty", {
1400
+ encoding: "utf-8",
1401
+ stdio: ["ignore", "pipe", "ignore"],
1402
+ timeout: 100,
1403
+ shell: "/bin/bash"
1404
+ }).trim();
1405
+ const cols = parseInt(tputCols, 10);
1406
+ if (!isNaN(cols) && cols > 0) {
1407
+ columns = cols;
1408
+ }
1409
+ } catch {
1410
+ }
1411
+ try {
1412
+ const tputRows = (0, import_child_process.execSync)("tput lines </dev/tty", {
1413
+ encoding: "utf-8",
1414
+ stdio: ["ignore", "pipe", "ignore"],
1415
+ timeout: 100,
1416
+ shell: "/bin/bash"
1417
+ }).trim();
1418
+ const lns = parseInt(tputRows, 10);
1419
+ if (!isNaN(lns) && lns > 0) {
1420
+ rows = lns;
1421
+ }
1422
+ } catch {
1423
+ }
1424
+ }
1425
+ return { rows, columns };
1426
+ }
1427
+
1428
+ // src/templates/diff-viewer/diff-prompt.ts
1429
+ var import_extensibility_tool_utils5 = require("@stripe/extensibility-tool-utils");
1430
+ var logger2 = (0, import_extensibility_tool_utils5._createLogger)({ name: "diff-prompt" });
1431
+ function isInteractiveTerminal() {
1432
+ if (process.env["CI"] === "true" || process.env["CI"] === "1") {
1433
+ return false;
1434
+ }
1435
+ const term = process.env["TERM"];
1436
+ if (!term || term === "dumb") {
1437
+ return false;
1438
+ }
1439
+ if (typeof process.stdin.setRawMode !== "function") {
1440
+ return false;
1441
+ }
1442
+ const termSize = getTerminalSize();
1443
+ if (termSize.rows === 24 && termSize.columns === 80) {
1444
+ }
1445
+ return true;
1446
+ }
1447
+ async function _advancedDiffPrompt(filePath, cwd, newContent) {
1448
+ const resolvedPath = import_node_path.default.resolve(cwd, filePath);
1449
+ if (!isInteractiveTerminal()) {
1450
+ return await _promptOverwrite(filePath);
1451
+ }
1452
+ try {
1453
+ const existingContent = await readExistingFile(resolvedPath);
1454
+ const diffResult = await generateDiff(filePath, existingContent, newContent);
1455
+ const termSize = getTerminalSize();
1456
+ if (termSize.rows < 20) {
1457
+ return await _promptOverwrite(filePath);
1458
+ }
1459
+ if (diffResult.lines.length > 5e3) {
1460
+ logger2.info("Diff too large to display comfortably");
1461
+ return await _promptOverwrite(filePath);
1462
+ }
1463
+ const wasRaw = process.stdin.isRaw ?? false;
1464
+ try {
1465
+ process.stdin.setRawMode(true);
1466
+ } catch {
1467
+ return await _promptOverwrite(filePath);
1468
+ }
1469
+ process.stdin.resume();
1470
+ const maxTotalHeight = Math.floor(termSize.rows * 0.75);
1471
+ const maxContentHeight = maxTotalHeight - 3;
1472
+ const windowHeight = Math.min(diffResult.lines.length, maxContentHeight);
1473
+ const state = {
1474
+ scrollOffset: 0,
1475
+ maxScroll: Math.max(0, diffResult.lines.length - windowHeight),
1476
+ diffLines: diffResult.lines,
1477
+ terminalHeight: termSize.rows,
1478
+ terminalWidth: termSize.columns,
1479
+ wasRaw,
1480
+ renderedHeight: 0,
1481
+ fullFileMode: false
1482
+ };
1483
+ render(state, filePath, false);
1484
+ return new Promise((resolve) => {
1485
+ const onExit = () => {
1486
+ cleanup(state.wasRaw, onData, onExit);
1487
+ };
1488
+ const onData = (buffer) => {
1489
+ handleKeypress(buffer, state, filePath, newContent, existingContent).then((result) => {
1490
+ if (result !== "continue") {
1491
+ cleanup(state.wasRaw, onData, onExit);
1492
+ resolve(result);
1493
+ }
1494
+ }).catch((err) => {
1495
+ cleanup(state.wasRaw, onData, onExit);
1496
+ logger2.error({ err }, "Error handling keypress");
1497
+ resolve("abort");
1498
+ });
1499
+ };
1500
+ process.stdin.on("data", onData);
1501
+ process.on("exit", onExit);
1502
+ });
1503
+ } catch (err) {
1504
+ logger2.warn({ err }, "Error displaying diff, using basic prompt");
1505
+ return await _promptOverwrite(filePath);
1506
+ }
1507
+ }
1508
+ async function handleKeypress(buffer, state, filePath, newContent, existingContent) {
1509
+ const code = buffer[0];
1510
+ const key = buffer.toString();
1511
+ if (code === 3) {
1512
+ process.stdout.write("\nCancelled.\n");
1513
+ return "abort";
1514
+ }
1515
+ switch (key.toLowerCase()) {
1516
+ case "y":
1517
+ return "overwrite";
1518
+ case "n":
1519
+ case "\r":
1520
+ case "\n":
1521
+ return "skip";
1522
+ case "a":
1523
+ return "overwrite-all";
1524
+ case "q":
1525
+ return "abort";
1526
+ case "d":
1527
+ await toggleDiffContext(state, filePath, newContent, existingContent);
1528
+ return "continue";
1529
+ }
1530
+ if (buffer.length >= 3 && buffer[0] === 27 && buffer[1] === 91) {
1531
+ const maxTotalHeight = Math.floor(state.terminalHeight * 0.75);
1532
+ const maxContentHeight = maxTotalHeight - 3;
1533
+ const windowHeight = Math.min(state.diffLines.length, maxContentHeight);
1534
+ let scrollDelta = 0;
1535
+ if (buffer[2] === 65) {
1536
+ scrollDelta = -1;
1537
+ } else if (buffer[2] === 66) {
1538
+ scrollDelta = 1;
1539
+ } else if (buffer[2] === 53) {
1540
+ scrollDelta = -windowHeight;
1541
+ } else if (buffer[2] === 54) {
1542
+ scrollDelta = windowHeight;
1543
+ }
1544
+ const newScrollOffset = Math.max(
1545
+ 0,
1546
+ Math.min(state.maxScroll, state.scrollOffset + scrollDelta)
1547
+ );
1548
+ if (newScrollOffset !== state.scrollOffset) {
1549
+ state.scrollOffset = newScrollOffset;
1550
+ render(state, filePath, true);
1551
+ }
1552
+ }
1553
+ return "continue";
1554
+ }
1555
+ function cleanup(wasRaw, onData, onExit) {
1556
+ if (process.stdin.setRawMode !== void 0) {
1557
+ process.stdin.setRawMode(wasRaw);
1558
+ }
1559
+ process.stdin.pause();
1560
+ if (onData) {
1561
+ process.stdin.off("data", onData);
1562
+ }
1563
+ if (onExit) {
1564
+ process.off("exit", onExit);
1565
+ }
1566
+ clearDiffWindow();
1567
+ }
1568
+ async function toggleDiffContext(state, filePath, newContent, existingContent) {
1569
+ state.fullFileMode = !state.fullFileMode;
1570
+ const contextLines = state.fullFileMode ? 1e4 : 3;
1571
+ const visibleStartIndex = state.scrollOffset;
1572
+ let referenceLineFinder = null;
1573
+ let skippedLines = 0;
1574
+ for (let i = visibleStartIndex; i < state.diffLines.length; i++) {
1575
+ const line = state.diffLines[i];
1576
+ if (line !== void 0) {
1577
+ if (line.type === "header") {
1578
+ skippedLines++;
1579
+ continue;
1580
+ }
1581
+ if (line.newLine !== void 0) {
1582
+ const targetNewLine = line.newLine;
1583
+ referenceLineFinder = (dl) => dl.newLine !== void 0 && dl.newLine >= targetNewLine - skippedLines;
1584
+ break;
1585
+ } else if (line.oldLine !== void 0) {
1586
+ const targetOldLine = line.oldLine;
1587
+ referenceLineFinder = (dl) => dl.oldLine !== void 0 && dl.oldLine >= targetOldLine - skippedLines;
1588
+ break;
1589
+ }
1590
+ }
1591
+ }
1592
+ const diffResult = await generateDiff(
1593
+ filePath,
1594
+ existingContent,
1595
+ newContent,
1596
+ contextLines
1597
+ );
1598
+ state.diffLines = diffResult.lines;
1599
+ let newScrollOffset = 0;
1600
+ if (referenceLineFinder !== null) {
1601
+ const referenceIndex = diffResult.lines.findIndex(referenceLineFinder);
1602
+ if (referenceIndex !== -1) {
1603
+ newScrollOffset = Math.max(0, referenceIndex);
1604
+ }
1605
+ }
1606
+ const maxTotalHeight = Math.floor(state.terminalHeight * 0.75);
1607
+ const maxContentHeight = maxTotalHeight - 3;
1608
+ const windowHeight = Math.min(diffResult.lines.length, maxContentHeight);
1609
+ state.maxScroll = Math.max(0, diffResult.lines.length - windowHeight);
1610
+ state.scrollOffset = Math.min(newScrollOffset, state.maxScroll);
1611
+ render(state, filePath, true);
1612
+ }
1613
+
1614
+ // src/templates/extensions/types.ts
1615
+ var _ExtensionTemplateManager = class extends import_extensibility_tool_utils._TemplateManager {
1616
+ /**
1617
+ * Get summary info for all registered extension templates
1618
+ */
1619
+ getTemplateInfo() {
1620
+ return this.getTemplateEntries().map(([key, t]) => ({
1621
+ key,
1622
+ description: t.description,
1623
+ deprecated: t.deprecated ?? false,
1624
+ hidden: t.hidden ?? false,
1625
+ methods: t.methods
1626
+ }));
1627
+ }
1628
+ };
1629
+
1630
+ // src/dependencies/index.ts
1631
+ var import_node_path2 = __toESM(require("path"), 1);
1632
+ var import_node_fs = __toESM(require("fs"), 1);
1633
+ var import_node_os = __toESM(require("os"), 1);
1634
+ var import_node_child_process = require("child_process");
1635
+ var import_package_json = __toESM(require("@npmcli/package-json"), 1);
1636
+ var semver = __toESM(require("semver"), 1);
1637
+ var import_js_toml = require("js-toml");
1638
+ var import_extensibility_tool_utils6 = require("@stripe/extensibility-tool-utils");
1639
+ function _npmDep(name, version) {
1640
+ return { type: "npm", name, version };
1641
+ }
1642
+ function _devNpmDep(name, version) {
1643
+ return { type: "dev-npm", name, version };
1644
+ }
1645
+
1646
+ // src/templates/extensions/base.ts
1647
+ var import_extensibility_tool_utils7 = require("@stripe/extensibility-tool-utils");
1648
+ var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
1649
+ var LANGUAGE_SERVER_PACKAGE_NAME = "@stripe/extensibility-language-server";
1650
+ var LANGUAGE_SERVER_PACKAGE_VERSION = "^0.2.0";
1651
+ function _createExtensionEslintConfigFile(params, context) {
1652
+ const { id, extensionInterfaceId } = params;
1653
+ const { fs: fs2 } = context;
1654
+ return {
1655
+ path: `extensions/${id}/eslint.config.mts`,
1656
+ content: fs2.mustache(
1657
+ { extensionInterfaceId },
1658
+ "common",
1659
+ "eslint.config.mts.mustache"
1660
+ ),
1661
+ precious: true
1662
+ };
1663
+ }
1664
+ function _createBaseOutput(params, context) {
1665
+ const { id } = params;
1666
+ const { fs: fs2 } = context;
1667
+ return {
1668
+ files: [
1669
+ {
1670
+ path: `extensions/${id}/package.json`,
1671
+ content: fs2.mustache(params, "common", "package.json.mustache")
1672
+ },
1673
+ {
1674
+ ..._createExtensionEslintConfigFile(params, context)
1675
+ },
1676
+ {
1677
+ path: `extensions/${id}/tsconfig.build.json`,
1678
+ content: fs2.mustache(params, "common", "tsconfig.build.json.mustache")
1679
+ },
1680
+ {
1681
+ path: `extensions/${id}/tsconfig.json`,
1682
+ content: fs2.mustache(params, "common", "tsconfig.json.mustache")
1683
+ },
1684
+ {
1685
+ path: `extensions/${id}/.prettierignore`,
1686
+ content: fs2.textFile("common", ".prettierignore")
1687
+ }
1688
+ ],
1689
+ methods: {},
1690
+ dependencies: {
1691
+ // Exact pin (no caret) — the SDK is tightly coupled to dev-tools and
1692
+ // must match the version that generated the extension scaffolding.
1693
+ runtime: [_npmDep(SDK_PACKAGE_NAME, (0, import_extensibility_tool_utils7._workspaceVersion)(SDK_PACKAGE_NAME))],
1694
+ dev: [_devNpmDep(LANGUAGE_SERVER_PACKAGE_NAME, LANGUAGE_SERVER_PACKAGE_VERSION)]
1695
+ },
1696
+ postGenerationHooks: [
1697
+ {
1698
+ script: "build",
1699
+ description: "Build extension"
1700
+ },
1701
+ {
1702
+ exec: "prettier --write .",
1703
+ description: "Format generated files"
1704
+ }
1705
+ ]
1706
+ };
1707
+ }
1708
+
1709
+ // src/templates/extensions/core.workflows.custom_action.ts
1710
+ var EXTENSION_INTERFACE_ID = "core.workflows.custom_action";
1711
+ var customActionTemplate = {
1712
+ methods: {
1713
+ execute: { implementation_types: ["script", "remote-function"] },
1714
+ get_form_state: { implementation_types: ["script", "remote-function"] }
1715
+ },
1716
+ 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.",
1717
+ generate: (params, context) => {
1718
+ const { id } = params;
1719
+ const { fs: fs2 } = context;
1720
+ const base = _createBaseOutput(
1721
+ {
1722
+ ...params,
1723
+ extensionInterfaceId: EXTENSION_INTERFACE_ID,
1724
+ executionProfile: "egress"
1725
+ },
1726
+ context
1727
+ );
1728
+ return {
1729
+ ...base,
1730
+ files: [
1731
+ {
1732
+ path: `extensions/${id}/src/index.ts`,
1733
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "index.ts"),
1734
+ precious: true
1735
+ },
1736
+ {
1737
+ path: `extensions/${id}/src/custom_input.schema.json`,
1738
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "custom_input.schema.json"),
1739
+ precious: true
1740
+ },
1741
+ {
1742
+ path: `extensions/${id}/src/index.test.ts`,
1743
+ content: fs2.textFile(EXTENSION_INTERFACE_ID, "index.test.ts"),
1744
+ precious: true
1745
+ },
1746
+ ...base.files
1747
+ ],
1748
+ methods: {
1749
+ execute: {
1750
+ implementation_type: "script",
1751
+ custom_input: {
1752
+ input_schema: {
1753
+ type: "json_schema",
1754
+ content: `extensions/${id}/src/custom_input.schema.json`
1755
+ }
1756
+ }
1757
+ },
1758
+ get_form_state: {
1759
+ implementation_type: "script"
1760
+ }
1761
+ }
1762
+ };
1763
+ }
1764
+ };
1765
+ var core_workflows_custom_action_default = {
1766
+ [EXTENSION_INTERFACE_ID]: customActionTemplate
1767
+ };
1768
+
1769
+ // src/templates/extensions/extend.objects.custom_objects.ts
1770
+ var EXTENSION_INTERFACE_ID2 = "extend.objects.custom_objects";
1771
+ var customObjectsTemplate = {
1772
+ methods: {
1773
+ execute_method: { implementation_types: ["script"] }
1774
+ },
1775
+ description: "Methods extension for custom object actions. Generated at build time \u2014 the transformed custom object class becomes the entry point.",
1776
+ hidden: true,
1777
+ generate: (params, context) => {
1778
+ const base = _createBaseOutput(
1779
+ {
1780
+ ...params,
1781
+ extensionInterfaceId: EXTENSION_INTERFACE_ID2,
1782
+ executionProfile: "egress"
1783
+ },
1784
+ context
1785
+ );
1786
+ return {
1787
+ ...base,
1788
+ methods: {
1789
+ execute_method: {
1790
+ implementation_type: "script"
1791
+ }
1792
+ }
1793
+ };
1794
+ }
1795
+ };
1796
+ var extend_objects_custom_objects_default = {
1797
+ [EXTENSION_INTERFACE_ID2]: customObjectsTemplate
1798
+ };
1799
+
1800
+ // src/templates/extensions/extend.workflows.custom_action.ts
1801
+ var EXTENSION_INTERFACE_ID3 = "extend.workflows.custom_action";
1802
+ var extendCustomActionTemplate = {
1803
+ methods: {
1804
+ execute: { implementation_types: ["script", "remote-function"] },
1805
+ get_form_state: { implementation_types: ["script", "remote-function"] }
1806
+ },
1807
+ 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.",
1808
+ generate: (params, context) => {
1809
+ const { id } = params;
1810
+ const { fs: fs2 } = context;
1811
+ const base = _createBaseOutput(
1812
+ {
1813
+ ...params,
1814
+ extensionInterfaceId: EXTENSION_INTERFACE_ID3,
1815
+ executionProfile: "egress"
1816
+ },
1817
+ context
1818
+ );
1819
+ return {
1820
+ ...base,
1821
+ files: [
1822
+ {
1823
+ path: `extensions/${id}/src/index.ts`,
1824
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "index.ts"),
1825
+ precious: true
1826
+ },
1827
+ {
1828
+ path: `extensions/${id}/src/custom_input.schema.json`,
1829
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "custom_input.schema.json"),
1830
+ precious: true
1831
+ },
1832
+ {
1833
+ path: `extensions/${id}/src/index.test.ts`,
1834
+ content: fs2.textFile(EXTENSION_INTERFACE_ID3, "index.test.ts"),
1835
+ precious: true
1836
+ },
1837
+ ...base.files
1838
+ ],
1839
+ methods: {
1840
+ execute: {
1841
+ implementation_type: "script",
1842
+ custom_input: {
1843
+ input_schema: {
1844
+ type: "json_schema",
1845
+ content: `extensions/${id}/src/custom_input.schema.json`
1846
+ }
1847
+ }
1848
+ },
1849
+ get_form_state: {
1850
+ implementation_type: "script"
1851
+ }
1852
+ }
1853
+ };
1854
+ }
1855
+ };
1856
+ var extend_workflows_custom_action_default = {
1857
+ [EXTENSION_INTERFACE_ID3]: extendCustomActionTemplate
1858
+ };
1859
+
1860
+ // src/templates/extensions/billing.customer_balance_application.ts
1861
+ var EXTENSION_INTERFACE_ID4 = "billing.customer_balance_application";
1862
+ var customerBalanceApplicationTemplate = {
1863
+ methods: {
1864
+ compute_applied_customer_balance: { implementation_types: ["script"] }
1865
+ },
1866
+ description: "Implement custom logic to control when and how much customer balance is applied to subscription invoices using scripts.",
1867
+ generate: (params, context) => {
1868
+ const { id } = params;
1869
+ const { fs: fs2 } = context;
1870
+ const base = _createBaseOutput(
1871
+ {
1872
+ ...params,
1873
+ extensionInterfaceId: EXTENSION_INTERFACE_ID4,
1874
+ executionProfile: "restricted"
1875
+ },
1876
+ context
1877
+ );
1878
+ return {
1879
+ ...base,
1880
+ files: [
1881
+ {
1882
+ path: `extensions/${id}/src/index.ts`,
1883
+ content: fs2.textFile(EXTENSION_INTERFACE_ID4, "index.ts"),
1884
+ precious: true
1885
+ },
1886
+ {
1887
+ path: `extensions/${id}/src/index.test.ts`,
1888
+ content: fs2.textFile(EXTENSION_INTERFACE_ID4, "index.test.ts"),
1889
+ precious: true
1890
+ },
1891
+ ...base.files
1892
+ ],
1893
+ methods: {
1894
+ compute_applied_customer_balance: {
1895
+ implementation_type: "script"
1896
+ }
1897
+ }
1898
+ };
1899
+ }
1900
+ };
1901
+ var billing_customer_balance_application_default = {
1902
+ [EXTENSION_INTERFACE_ID4]: customerBalanceApplicationTemplate
1903
+ };
1904
+
1905
+ // src/templates/extensions/billing.bill.discount_calculation.ts
1906
+ var EXTENSION_INTERFACE_ID5 = "billing.bill.discount_calculation";
1907
+ var discountCalculationTemplate = {
1908
+ hidden: true,
1909
+ methods: {
1910
+ compute_discounts: { implementation_types: ["script"] }
1911
+ },
1912
+ description: "Create coupons with custom scripting logic for dynamic discounts based on subscription attributes, customer metadata, and complex business rules.",
1913
+ generate: (params, context) => {
1914
+ const { id } = params;
1915
+ const { fs: fs2 } = context;
1916
+ const base = _createBaseOutput(
1917
+ {
1918
+ ...params,
1919
+ extensionInterfaceId: EXTENSION_INTERFACE_ID5,
1920
+ executionProfile: "restricted"
1921
+ },
1922
+ context
1923
+ );
1924
+ return {
1925
+ ...base,
1926
+ files: [
1927
+ {
1928
+ path: `extensions/${id}/src/index.ts`,
1929
+ content: fs2.textFile(EXTENSION_INTERFACE_ID5, "index.ts"),
1930
+ precious: true
1931
+ },
1932
+ {
1933
+ path: `extensions/${id}/src/index.test.ts`,
1934
+ content: fs2.textFile(EXTENSION_INTERFACE_ID5, "index.test.ts"),
1935
+ precious: true
1936
+ },
1937
+ ...base.files
1938
+ ],
1939
+ methods: {
1940
+ compute_discounts: {
1941
+ implementation_type: "script"
1942
+ }
1943
+ }
1944
+ };
1945
+ }
1946
+ };
1947
+ var billing_bill_discount_calculation_default = {
1948
+ [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
1949
+ };
1950
+
1951
+ // src/templates/extensions/billing.invoice_collection_setting.ts
1952
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
1953
+ var invoiceCollectionSettingTemplate = {
1954
+ hidden: true,
1955
+ methods: {
1956
+ collection_override: { implementation_types: ["script"] }
1957
+ },
1958
+ description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
1959
+ generate: (params, context) => {
1960
+ const { id } = params;
1961
+ const { fs: fs2 } = context;
1962
+ const base = _createBaseOutput(
1963
+ {
1964
+ ...params,
1965
+ extensionInterfaceId: EXTENSION_INTERFACE_ID6,
1966
+ executionProfile: "restricted"
1967
+ },
1968
+ context
1969
+ );
1970
+ return {
1971
+ ...base,
1972
+ files: [
1973
+ {
1974
+ path: `extensions/${id}/src/index.ts`,
1975
+ content: fs2.textFile(EXTENSION_INTERFACE_ID6, "index.ts"),
1976
+ precious: true
1977
+ },
1978
+ {
1979
+ path: `extensions/${id}/src/index.test.ts`,
1980
+ content: fs2.textFile(EXTENSION_INTERFACE_ID6, "index.test.ts"),
1981
+ precious: true
1982
+ },
1983
+ ...base.files
1984
+ ],
1985
+ methods: {
1986
+ collection_override: {
1987
+ implementation_type: "script"
1988
+ }
1989
+ }
1990
+ };
1991
+ }
1992
+ };
1993
+ var billing_invoice_collection_setting_default = {
1994
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
1995
+ };
1996
+
1997
+ // src/templates/extensions/billing.prorations.ts
1998
+ var EXTENSION_INTERFACE_ID7 = "billing.prorations";
1999
+ var prorationsTemplate = {
2000
+ methods: {
2001
+ prorate_items: { implementation_types: ["script"] }
2002
+ },
2003
+ description: "Create custom proration logic for subscriptions using scripts to handle upgrades, downgrades, and mid-cycle changes.",
2004
+ generate: (params, context) => {
2005
+ const { id } = params;
2006
+ const { fs: fs2 } = context;
2007
+ const base = _createBaseOutput(
2008
+ {
2009
+ ...params,
2010
+ extensionInterfaceId: EXTENSION_INTERFACE_ID7,
2011
+ executionProfile: "restricted"
2012
+ },
2013
+ context
2014
+ );
2015
+ return {
2016
+ ...base,
2017
+ files: [
2018
+ {
2019
+ path: `extensions/${id}/src/index.ts`,
2020
+ content: fs2.textFile(EXTENSION_INTERFACE_ID7, "index.ts"),
2021
+ precious: true
2022
+ },
2023
+ {
2024
+ path: `extensions/${id}/src/index.test.ts`,
2025
+ content: fs2.textFile(EXTENSION_INTERFACE_ID7, "index.test.ts"),
2026
+ precious: true
2027
+ },
2028
+ ...base.files
2029
+ ],
2030
+ methods: {
2031
+ prorate_items: {
2032
+ implementation_type: "script"
2033
+ }
2034
+ }
2035
+ };
2036
+ }
2037
+ };
2038
+ var billing_prorations_default = {
2039
+ [EXTENSION_INTERFACE_ID7]: prorationsTemplate
2040
+ };
2041
+
2042
+ // src/templates/extensions/billing.recurring_billing_item_handling.ts
2043
+ var EXTENSION_INTERFACE_ID8 = "billing.recurring_billing_item_handling";
2044
+ var template = {
2045
+ methods: {
2046
+ before_item_creation: { implementation_types: ["script"] },
2047
+ filter_items: { implementation_types: ["script"] },
2048
+ group_items: { implementation_types: ["script"] }
2049
+ },
2050
+ description: "Customize how recurring billing items are filtered, grouped, and created during subscription billing runs.",
2051
+ generate: (params, context) => {
2052
+ const { id } = params;
2053
+ const { fs: fs2 } = context;
2054
+ const base = _createBaseOutput(
2055
+ {
2056
+ ...params,
2057
+ extensionInterfaceId: EXTENSION_INTERFACE_ID8,
2058
+ executionProfile: "restricted"
2059
+ },
2060
+ context
2061
+ );
2062
+ return {
2063
+ ...base,
2064
+ files: [
2065
+ {
2066
+ path: `extensions/${id}/src/index.ts`,
2067
+ content: fs2.textFile(EXTENSION_INTERFACE_ID8, "index.ts"),
2068
+ precious: true
2069
+ },
2070
+ {
2071
+ path: `extensions/${id}/src/index.test.ts`,
2072
+ content: fs2.textFile(EXTENSION_INTERFACE_ID8, "index.test.ts"),
2073
+ precious: true
2074
+ },
2075
+ ...base.files
2076
+ ],
2077
+ methods: {
2078
+ before_item_creation: {
2079
+ implementation_type: "script"
2080
+ },
2081
+ filter_items: {
2082
+ implementation_type: "script"
2083
+ },
2084
+ group_items: {
2085
+ implementation_type: "script"
2086
+ }
2087
+ }
2088
+ };
2089
+ }
2090
+ };
2091
+ var billing_recurring_billing_item_handling_default = {
2092
+ [EXTENSION_INTERFACE_ID8]: template
2093
+ };
2094
+
2095
+ // src/templates/extensions/registry.ts
2096
+ var DEFAULT_TEMPLATES = {
2097
+ ...core_workflows_custom_action_default,
2098
+ ...extend_objects_custom_objects_default,
2099
+ ...extend_workflows_custom_action_default,
2100
+ ...billing_customer_balance_application_default,
2101
+ ...billing_bill_discount_calculation_default,
2102
+ ...billing_invoice_collection_setting_default,
2103
+ ...billing_prorations_default,
2104
+ ...billing_recurring_billing_item_handling_default
2105
+ };
2106
+ var registry_default = DEFAULT_TEMPLATES;
2107
+
2108
+ // src/templates/extensions/index.ts
2109
+ var _templateManager = new _ExtensionTemplateManager(
2110
+ registry_default,
2111
+ _fs.scope("extensions")
2112
+ );
2113
+
2114
+ // src/templates/root/index.ts
2115
+ var import_extensibility_tool_utils8 = require("@stripe/extensibility-tool-utils");
2116
+ var EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME = "@stripe/extensibility-eslint-plugin";
2117
+ var EXTENSIBILITY_ESLINT_PLUGIN_VERSION = `^${(0, import_extensibility_tool_utils8._workspaceVersion)(EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME)}`;
2118
+ var _rootWorkspaceTemplate = {
2119
+ generate: (params, context) => {
2120
+ const { fs: fs2 } = context;
2121
+ return {
2122
+ files: [
2123
+ {
2124
+ path: "stripe-app.yaml",
2125
+ content: fs2.mustache(params, "stripe-app.yaml.mustache"),
2126
+ precious: true
2127
+ },
2128
+ {
2129
+ path: "package.json",
2130
+ content: fs2.mustache(params, "package.json.mustache")
2131
+ },
2132
+ {
2133
+ path: ".husky/pre-commit",
2134
+ content: fs2.textFile(".husky/pre-commit")
2135
+ },
2136
+ {
2137
+ path: "tsconfig.base.json",
2138
+ content: fs2.textFile("tsconfig.base.json")
2139
+ },
2140
+ {
2141
+ path: "tsconfig.json",
2142
+ content: fs2.textFile("tsconfig.json")
2143
+ },
2144
+ {
2145
+ path: "eslint.config.mts",
2146
+ content: fs2.textFile("eslint.config.mts")
2147
+ },
2148
+ {
2149
+ path: "vitest.config.mts",
2150
+ content: fs2.textFile("vitest.config.mts")
2151
+ },
2152
+ {
2153
+ path: ".gitignore",
2154
+ content: fs2.textFile("_gitignore")
2155
+ },
2156
+ {
2157
+ path: "pnpm-workspace.yaml",
2158
+ content: fs2.textFile("pnpm-workspace.yaml")
2159
+ },
2160
+ {
2161
+ path: ".prettierrc",
2162
+ content: fs2.textFile(".prettierrc")
2163
+ },
2164
+ {
2165
+ path: ".prettierignore",
2166
+ content: fs2.textFile(".prettierignore")
2167
+ },
2168
+ {
2169
+ path: "custom-objects/package.json",
2170
+ content: fs2.textFile("custom-objects/package.json"),
2171
+ precious: true
2172
+ },
2173
+ {
2174
+ path: "custom-objects/tsconfig.json",
2175
+ content: fs2.textFile("custom-objects/tsconfig.json"),
2176
+ precious: true
2177
+ },
2178
+ {
2179
+ path: "ui/package.json",
2180
+ content: fs2.textFile("ui/package.json"),
2181
+ precious: true
2182
+ },
2183
+ {
2184
+ path: "tools/test.mts",
2185
+ content: fs2.textFile("tools/test.mts")
2186
+ },
2187
+ {
2188
+ // temporarily add dummy JSON manifest until stripe apps plugin is fixed
2189
+ path: "stripe-app.json",
2190
+ content: "{}\n"
2191
+ }
2192
+ ],
2193
+ dependencies: {
2194
+ dev: [
2195
+ _devNpmDep("@eslint/js", "^9.0.0"),
2196
+ _devNpmDep(
2197
+ EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME,
2198
+ EXTENSIBILITY_ESLINT_PLUGIN_VERSION
2199
+ ),
2200
+ _devNpmDep(LANGUAGE_SERVER_PACKAGE_NAME, LANGUAGE_SERVER_PACKAGE_VERSION),
2201
+ _devNpmDep("@types/node", "^20.19.0"),
2202
+ _devNpmDep(
2203
+ "@stripe/extensibility-dev-tools",
2204
+ `^${(0, import_extensibility_tool_utils8._workspaceVersion)("@stripe/extensibility-dev-tools")}`
2205
+ ),
2206
+ _devNpmDep("concurrently", "^9.2.1"),
2207
+ _devNpmDep("eslint", "^9.0.0"),
2208
+ _devNpmDep("eslint-config-prettier", "^10.1.8"),
2209
+ _devNpmDep("eslint-plugin-workspaces", "^0.12.1"),
2210
+ _devNpmDep("globals", "^17.4.0"),
2211
+ _devNpmDep("husky", "^9.1.7"),
2212
+ _devNpmDep("jiti", "^2.6.1"),
2213
+ _devNpmDep("lint-staged", "^16.2.7"),
2214
+ _devNpmDep("chokidar-cli", "^3.0.0"),
2215
+ _devNpmDep("prettier", "^3.8.1"),
2216
+ _devNpmDep("ts-node", "^10.9.2"),
2217
+ _devNpmDep("tsx", "^4.21.0"),
2218
+ _devNpmDep("typescript", "^5.9.3"),
2219
+ _devNpmDep("typescript-eslint", "^8.54.0"),
2220
+ _devNpmDep("vitest", "^3.0.0")
2221
+ ]
2222
+ },
2223
+ postGenerationHooks: [
2224
+ {
2225
+ exec: "prettier --write .",
2226
+ description: "Format generated files"
2227
+ }
2228
+ ]
2229
+ };
2230
+ }
2231
+ };
2232
+ var _rootTemplateManager = new import_extensibility_tool_utils3._SingleTemplateManager(_rootWorkspaceTemplate, _fs.scope("root"));
2233
+ // Annotate the CommonJS export names for ESM import in node:
2234
+ 0 && (module.exports = {
2235
+ _ExtensionTemplateManager,
2236
+ _SingleTemplateManager,
2237
+ _TemplateManager,
2238
+ _advancedDiffPrompt,
2239
+ _createExtensionEslintConfigFile,
2240
+ _createSimpleSingleFileTemplate,
2241
+ _createSimpleTemplate,
2242
+ _fs,
2243
+ _promptOverwrite,
2244
+ _rootTemplateManager,
2245
+ _rootWorkspaceTemplate,
2246
+ _templateManager,
2247
+ _writeGeneratedFiles
2248
+ });