@stripe/extensibility-dev-tools 0.24.3 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/bin/build-custom-object-definitions.cjs +165 -34
  2. package/dist/bin/build-custom-object-definitions.js +156 -25
  3. package/dist/bin/create-upload-image.cjs +164 -33
  4. package/dist/bin/create-upload-image.js +156 -25
  5. package/dist/bin/dev-tools-rpc.cjs +199 -59
  6. package/dist/bin/dev-tools-rpc.js +174 -34
  7. package/dist/bin/gen-workspace.cjs +187 -47
  8. package/dist/bin/gen-workspace.js +174 -34
  9. package/dist/bin/template-info.cjs +161 -30
  10. package/dist/bin/template-info.js +156 -25
  11. package/dist/custom-objects/generated/proto/custom_objects/pub/api/app_api/object_definitions_app_service.pb.d.ts +32 -0
  12. package/dist/custom-objects/generated/proto/custom_objects/pub/api/app_api/object_definitions_app_service.pb.d.ts.map +1 -1
  13. package/dist/custom-objects/generated/proto/google/protobuf/descriptor.pb.d.ts +2 -2
  14. package/dist/custom-objects/generated/proto/google/protobuf/wrappers.pb.d.ts +168 -0
  15. package/dist/custom-objects/generated/proto/google/protobuf/wrappers.pb.d.ts.map +1 -0
  16. package/dist/custom-objects/generated/proto/proto/extensions.pb.d.ts +4 -4
  17. package/dist/custom-objects/generated/proto/proto/extensions.pb.d.ts.map +1 -1
  18. package/dist/custom-objects/generated/proto/vendor/proto/model/common/common_model.pb.d.ts +1553 -0
  19. package/dist/custom-objects/generated/proto/vendor/proto/model/common/common_model.pb.d.ts.map +1 -0
  20. package/dist/custom-objects/generated/proto/vendor/proto/model/common/kronos_model.pb.d.ts +1372 -0
  21. package/dist/custom-objects/generated/proto/vendor/proto/model/common/kronos_model.pb.d.ts.map +1 -0
  22. package/dist/custom-objects/generated/proto/vendor/publicapi/api_group_enum.pb.d.ts +2 -0
  23. package/dist/custom-objects/generated/proto/vendor/publicapi/api_group_enum.pb.d.ts.map +1 -1
  24. package/dist/custom-objects/generated/proto/vendor/publicapi/extension_interface.pb.d.ts +2 -0
  25. package/dist/custom-objects/generated/proto/vendor/publicapi/extension_interface.pb.d.ts.map +1 -1
  26. package/dist/custom-objects/generated/proto/vendor/publicapi/feature_enum.pb.d.ts +14 -2
  27. package/dist/custom-objects/generated/proto/vendor/publicapi/feature_enum.pb.d.ts.map +1 -1
  28. package/dist/custom-objects/generated/proto/vendor/publicapi/http_error_status.pb.d.ts +6 -0
  29. package/dist/custom-objects/generated/proto/vendor/publicapi/http_error_status.pb.d.ts.map +1 -1
  30. package/dist/custom-objects/generated/proto/vendor/publicapi/rollout_configs.pb.d.ts +74 -0
  31. package/dist/custom-objects/generated/proto/vendor/publicapi/rollout_configs.pb.d.ts.map +1 -1
  32. package/dist/custom-objects/generated/proto/vendor/publicapi/v2ext.pb.d.ts +10 -3
  33. package/dist/custom-objects/generated/proto/vendor/publicapi/v2ext.pb.d.ts.map +1 -1
  34. package/dist/custom-objects/generated/proto/vendor/vext/privacy_unified_annotations.pb.d.ts +1 -0
  35. package/dist/custom-objects/generated/proto/vendor/vext/privacy_unified_annotations.pb.d.ts.map +1 -1
  36. package/dist/index.cjs +192 -52
  37. package/dist/index.js +174 -34
  38. package/dist/templates/extensions/billing.invoice_collection_options.d.ts +6 -0
  39. package/dist/templates/extensions/billing.invoice_collection_options.d.ts.map +1 -0
  40. package/dist/templates/index.cjs +174 -34
  41. package/dist/templates/index.js +172 -32
  42. package/dist/templates/root/index.d.ts.map +1 -1
  43. package/dist/tsconfig.build.tsbuildinfo +1 -1
  44. package/dist/workspace/index.cjs +183 -43
  45. package/dist/workspace/index.d.ts.map +1 -1
  46. package/dist/workspace/index.js +174 -34
  47. package/dist/workspace-versions.d.ts +26 -0
  48. package/dist/workspace-versions.d.ts.map +1 -0
  49. package/package.json +4 -4
  50. package/templates/extensions/billing.invoice_collection_options/index.test.ts +15 -0
  51. package/templates/extensions/billing.invoice_collection_options/index.ts +16 -0
  52. package/templates/root/custom-objects/eslint.config.mts +89 -0
  53. package/templates/root/custom-objects/package.json.mustache +2 -0
  54. package/templates/root/custom-objects/tsconfig.json +1 -0
  55. package/templates/root/custom-objects/vitest.config.mts +7 -0
  56. package/templates/root/package.json.mustache +1 -1
  57. package/templates/root/tools/test.mts +4 -2
  58. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts +0 -6
  59. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts.map +0 -1
  60. package/templates/extensions/billing.invoice_collection_setting/index.test.ts +0 -15
  61. package/templates/extensions/billing.invoice_collection_setting/index.ts +0 -16
@@ -1237,35 +1237,35 @@ export default class MyBalanceApp implements Billing.CustomerBalanceApplication<
1237
1237
  `
1238
1238
  },
1239
1239
  {
1240
- path: "extensions/billing.invoice_collection_setting/index.test.ts",
1240
+ path: "extensions/billing.invoice_collection_options/index.test.ts",
1241
1241
  content: `import { beforeEach, describe, it, expect } from 'vitest';
1242
1242
 
1243
- import MyInvoiceCollectionSetting from './index.js';
1243
+ import MyInvoiceCollectionOptions from './index.js';
1244
1244
 
1245
- describe('MyInvoiceCollectionSetting', () => {
1246
- let instance: MyInvoiceCollectionSetting;
1245
+ describe('MyInvoiceCollectionOptions', () => {
1246
+ let instance: MyInvoiceCollectionOptions;
1247
1247
 
1248
1248
  beforeEach(() => {
1249
- instance = new MyInvoiceCollectionSetting();
1249
+ instance = new MyInvoiceCollectionOptions();
1250
1250
  });
1251
1251
 
1252
1252
  it('should be constructable', () => {
1253
- expect(instance).toBeInstanceOf(MyInvoiceCollectionSetting);
1253
+ expect(instance).toBeInstanceOf(MyInvoiceCollectionOptions);
1254
1254
  });
1255
1255
  });
1256
1256
  `
1257
1257
  },
1258
1258
  {
1259
- path: "extensions/billing.invoice_collection_setting/index.ts",
1259
+ path: "extensions/billing.invoice_collection_options/index.ts",
1260
1260
  content: `import type { Billing, Context } from '@stripe/extensibility-sdk';
1261
1261
 
1262
1262
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
1263
- interface MyInvoiceCollectionSettingConfig {}
1263
+ interface MyInvoiceCollectionOptionsConfig {}
1264
1264
 
1265
- export default class MyInvoiceCollectionSetting implements Billing.InvoiceCollectionSetting<MyInvoiceCollectionSettingConfig> {
1266
- collectionOverride(
1267
- _request: Billing.InvoiceCollectionSetting.InvoiceCollectionRequest,
1268
- _config: MyInvoiceCollectionSettingConfig,
1265
+ export default class MyInvoiceCollectionOptions implements Billing.InvoiceCollectionOptions<MyInvoiceCollectionOptionsConfig> {
1266
+ overrideOptions(
1267
+ _request: Billing.InvoiceCollectionOptions.InvoiceCollectionOptionsInput,
1268
+ _config: MyInvoiceCollectionOptionsConfig,
1269
1269
  _context: Context
1270
1270
  ) {
1271
1271
  // TODO: implement your collection setting logic here
@@ -1737,6 +1737,99 @@ install-deps.log
1737
1737
 
1738
1738
  # generated schemas
1739
1739
  generated
1740
+ `
1741
+ },
1742
+ {
1743
+ path: "root/custom-objects/eslint.config.mts",
1744
+ content: `import eslint from '@eslint/js';
1745
+ import { defineConfig } from 'eslint/config';
1746
+ import tseslint from 'typescript-eslint';
1747
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
1748
+
1749
+ import globals from 'globals';
1750
+
1751
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
1752
+ import customObjectsConfig from '@stripe/extensibility-eslint-plugin/custom-objects';
1753
+
1754
+ export default defineConfig([
1755
+ eslint.configs.recommended,
1756
+ ...tseslint.configs.recommended,
1757
+ ...stripeAppsConfig,
1758
+ ...customObjectsConfig,
1759
+
1760
+ // Global ignores
1761
+ {
1762
+ ignores: ['dist', 'generated', 'node_modules'],
1763
+ },
1764
+
1765
+ // TypeScript source files (with type-checking)
1766
+ {
1767
+ name: 'sources',
1768
+ files: ['src/**/*.ts'],
1769
+ ignores: ['**/*.test.ts', '**/__tests__/**'],
1770
+ languageOptions: {
1771
+ globals: {
1772
+ ...globals.node,
1773
+ },
1774
+ parserOptions: {
1775
+ projectService: true,
1776
+ tsconfigRootDir: import.meta.dirname,
1777
+ },
1778
+ },
1779
+ },
1780
+
1781
+ // Test files
1782
+ {
1783
+ name: 'tests',
1784
+ files: ['src/**/*.test.ts', 'src/**/__tests__/**/*.ts'],
1785
+ languageOptions: {
1786
+ globals: {
1787
+ ...globals.node,
1788
+ },
1789
+ parserOptions: {
1790
+ projectService: true,
1791
+ tsconfigRootDir: import.meta.dirname,
1792
+ },
1793
+ },
1794
+ },
1795
+
1796
+ // Config files
1797
+ {
1798
+ name: 'ts-configs',
1799
+ files: ['*.config.m?ts', 'eslint.config.mts'],
1800
+ languageOptions: {
1801
+ globals: {
1802
+ ...globals.node,
1803
+ },
1804
+ parserOptions: {
1805
+ projectService: false,
1806
+ },
1807
+ },
1808
+ rules: {
1809
+ '@typescript-eslint/no-unused-vars': 'off',
1810
+ },
1811
+ },
1812
+
1813
+ // JavaScript/MJS files (scripts, configs) \u2014 no TS project, so only
1814
+ // disable the TS-parser-specific rule that doesn't apply without it.
1815
+ {
1816
+ name: 'js-configs',
1817
+ files: ['**/*.js', '**/*.mjs'],
1818
+ languageOptions: {
1819
+ globals: {
1820
+ ...globals.node,
1821
+ },
1822
+ parserOptions: {
1823
+ projectService: false,
1824
+ },
1825
+ },
1826
+ rules: {
1827
+ '@typescript-eslint/no-require-imports': 'off',
1828
+ },
1829
+ },
1830
+
1831
+ eslintConfigPrettier,
1832
+ ]);
1740
1833
  `
1741
1834
  },
1742
1835
  {
@@ -1749,7 +1842,9 @@ generated
1749
1842
  "private": true,
1750
1843
  "scripts": {
1751
1844
  "build": "test -d src && custom-objects-build --input src --output dist || true",
1845
+ "lint": "pnpm lint:types && pnpm lint:eslint",
1752
1846
  "lint:types": "test ! -d src || tsc --noEmit",
1847
+ "lint:eslint": "eslint .",
1753
1848
  "test": "vitest run"
1754
1849
  },
1755
1850
  "dependencies": {
@@ -1772,8 +1867,20 @@ generated
1772
1867
  "moduleResolution": "bundler",
1773
1868
  "types": ["vitest/globals"]
1774
1869
  },
1870
+ "include": ["src/**/*.ts"],
1775
1871
  "exclude": ["dist"]
1776
1872
  }
1873
+ `
1874
+ },
1875
+ {
1876
+ path: "root/custom-objects/vitest.config.mts",
1877
+ content: `import { defineConfig } from 'vitest/config';
1878
+
1879
+ export default defineConfig({
1880
+ test: {
1881
+ globals: true,
1882
+ },
1883
+ });
1777
1884
  `
1778
1885
  },
1779
1886
  {
@@ -1891,7 +1998,7 @@ export default defineConfig([
1891
1998
  "build": "pnpm -r --if-present build",
1892
1999
  "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
1893
2000
  "lint:types": "pnpm -r --if-present lint:types",
1894
- "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint",
2001
+ "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint && pnpm -r --filter './custom-objects' --if-present lint:eslint",
1895
2002
  "lint:format": "prettier --check .",
1896
2003
  "fix:lint": "eslint --fix . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present fix:lint",
1897
2004
  "fix:format": "prettier --write .",
@@ -1937,7 +2044,7 @@ declarations:
1937
2044
  content: `#!/usr/bin/env tsx
1938
2045
  /**
1939
2046
  * Runs tests across the workspace:
1940
- * - vitest for script extensions and custom objects (extensions/*)
2047
+ * - vitest for script extensions (extensions/*) and custom objects (custom-objects/)
1941
2048
  * - jest for UI extensions (ui/)
1942
2049
  */
1943
2050
  import { existsSync, readdirSync } from 'node:fs';
@@ -1947,6 +2054,8 @@ const hasExtensions =
1947
2054
  existsSync('extensions') &&
1948
2055
  readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
1949
2056
 
2057
+ const hasCustomObjects = existsSync('custom-objects/package.json');
2058
+
1950
2059
  const hasUI = existsSync('ui/package.json');
1951
2060
 
1952
2061
  let exitCode = 0;
@@ -1959,7 +2068,7 @@ function run(cmd: string): void {
1959
2068
  }
1960
2069
  }
1961
2070
 
1962
- if (hasExtensions) {
2071
+ if (hasExtensions || hasCustomObjects) {
1963
2072
  run('vitest run');
1964
2073
  }
1965
2074
 
@@ -2727,8 +2836,30 @@ var _ExtensionTemplateManager = class extends _TemplateManager {
2727
2836
  }
2728
2837
  };
2729
2838
 
2839
+ // src/workspace-versions.json
2840
+ var workspace_versions_default = {
2841
+ "@stripe/extensibility-custom-objects": "0.8.0",
2842
+ "@stripe/extensibility-custom-objects-tools": "0.42.1",
2843
+ "@stripe/extensibility-dev-tools": "0.25.1",
2844
+ "@stripe/extensibility-eslint-plugin": "0.17.1",
2845
+ "@stripe/extensibility-language-server": "0.3.4",
2846
+ "@stripe/extensibility-sdk": "0.27.1",
2847
+ "@stripe/extensibility-test-helpers": "0.2.7"
2848
+ };
2849
+
2850
+ // src/workspace-versions.ts
2851
+ var _workspaceVersions = workspace_versions_default;
2852
+ function _workspaceVersion(packageName) {
2853
+ const v = _workspaceVersions[packageName];
2854
+ if (v === void 0) {
2855
+ throw new Error(
2856
+ `Unknown workspace package "${packageName}". Check workspace-versions.json or run: tsx scripts/src/sync-workspace-versions.ts`
2857
+ );
2858
+ }
2859
+ return v;
2860
+ }
2861
+
2730
2862
  // src/templates/extensions/base.ts
2731
- import { _workspaceVersion } from "@stripe/extensibility-tool-utils";
2732
2863
  var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
2733
2864
  var LANGUAGE_SERVER_PACKAGE_NAME = "@stripe/extensibility-language-server";
2734
2865
  var LANGUAGE_SERVER_PACKAGE_VERSION = `^${_workspaceVersion(LANGUAGE_SERVER_PACKAGE_NAME)}`;
@@ -3033,14 +3164,14 @@ var billing_bill_discount_calculation_default = {
3033
3164
  [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
3034
3165
  };
3035
3166
 
3036
- // src/templates/extensions/billing.invoice_collection_setting.ts
3037
- var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
3038
- var invoiceCollectionSettingTemplate = {
3167
+ // src/templates/extensions/billing.invoice_collection_options.ts
3168
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_options";
3169
+ var invoiceCollectionOptionsTemplate = {
3039
3170
  hidden: true,
3040
3171
  methods: {
3041
- collection_override: { implementation_types: ["script"] }
3172
+ override_options: { implementation_types: ["script"] }
3042
3173
  },
3043
- description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
3174
+ description: "Use Stripe Scripts to create custom invoice collection options that controls how your integration handles invoices generated from subscriptions.",
3044
3175
  generate: (params, context) => {
3045
3176
  const { id } = params;
3046
3177
  const { fs: fs2 } = context;
@@ -3068,15 +3199,15 @@ var invoiceCollectionSettingTemplate = {
3068
3199
  ...base.files
3069
3200
  ],
3070
3201
  methods: {
3071
- collection_override: {
3202
+ override_options: {
3072
3203
  implementation_type: "script"
3073
3204
  }
3074
3205
  }
3075
3206
  };
3076
3207
  }
3077
3208
  };
3078
- var billing_invoice_collection_setting_default = {
3079
- [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
3209
+ var billing_invoice_collection_options_default = {
3210
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionOptionsTemplate
3080
3211
  };
3081
3212
 
3082
3213
  // src/templates/extensions/billing.prorations.ts
@@ -3184,7 +3315,7 @@ var DEFAULT_TEMPLATES = {
3184
3315
  ...extend_workflows_custom_action_default,
3185
3316
  ...billing_customer_balance_application_default,
3186
3317
  ...billing_bill_discount_calculation_default,
3187
- ...billing_invoice_collection_setting_default,
3318
+ ...billing_invoice_collection_options_default,
3188
3319
  ...billing_prorations_default,
3189
3320
  ...billing_recurring_billing_item_handling_default
3190
3321
  };
@@ -3197,9 +3328,8 @@ var _templateManager = new _ExtensionTemplateManager(
3197
3328
  );
3198
3329
 
3199
3330
  // src/templates/root/index.ts
3200
- import { _workspaceVersion as _workspaceVersion2 } from "@stripe/extensibility-tool-utils";
3201
3331
  var EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME = "@stripe/extensibility-eslint-plugin";
3202
- var EXTENSIBILITY_ESLINT_PLUGIN_VERSION = `^${_workspaceVersion2(EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME)}`;
3332
+ var EXTENSIBILITY_ESLINT_PLUGIN_VERSION = `^${_workspaceVersion(EXTENSIBILITY_ESLINT_PLUGIN_PACKAGE_NAME)}`;
3203
3333
  var _rootWorkspaceTemplate = {
3204
3334
  generate: (params, context) => {
3205
3335
  const { fs: fs2 } = context;
@@ -3254,14 +3384,14 @@ var _rootWorkspaceTemplate = {
3254
3384
  path: "custom-objects/package.json",
3255
3385
  content: fs2.mustache(
3256
3386
  {
3257
- customObjectsVersion: _workspaceVersion2(
3387
+ customObjectsVersion: _workspaceVersion(
3258
3388
  "@stripe/extensibility-custom-objects"
3259
3389
  ),
3260
- sdkVersion: _workspaceVersion2("@stripe/extensibility-sdk"),
3261
- customObjectsToolsVersion: _workspaceVersion2(
3390
+ sdkVersion: _workspaceVersion("@stripe/extensibility-sdk"),
3391
+ customObjectsToolsVersion: _workspaceVersion(
3262
3392
  "@stripe/extensibility-custom-objects-tools"
3263
3393
  ),
3264
- testHelpersVersion: _workspaceVersion2("@stripe/extensibility-test-helpers")
3394
+ testHelpersVersion: _workspaceVersion("@stripe/extensibility-test-helpers")
3265
3395
  },
3266
3396
  "custom-objects",
3267
3397
  "package.json.mustache"
@@ -3273,6 +3403,16 @@ var _rootWorkspaceTemplate = {
3273
3403
  content: fs2.textFile("custom-objects/tsconfig.json"),
3274
3404
  precious: true
3275
3405
  },
3406
+ {
3407
+ path: "custom-objects/eslint.config.mts",
3408
+ content: fs2.textFile("custom-objects/eslint.config.mts"),
3409
+ precious: true
3410
+ },
3411
+ {
3412
+ path: "custom-objects/vitest.config.mts",
3413
+ content: fs2.textFile("custom-objects/vitest.config.mts"),
3414
+ precious: true
3415
+ },
3276
3416
  {
3277
3417
  path: "ui/package.json",
3278
3418
  content: fs2.textFile("ui/package.json"),
@@ -3299,7 +3439,7 @@ var _rootWorkspaceTemplate = {
3299
3439
  _devNpmDep("@types/node", "^20.19.0"),
3300
3440
  _devNpmDep(
3301
3441
  "@stripe/extensibility-dev-tools",
3302
- `^${_workspaceVersion2("@stripe/extensibility-dev-tools")}`
3442
+ `^${_workspaceVersion("@stripe/extensibility-dev-tools")}`
3303
3443
  ),
3304
3444
  _devNpmDep("concurrently", "^9.2.1"),
3305
3445
  _devNpmDep("eslint", "^9.0.0"),
@@ -3497,9 +3637,9 @@ function resolveMode(options, projectRoot, packageDir) {
3497
3637
  workspaceDir: () => packageDir ?? path4.join(projectRoot, "custom-objects"),
3498
3638
  generate: async (svc) => {
3499
3639
  const customObjectsWorkspaceDir = packageDir ?? path4.join(projectRoot, "custom-objects");
3500
- const workspaceExists = existsSync2(path4.join(customObjectsWorkspaceDir, "package.json")) && existsSync2(path4.join(customObjectsWorkspaceDir, "tsconfig.json"));
3640
+ const workspaceScaffoldingExists = existsSync2(path4.join(customObjectsWorkspaceDir, "package.json")) && existsSync2(path4.join(customObjectsWorkspaceDir, "tsconfig.json")) && existsSync2(path4.join(customObjectsWorkspaceDir, "eslint.config.mts"));
3501
3641
  const objectResult = await svc.generateCustomObject({ name: objectName });
3502
- if (workspaceExists) {
3642
+ if (workspaceScaffoldingExists) {
3503
3643
  return objectResult;
3504
3644
  }
3505
3645
  const workspaceResult = await svc.generateCustomObjectsWorkspace({});
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  // src/bin/template-info.ts
27
27
  var import_yargs = __toESM(require("yargs"), 1);
28
28
  var import_helpers = require("yargs/helpers");
29
- var import_extensibility_tool_utils5 = require("@stripe/extensibility-tool-utils");
29
+ var import_extensibility_tool_utils4 = require("@stripe/extensibility-tool-utils");
30
30
 
31
31
  // src/templates/template-manager.ts
32
32
  var import_extensibility_tool_utils = require("@stripe/extensibility-tool-utils");
@@ -136,35 +136,35 @@ export default class MyBalanceApp implements Billing.CustomerBalanceApplication<
136
136
  `
137
137
  },
138
138
  {
139
- path: "extensions/billing.invoice_collection_setting/index.test.ts",
139
+ path: "extensions/billing.invoice_collection_options/index.test.ts",
140
140
  content: `import { beforeEach, describe, it, expect } from 'vitest';
141
141
 
142
- import MyInvoiceCollectionSetting from './index.js';
142
+ import MyInvoiceCollectionOptions from './index.js';
143
143
 
144
- describe('MyInvoiceCollectionSetting', () => {
145
- let instance: MyInvoiceCollectionSetting;
144
+ describe('MyInvoiceCollectionOptions', () => {
145
+ let instance: MyInvoiceCollectionOptions;
146
146
 
147
147
  beforeEach(() => {
148
- instance = new MyInvoiceCollectionSetting();
148
+ instance = new MyInvoiceCollectionOptions();
149
149
  });
150
150
 
151
151
  it('should be constructable', () => {
152
- expect(instance).toBeInstanceOf(MyInvoiceCollectionSetting);
152
+ expect(instance).toBeInstanceOf(MyInvoiceCollectionOptions);
153
153
  });
154
154
  });
155
155
  `
156
156
  },
157
157
  {
158
- path: "extensions/billing.invoice_collection_setting/index.ts",
158
+ path: "extensions/billing.invoice_collection_options/index.ts",
159
159
  content: `import type { Billing, Context } from '@stripe/extensibility-sdk';
160
160
 
161
161
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
162
- interface MyInvoiceCollectionSettingConfig {}
162
+ interface MyInvoiceCollectionOptionsConfig {}
163
163
 
164
- export default class MyInvoiceCollectionSetting implements Billing.InvoiceCollectionSetting<MyInvoiceCollectionSettingConfig> {
165
- collectionOverride(
166
- _request: Billing.InvoiceCollectionSetting.InvoiceCollectionRequest,
167
- _config: MyInvoiceCollectionSettingConfig,
164
+ export default class MyInvoiceCollectionOptions implements Billing.InvoiceCollectionOptions<MyInvoiceCollectionOptionsConfig> {
165
+ overrideOptions(
166
+ _request: Billing.InvoiceCollectionOptions.InvoiceCollectionOptionsInput,
167
+ _config: MyInvoiceCollectionOptionsConfig,
168
168
  _context: Context
169
169
  ) {
170
170
  // TODO: implement your collection setting logic here
@@ -636,6 +636,99 @@ install-deps.log
636
636
 
637
637
  # generated schemas
638
638
  generated
639
+ `
640
+ },
641
+ {
642
+ path: "root/custom-objects/eslint.config.mts",
643
+ content: `import eslint from '@eslint/js';
644
+ import { defineConfig } from 'eslint/config';
645
+ import tseslint from 'typescript-eslint';
646
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
647
+
648
+ import globals from 'globals';
649
+
650
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
651
+ import customObjectsConfig from '@stripe/extensibility-eslint-plugin/custom-objects';
652
+
653
+ export default defineConfig([
654
+ eslint.configs.recommended,
655
+ ...tseslint.configs.recommended,
656
+ ...stripeAppsConfig,
657
+ ...customObjectsConfig,
658
+
659
+ // Global ignores
660
+ {
661
+ ignores: ['dist', 'generated', 'node_modules'],
662
+ },
663
+
664
+ // TypeScript source files (with type-checking)
665
+ {
666
+ name: 'sources',
667
+ files: ['src/**/*.ts'],
668
+ ignores: ['**/*.test.ts', '**/__tests__/**'],
669
+ languageOptions: {
670
+ globals: {
671
+ ...globals.node,
672
+ },
673
+ parserOptions: {
674
+ projectService: true,
675
+ tsconfigRootDir: import.meta.dirname,
676
+ },
677
+ },
678
+ },
679
+
680
+ // Test files
681
+ {
682
+ name: 'tests',
683
+ files: ['src/**/*.test.ts', 'src/**/__tests__/**/*.ts'],
684
+ languageOptions: {
685
+ globals: {
686
+ ...globals.node,
687
+ },
688
+ parserOptions: {
689
+ projectService: true,
690
+ tsconfigRootDir: import.meta.dirname,
691
+ },
692
+ },
693
+ },
694
+
695
+ // Config files
696
+ {
697
+ name: 'ts-configs',
698
+ files: ['*.config.m?ts', 'eslint.config.mts'],
699
+ languageOptions: {
700
+ globals: {
701
+ ...globals.node,
702
+ },
703
+ parserOptions: {
704
+ projectService: false,
705
+ },
706
+ },
707
+ rules: {
708
+ '@typescript-eslint/no-unused-vars': 'off',
709
+ },
710
+ },
711
+
712
+ // JavaScript/MJS files (scripts, configs) \u2014 no TS project, so only
713
+ // disable the TS-parser-specific rule that doesn't apply without it.
714
+ {
715
+ name: 'js-configs',
716
+ files: ['**/*.js', '**/*.mjs'],
717
+ languageOptions: {
718
+ globals: {
719
+ ...globals.node,
720
+ },
721
+ parserOptions: {
722
+ projectService: false,
723
+ },
724
+ },
725
+ rules: {
726
+ '@typescript-eslint/no-require-imports': 'off',
727
+ },
728
+ },
729
+
730
+ eslintConfigPrettier,
731
+ ]);
639
732
  `
640
733
  },
641
734
  {
@@ -648,7 +741,9 @@ generated
648
741
  "private": true,
649
742
  "scripts": {
650
743
  "build": "test -d src && custom-objects-build --input src --output dist || true",
744
+ "lint": "pnpm lint:types && pnpm lint:eslint",
651
745
  "lint:types": "test ! -d src || tsc --noEmit",
746
+ "lint:eslint": "eslint .",
652
747
  "test": "vitest run"
653
748
  },
654
749
  "dependencies": {
@@ -671,8 +766,20 @@ generated
671
766
  "moduleResolution": "bundler",
672
767
  "types": ["vitest/globals"]
673
768
  },
769
+ "include": ["src/**/*.ts"],
674
770
  "exclude": ["dist"]
675
771
  }
772
+ `
773
+ },
774
+ {
775
+ path: "root/custom-objects/vitest.config.mts",
776
+ content: `import { defineConfig } from 'vitest/config';
777
+
778
+ export default defineConfig({
779
+ test: {
780
+ globals: true,
781
+ },
782
+ });
676
783
  `
677
784
  },
678
785
  {
@@ -790,7 +897,7 @@ export default defineConfig([
790
897
  "build": "pnpm -r --if-present build",
791
898
  "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
792
899
  "lint:types": "pnpm -r --if-present lint:types",
793
- "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint",
900
+ "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint && pnpm -r --filter './custom-objects' --if-present lint:eslint",
794
901
  "lint:format": "prettier --check .",
795
902
  "fix:lint": "eslint --fix . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present fix:lint",
796
903
  "fix:format": "prettier --write .",
@@ -836,7 +943,7 @@ declarations:
836
943
  content: `#!/usr/bin/env tsx
837
944
  /**
838
945
  * Runs tests across the workspace:
839
- * - vitest for script extensions and custom objects (extensions/*)
946
+ * - vitest for script extensions (extensions/*) and custom objects (custom-objects/)
840
947
  * - jest for UI extensions (ui/)
841
948
  */
842
949
  import { existsSync, readdirSync } from 'node:fs';
@@ -846,6 +953,8 @@ const hasExtensions =
846
953
  existsSync('extensions') &&
847
954
  readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
848
955
 
956
+ const hasCustomObjects = existsSync('custom-objects/package.json');
957
+
849
958
  const hasUI = existsSync('ui/package.json');
850
959
 
851
960
  let exitCode = 0;
@@ -858,7 +967,7 @@ function run(cmd: string): void {
858
967
  }
859
968
  }
860
969
 
861
- if (hasExtensions) {
970
+ if (hasExtensions || hasCustomObjects) {
862
971
  run('vitest run');
863
972
  }
864
973
 
@@ -1010,11 +1119,33 @@ function _devNpmDep(name, version) {
1010
1119
  return { type: "dev-npm", name, version };
1011
1120
  }
1012
1121
 
1122
+ // src/workspace-versions.json
1123
+ var workspace_versions_default = {
1124
+ "@stripe/extensibility-custom-objects": "0.8.0",
1125
+ "@stripe/extensibility-custom-objects-tools": "0.42.1",
1126
+ "@stripe/extensibility-dev-tools": "0.25.1",
1127
+ "@stripe/extensibility-eslint-plugin": "0.17.1",
1128
+ "@stripe/extensibility-language-server": "0.3.4",
1129
+ "@stripe/extensibility-sdk": "0.27.1",
1130
+ "@stripe/extensibility-test-helpers": "0.2.7"
1131
+ };
1132
+
1133
+ // src/workspace-versions.ts
1134
+ var _workspaceVersions = workspace_versions_default;
1135
+ function _workspaceVersion(packageName) {
1136
+ const v = _workspaceVersions[packageName];
1137
+ if (v === void 0) {
1138
+ throw new Error(
1139
+ `Unknown workspace package "${packageName}". Check workspace-versions.json or run: tsx scripts/src/sync-workspace-versions.ts`
1140
+ );
1141
+ }
1142
+ return v;
1143
+ }
1144
+
1013
1145
  // src/templates/extensions/base.ts
1014
- var import_extensibility_tool_utils4 = require("@stripe/extensibility-tool-utils");
1015
1146
  var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
1016
1147
  var LANGUAGE_SERVER_PACKAGE_NAME = "@stripe/extensibility-language-server";
1017
- var LANGUAGE_SERVER_PACKAGE_VERSION = `^${(0, import_extensibility_tool_utils4._workspaceVersion)(LANGUAGE_SERVER_PACKAGE_NAME)}`;
1148
+ var LANGUAGE_SERVER_PACKAGE_VERSION = `^${_workspaceVersion(LANGUAGE_SERVER_PACKAGE_NAME)}`;
1018
1149
  function _createExtensionEslintConfigFile(params, context) {
1019
1150
  const { id, extensionInterfaceId } = params;
1020
1151
  const { fs: fs2 } = context;
@@ -1057,7 +1188,7 @@ function _createBaseOutput(params, context) {
1057
1188
  dependencies: {
1058
1189
  // Exact pin (no caret) — the SDK is tightly coupled to dev-tools and
1059
1190
  // must match the version that generated the extension scaffolding.
1060
- runtime: [_npmDep(SDK_PACKAGE_NAME, (0, import_extensibility_tool_utils4._workspaceVersion)(SDK_PACKAGE_NAME))],
1191
+ runtime: [_npmDep(SDK_PACKAGE_NAME, _workspaceVersion(SDK_PACKAGE_NAME))],
1061
1192
  dev: [_devNpmDep(LANGUAGE_SERVER_PACKAGE_NAME, LANGUAGE_SERVER_PACKAGE_VERSION)]
1062
1193
  },
1063
1194
  postGenerationHooks: [
@@ -1316,14 +1447,14 @@ var billing_bill_discount_calculation_default = {
1316
1447
  [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
1317
1448
  };
1318
1449
 
1319
- // src/templates/extensions/billing.invoice_collection_setting.ts
1320
- var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
1321
- var invoiceCollectionSettingTemplate = {
1450
+ // src/templates/extensions/billing.invoice_collection_options.ts
1451
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_options";
1452
+ var invoiceCollectionOptionsTemplate = {
1322
1453
  hidden: true,
1323
1454
  methods: {
1324
- collection_override: { implementation_types: ["script"] }
1455
+ override_options: { implementation_types: ["script"] }
1325
1456
  },
1326
- description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
1457
+ description: "Use Stripe Scripts to create custom invoice collection options that controls how your integration handles invoices generated from subscriptions.",
1327
1458
  generate: (params, context) => {
1328
1459
  const { id } = params;
1329
1460
  const { fs: fs2 } = context;
@@ -1351,15 +1482,15 @@ var invoiceCollectionSettingTemplate = {
1351
1482
  ...base.files
1352
1483
  ],
1353
1484
  methods: {
1354
- collection_override: {
1485
+ override_options: {
1355
1486
  implementation_type: "script"
1356
1487
  }
1357
1488
  }
1358
1489
  };
1359
1490
  }
1360
1491
  };
1361
- var billing_invoice_collection_setting_default = {
1362
- [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
1492
+ var billing_invoice_collection_options_default = {
1493
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionOptionsTemplate
1363
1494
  };
1364
1495
 
1365
1496
  // src/templates/extensions/billing.prorations.ts
@@ -1467,7 +1598,7 @@ var DEFAULT_TEMPLATES = {
1467
1598
  ...extend_workflows_custom_action_default,
1468
1599
  ...billing_customer_balance_application_default,
1469
1600
  ...billing_bill_discount_calculation_default,
1470
- ...billing_invoice_collection_setting_default,
1601
+ ...billing_invoice_collection_options_default,
1471
1602
  ...billing_prorations_default,
1472
1603
  ...billing_recurring_billing_item_handling_default
1473
1604
  };
@@ -1480,7 +1611,7 @@ var _templateManager = new _ExtensionTemplateManager(
1480
1611
  );
1481
1612
 
1482
1613
  // src/bin/template-info.ts
1483
- var logger = (0, import_extensibility_tool_utils5._createLogger)({ name: "template-info" });
1614
+ var logger = (0, import_extensibility_tool_utils4._createLogger)({ name: "template-info" });
1484
1615
  async function main() {
1485
1616
  await (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).usage("Show available extension templates").help().version(false).command(
1486
1617
  "$0",
@@ -1492,7 +1623,7 @@ async function main() {
1492
1623
  (args) => {
1493
1624
  const templates = _templateManager.getTemplateInfo().filter((t) => !t.hidden);
1494
1625
  if (args.outputPath) {
1495
- (0, import_extensibility_tool_utils5._writeJsonOutput)(args.outputPath, templates);
1626
+ (0, import_extensibility_tool_utils4._writeJsonOutput)(args.outputPath, templates);
1496
1627
  } else {
1497
1628
  for (const t of templates) {
1498
1629
  const suffix = t.deprecated ? " (deprecated)" : "";