@stripe/extensibility-dev-tools 0.24.3 → 1.0.2

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 (62) hide show
  1. package/dist/bin/build-custom-object-definitions.cjs +169 -34
  2. package/dist/bin/build-custom-object-definitions.js +160 -25
  3. package/dist/bin/create-upload-image.cjs +168 -33
  4. package/dist/bin/create-upload-image.js +160 -25
  5. package/dist/bin/dev-tools-rpc.cjs +203 -59
  6. package/dist/bin/dev-tools-rpc.js +178 -34
  7. package/dist/bin/gen-workspace.cjs +191 -47
  8. package/dist/bin/gen-workspace.js +178 -34
  9. package/dist/bin/template-info.cjs +165 -30
  10. package/dist/bin/template-info.js +160 -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 +196 -52
  37. package/dist/index.js +178 -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 +178 -34
  41. package/dist/templates/index.js +176 -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 +187 -43
  45. package/dist/workspace/index.d.ts.map +1 -1
  46. package/dist/workspace/index.js +178 -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/pnpm-workspace.yaml +4 -0
  58. package/templates/root/tools/test.mts +4 -2
  59. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts +0 -6
  60. package/dist/templates/extensions/billing.invoice_collection_setting.d.ts.map +0 -1
  61. package/templates/extensions/billing.invoice_collection_setting/index.test.ts +0 -15
  62. package/templates/extensions/billing.invoice_collection_setting/index.ts +0 -16
@@ -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 .",
@@ -819,6 +926,10 @@ export default defineConfig([
819
926
 
820
927
  overrides:
821
928
  vite: ^6.0.0
929
+
930
+ allowBuilds:
931
+ core-js-pure: false
932
+ esbuild: false
822
933
  `
823
934
  },
824
935
  {
@@ -836,7 +947,7 @@ declarations:
836
947
  content: `#!/usr/bin/env tsx
837
948
  /**
838
949
  * Runs tests across the workspace:
839
- * - vitest for script extensions and custom objects (extensions/*)
950
+ * - vitest for script extensions (extensions/*) and custom objects (custom-objects/)
840
951
  * - jest for UI extensions (ui/)
841
952
  */
842
953
  import { existsSync, readdirSync } from 'node:fs';
@@ -846,6 +957,8 @@ const hasExtensions =
846
957
  existsSync('extensions') &&
847
958
  readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
848
959
 
960
+ const hasCustomObjects = existsSync('custom-objects/package.json');
961
+
849
962
  const hasUI = existsSync('ui/package.json');
850
963
 
851
964
  let exitCode = 0;
@@ -858,7 +971,7 @@ function run(cmd: string): void {
858
971
  }
859
972
  }
860
973
 
861
- if (hasExtensions) {
974
+ if (hasExtensions || hasCustomObjects) {
862
975
  run('vitest run');
863
976
  }
864
977
 
@@ -1010,11 +1123,33 @@ function _devNpmDep(name, version) {
1010
1123
  return { type: "dev-npm", name, version };
1011
1124
  }
1012
1125
 
1126
+ // src/workspace-versions.json
1127
+ var workspace_versions_default = {
1128
+ "@stripe/extensibility-custom-objects": "1.0.0",
1129
+ "@stripe/extensibility-custom-objects-tools": "4.0.1",
1130
+ "@stripe/extensibility-dev-tools": "1.0.2",
1131
+ "@stripe/extensibility-eslint-plugin": "1.0.0",
1132
+ "@stripe/extensibility-language-server": "1.0.0",
1133
+ "@stripe/extensibility-sdk": "1.0.0",
1134
+ "@stripe/extensibility-test-helpers": "1.0.0"
1135
+ };
1136
+
1137
+ // src/workspace-versions.ts
1138
+ var _workspaceVersions = workspace_versions_default;
1139
+ function _workspaceVersion(packageName) {
1140
+ const v = _workspaceVersions[packageName];
1141
+ if (v === void 0) {
1142
+ throw new Error(
1143
+ `Unknown workspace package "${packageName}". Check workspace-versions.json or run: tsx scripts/src/sync-workspace-versions.ts`
1144
+ );
1145
+ }
1146
+ return v;
1147
+ }
1148
+
1013
1149
  // src/templates/extensions/base.ts
1014
- var import_extensibility_tool_utils4 = require("@stripe/extensibility-tool-utils");
1015
1150
  var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
1016
1151
  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)}`;
1152
+ var LANGUAGE_SERVER_PACKAGE_VERSION = `^${_workspaceVersion(LANGUAGE_SERVER_PACKAGE_NAME)}`;
1018
1153
  function _createExtensionEslintConfigFile(params, context) {
1019
1154
  const { id, extensionInterfaceId } = params;
1020
1155
  const { fs: fs2 } = context;
@@ -1057,7 +1192,7 @@ function _createBaseOutput(params, context) {
1057
1192
  dependencies: {
1058
1193
  // Exact pin (no caret) — the SDK is tightly coupled to dev-tools and
1059
1194
  // must match the version that generated the extension scaffolding.
1060
- runtime: [_npmDep(SDK_PACKAGE_NAME, (0, import_extensibility_tool_utils4._workspaceVersion)(SDK_PACKAGE_NAME))],
1195
+ runtime: [_npmDep(SDK_PACKAGE_NAME, _workspaceVersion(SDK_PACKAGE_NAME))],
1061
1196
  dev: [_devNpmDep(LANGUAGE_SERVER_PACKAGE_NAME, LANGUAGE_SERVER_PACKAGE_VERSION)]
1062
1197
  },
1063
1198
  postGenerationHooks: [
@@ -1316,14 +1451,14 @@ var billing_bill_discount_calculation_default = {
1316
1451
  [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
1317
1452
  };
1318
1453
 
1319
- // src/templates/extensions/billing.invoice_collection_setting.ts
1320
- var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
1321
- var invoiceCollectionSettingTemplate = {
1454
+ // src/templates/extensions/billing.invoice_collection_options.ts
1455
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_options";
1456
+ var invoiceCollectionOptionsTemplate = {
1322
1457
  hidden: true,
1323
1458
  methods: {
1324
- collection_override: { implementation_types: ["script"] }
1459
+ override_options: { implementation_types: ["script"] }
1325
1460
  },
1326
- description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
1461
+ description: "Use Stripe Scripts to create custom invoice collection options that controls how your integration handles invoices generated from subscriptions.",
1327
1462
  generate: (params, context) => {
1328
1463
  const { id } = params;
1329
1464
  const { fs: fs2 } = context;
@@ -1351,15 +1486,15 @@ var invoiceCollectionSettingTemplate = {
1351
1486
  ...base.files
1352
1487
  ],
1353
1488
  methods: {
1354
- collection_override: {
1489
+ override_options: {
1355
1490
  implementation_type: "script"
1356
1491
  }
1357
1492
  }
1358
1493
  };
1359
1494
  }
1360
1495
  };
1361
- var billing_invoice_collection_setting_default = {
1362
- [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
1496
+ var billing_invoice_collection_options_default = {
1497
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionOptionsTemplate
1363
1498
  };
1364
1499
 
1365
1500
  // src/templates/extensions/billing.prorations.ts
@@ -1467,7 +1602,7 @@ var DEFAULT_TEMPLATES = {
1467
1602
  ...extend_workflows_custom_action_default,
1468
1603
  ...billing_customer_balance_application_default,
1469
1604
  ...billing_bill_discount_calculation_default,
1470
- ...billing_invoice_collection_setting_default,
1605
+ ...billing_invoice_collection_options_default,
1471
1606
  ...billing_prorations_default,
1472
1607
  ...billing_recurring_billing_item_handling_default
1473
1608
  };
@@ -1480,7 +1615,7 @@ var _templateManager = new _ExtensionTemplateManager(
1480
1615
  );
1481
1616
 
1482
1617
  // src/bin/template-info.ts
1483
- var logger = (0, import_extensibility_tool_utils5._createLogger)({ name: "template-info" });
1618
+ var logger = (0, import_extensibility_tool_utils4._createLogger)({ name: "template-info" });
1484
1619
  async function main() {
1485
1620
  await (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).usage("Show available extension templates").help().version(false).command(
1486
1621
  "$0",
@@ -1492,7 +1627,7 @@ async function main() {
1492
1627
  (args) => {
1493
1628
  const templates = _templateManager.getTemplateInfo().filter((t) => !t.hidden);
1494
1629
  if (args.outputPath) {
1495
- (0, import_extensibility_tool_utils5._writeJsonOutput)(args.outputPath, templates);
1630
+ (0, import_extensibility_tool_utils4._writeJsonOutput)(args.outputPath, templates);
1496
1631
  } else {
1497
1632
  for (const t of templates) {
1498
1633
  const suffix = t.deprecated ? " (deprecated)" : "";
@@ -113,35 +113,35 @@ export default class MyBalanceApp implements Billing.CustomerBalanceApplication<
113
113
  `
114
114
  },
115
115
  {
116
- path: "extensions/billing.invoice_collection_setting/index.test.ts",
116
+ path: "extensions/billing.invoice_collection_options/index.test.ts",
117
117
  content: `import { beforeEach, describe, it, expect } from 'vitest';
118
118
 
119
- import MyInvoiceCollectionSetting from './index.js';
119
+ import MyInvoiceCollectionOptions from './index.js';
120
120
 
121
- describe('MyInvoiceCollectionSetting', () => {
122
- let instance: MyInvoiceCollectionSetting;
121
+ describe('MyInvoiceCollectionOptions', () => {
122
+ let instance: MyInvoiceCollectionOptions;
123
123
 
124
124
  beforeEach(() => {
125
- instance = new MyInvoiceCollectionSetting();
125
+ instance = new MyInvoiceCollectionOptions();
126
126
  });
127
127
 
128
128
  it('should be constructable', () => {
129
- expect(instance).toBeInstanceOf(MyInvoiceCollectionSetting);
129
+ expect(instance).toBeInstanceOf(MyInvoiceCollectionOptions);
130
130
  });
131
131
  });
132
132
  `
133
133
  },
134
134
  {
135
- path: "extensions/billing.invoice_collection_setting/index.ts",
135
+ path: "extensions/billing.invoice_collection_options/index.ts",
136
136
  content: `import type { Billing, Context } from '@stripe/extensibility-sdk';
137
137
 
138
138
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
139
- interface MyInvoiceCollectionSettingConfig {}
139
+ interface MyInvoiceCollectionOptionsConfig {}
140
140
 
141
- export default class MyInvoiceCollectionSetting implements Billing.InvoiceCollectionSetting<MyInvoiceCollectionSettingConfig> {
142
- collectionOverride(
143
- _request: Billing.InvoiceCollectionSetting.InvoiceCollectionRequest,
144
- _config: MyInvoiceCollectionSettingConfig,
141
+ export default class MyInvoiceCollectionOptions implements Billing.InvoiceCollectionOptions<MyInvoiceCollectionOptionsConfig> {
142
+ overrideOptions(
143
+ _request: Billing.InvoiceCollectionOptions.InvoiceCollectionOptionsInput,
144
+ _config: MyInvoiceCollectionOptionsConfig,
145
145
  _context: Context
146
146
  ) {
147
147
  // TODO: implement your collection setting logic here
@@ -613,6 +613,99 @@ install-deps.log
613
613
 
614
614
  # generated schemas
615
615
  generated
616
+ `
617
+ },
618
+ {
619
+ path: "root/custom-objects/eslint.config.mts",
620
+ content: `import eslint from '@eslint/js';
621
+ import { defineConfig } from 'eslint/config';
622
+ import tseslint from 'typescript-eslint';
623
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
624
+
625
+ import globals from 'globals';
626
+
627
+ import stripeAppsConfig from '@stripe/extensibility-eslint-plugin';
628
+ import customObjectsConfig from '@stripe/extensibility-eslint-plugin/custom-objects';
629
+
630
+ export default defineConfig([
631
+ eslint.configs.recommended,
632
+ ...tseslint.configs.recommended,
633
+ ...stripeAppsConfig,
634
+ ...customObjectsConfig,
635
+
636
+ // Global ignores
637
+ {
638
+ ignores: ['dist', 'generated', 'node_modules'],
639
+ },
640
+
641
+ // TypeScript source files (with type-checking)
642
+ {
643
+ name: 'sources',
644
+ files: ['src/**/*.ts'],
645
+ ignores: ['**/*.test.ts', '**/__tests__/**'],
646
+ languageOptions: {
647
+ globals: {
648
+ ...globals.node,
649
+ },
650
+ parserOptions: {
651
+ projectService: true,
652
+ tsconfigRootDir: import.meta.dirname,
653
+ },
654
+ },
655
+ },
656
+
657
+ // Test files
658
+ {
659
+ name: 'tests',
660
+ files: ['src/**/*.test.ts', 'src/**/__tests__/**/*.ts'],
661
+ languageOptions: {
662
+ globals: {
663
+ ...globals.node,
664
+ },
665
+ parserOptions: {
666
+ projectService: true,
667
+ tsconfigRootDir: import.meta.dirname,
668
+ },
669
+ },
670
+ },
671
+
672
+ // Config files
673
+ {
674
+ name: 'ts-configs',
675
+ files: ['*.config.m?ts', 'eslint.config.mts'],
676
+ languageOptions: {
677
+ globals: {
678
+ ...globals.node,
679
+ },
680
+ parserOptions: {
681
+ projectService: false,
682
+ },
683
+ },
684
+ rules: {
685
+ '@typescript-eslint/no-unused-vars': 'off',
686
+ },
687
+ },
688
+
689
+ // JavaScript/MJS files (scripts, configs) \u2014 no TS project, so only
690
+ // disable the TS-parser-specific rule that doesn't apply without it.
691
+ {
692
+ name: 'js-configs',
693
+ files: ['**/*.js', '**/*.mjs'],
694
+ languageOptions: {
695
+ globals: {
696
+ ...globals.node,
697
+ },
698
+ parserOptions: {
699
+ projectService: false,
700
+ },
701
+ },
702
+ rules: {
703
+ '@typescript-eslint/no-require-imports': 'off',
704
+ },
705
+ },
706
+
707
+ eslintConfigPrettier,
708
+ ]);
616
709
  `
617
710
  },
618
711
  {
@@ -625,7 +718,9 @@ generated
625
718
  "private": true,
626
719
  "scripts": {
627
720
  "build": "test -d src && custom-objects-build --input src --output dist || true",
721
+ "lint": "pnpm lint:types && pnpm lint:eslint",
628
722
  "lint:types": "test ! -d src || tsc --noEmit",
723
+ "lint:eslint": "eslint .",
629
724
  "test": "vitest run"
630
725
  },
631
726
  "dependencies": {
@@ -648,8 +743,20 @@ generated
648
743
  "moduleResolution": "bundler",
649
744
  "types": ["vitest/globals"]
650
745
  },
746
+ "include": ["src/**/*.ts"],
651
747
  "exclude": ["dist"]
652
748
  }
749
+ `
750
+ },
751
+ {
752
+ path: "root/custom-objects/vitest.config.mts",
753
+ content: `import { defineConfig } from 'vitest/config';
754
+
755
+ export default defineConfig({
756
+ test: {
757
+ globals: true,
758
+ },
759
+ });
653
760
  `
654
761
  },
655
762
  {
@@ -767,7 +874,7 @@ export default defineConfig([
767
874
  "build": "pnpm -r --if-present build",
768
875
  "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:format",
769
876
  "lint:types": "pnpm -r --if-present lint:types",
770
- "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint",
877
+ "lint:eslint": "eslint . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present lint:eslint && pnpm -r --filter './custom-objects' --if-present lint:eslint",
771
878
  "lint:format": "prettier --check .",
772
879
  "fix:lint": "eslint --fix . --ignore-pattern 'extensions/**' && pnpm -r --filter './extensions/*' --if-present fix:lint",
773
880
  "fix:format": "prettier --write .",
@@ -796,6 +903,10 @@ export default defineConfig([
796
903
 
797
904
  overrides:
798
905
  vite: ^6.0.0
906
+
907
+ allowBuilds:
908
+ core-js-pure: false
909
+ esbuild: false
799
910
  `
800
911
  },
801
912
  {
@@ -813,7 +924,7 @@ declarations:
813
924
  content: `#!/usr/bin/env tsx
814
925
  /**
815
926
  * Runs tests across the workspace:
816
- * - vitest for script extensions and custom objects (extensions/*)
927
+ * - vitest for script extensions (extensions/*) and custom objects (custom-objects/)
817
928
  * - jest for UI extensions (ui/)
818
929
  */
819
930
  import { existsSync, readdirSync } from 'node:fs';
@@ -823,6 +934,8 @@ const hasExtensions =
823
934
  existsSync('extensions') &&
824
935
  readdirSync('extensions').some((name) => existsSync(\`extensions/\${name}/package.json\`));
825
936
 
937
+ const hasCustomObjects = existsSync('custom-objects/package.json');
938
+
826
939
  const hasUI = existsSync('ui/package.json');
827
940
 
828
941
  let exitCode = 0;
@@ -835,7 +948,7 @@ function run(cmd: string): void {
835
948
  }
836
949
  }
837
950
 
838
- if (hasExtensions) {
951
+ if (hasExtensions || hasCustomObjects) {
839
952
  run('vitest run');
840
953
  }
841
954
 
@@ -987,8 +1100,30 @@ function _devNpmDep(name, version) {
987
1100
  return { type: "dev-npm", name, version };
988
1101
  }
989
1102
 
1103
+ // src/workspace-versions.json
1104
+ var workspace_versions_default = {
1105
+ "@stripe/extensibility-custom-objects": "1.0.0",
1106
+ "@stripe/extensibility-custom-objects-tools": "4.0.1",
1107
+ "@stripe/extensibility-dev-tools": "1.0.2",
1108
+ "@stripe/extensibility-eslint-plugin": "1.0.0",
1109
+ "@stripe/extensibility-language-server": "1.0.0",
1110
+ "@stripe/extensibility-sdk": "1.0.0",
1111
+ "@stripe/extensibility-test-helpers": "1.0.0"
1112
+ };
1113
+
1114
+ // src/workspace-versions.ts
1115
+ var _workspaceVersions = workspace_versions_default;
1116
+ function _workspaceVersion(packageName) {
1117
+ const v = _workspaceVersions[packageName];
1118
+ if (v === void 0) {
1119
+ throw new Error(
1120
+ `Unknown workspace package "${packageName}". Check workspace-versions.json or run: tsx scripts/src/sync-workspace-versions.ts`
1121
+ );
1122
+ }
1123
+ return v;
1124
+ }
1125
+
990
1126
  // src/templates/extensions/base.ts
991
- import { _workspaceVersion } from "@stripe/extensibility-tool-utils";
992
1127
  var SDK_PACKAGE_NAME = "@stripe/extensibility-sdk";
993
1128
  var LANGUAGE_SERVER_PACKAGE_NAME = "@stripe/extensibility-language-server";
994
1129
  var LANGUAGE_SERVER_PACKAGE_VERSION = `^${_workspaceVersion(LANGUAGE_SERVER_PACKAGE_NAME)}`;
@@ -1293,14 +1428,14 @@ var billing_bill_discount_calculation_default = {
1293
1428
  [EXTENSION_INTERFACE_ID5]: discountCalculationTemplate
1294
1429
  };
1295
1430
 
1296
- // src/templates/extensions/billing.invoice_collection_setting.ts
1297
- var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_setting";
1298
- var invoiceCollectionSettingTemplate = {
1431
+ // src/templates/extensions/billing.invoice_collection_options.ts
1432
+ var EXTENSION_INTERFACE_ID6 = "billing.invoice_collection_options";
1433
+ var invoiceCollectionOptionsTemplate = {
1299
1434
  hidden: true,
1300
1435
  methods: {
1301
- collection_override: { implementation_types: ["script"] }
1436
+ override_options: { implementation_types: ["script"] }
1302
1437
  },
1303
- description: "Use Stripe Scripts to create custom invoice collection logic that controls how your integration handles invoices generated from subscriptions.",
1438
+ description: "Use Stripe Scripts to create custom invoice collection options that controls how your integration handles invoices generated from subscriptions.",
1304
1439
  generate: (params, context) => {
1305
1440
  const { id } = params;
1306
1441
  const { fs: fs2 } = context;
@@ -1328,15 +1463,15 @@ var invoiceCollectionSettingTemplate = {
1328
1463
  ...base.files
1329
1464
  ],
1330
1465
  methods: {
1331
- collection_override: {
1466
+ override_options: {
1332
1467
  implementation_type: "script"
1333
1468
  }
1334
1469
  }
1335
1470
  };
1336
1471
  }
1337
1472
  };
1338
- var billing_invoice_collection_setting_default = {
1339
- [EXTENSION_INTERFACE_ID6]: invoiceCollectionSettingTemplate
1473
+ var billing_invoice_collection_options_default = {
1474
+ [EXTENSION_INTERFACE_ID6]: invoiceCollectionOptionsTemplate
1340
1475
  };
1341
1476
 
1342
1477
  // src/templates/extensions/billing.prorations.ts
@@ -1444,7 +1579,7 @@ var DEFAULT_TEMPLATES = {
1444
1579
  ...extend_workflows_custom_action_default,
1445
1580
  ...billing_customer_balance_application_default,
1446
1581
  ...billing_bill_discount_calculation_default,
1447
- ...billing_invoice_collection_setting_default,
1582
+ ...billing_invoice_collection_options_default,
1448
1583
  ...billing_prorations_default,
1449
1584
  ...billing_recurring_billing_item_handling_default
1450
1585
  };
@@ -124,11 +124,43 @@ export interface UpdateObjectDefinitionsMethodsScriptsRequest_MethodsScriptsEntr
124
124
  export interface UpdateObjectDefinitionsMethodsScriptsResponse {
125
125
  objectDefinitionIds: string[];
126
126
  }
127
+ export interface ValidateObjectDefinitionDeletionRequest {
128
+ /** The singular API name of the object definition to validate deletion for. */
129
+ apiNameSingular: string;
130
+ /** Target compartment. */
131
+ targetCompartment: TargetCompartment | undefined;
132
+ }
133
+ export interface ValidateObjectDefinitionDeletionResponse {
134
+ result: ValidateObjectDefinitionDeletionResponse_Result;
135
+ /** Error details, present when result = ERROR. */
136
+ errorDetails?: ValidateObjectDefinitionDeletionResponse_ErrorDetails | undefined;
137
+ }
138
+ export declare const ValidateObjectDefinitionDeletionResponse_Result: {
139
+ readonly RESULT_UNSPECIFIED: "RESULT_UNSPECIFIED";
140
+ /** SUCCESS - If the object definition can be deleted, or doesn't exist. */
141
+ readonly SUCCESS: "SUCCESS";
142
+ /** ERROR - If the object definition can't be deleted. */
143
+ readonly ERROR: "ERROR";
144
+ readonly UNRECOGNIZED: "UNRECOGNIZED";
145
+ };
146
+ export type ValidateObjectDefinitionDeletionResponse_Result = typeof ValidateObjectDefinitionDeletionResponse_Result[keyof typeof ValidateObjectDefinitionDeletionResponse_Result];
147
+ export declare namespace ValidateObjectDefinitionDeletionResponse_Result {
148
+ type RESULT_UNSPECIFIED = typeof ValidateObjectDefinitionDeletionResponse_Result.RESULT_UNSPECIFIED;
149
+ type SUCCESS = typeof ValidateObjectDefinitionDeletionResponse_Result.SUCCESS;
150
+ type ERROR = typeof ValidateObjectDefinitionDeletionResponse_Result.ERROR;
151
+ type UNRECOGNIZED = typeof ValidateObjectDefinitionDeletionResponse_Result.UNRECOGNIZED;
152
+ }
153
+ export interface ValidateObjectDefinitionDeletionResponse_ErrorDetails {
154
+ /** User-facing message explaining why the object definition can't be deleted. */
155
+ message: string;
156
+ }
127
157
  export interface ObjectDefinitionsAppApi {
128
158
  /** Updates an existing object definition, or creates a new one if it doesn't exist. */
129
159
  UpsertObjectDefinition(request: UpsertObjectDefinitionRequest): Promise<UpsertObjectDefinitionResponse>;
130
160
  /** Updates the scripts that back object definitions' methods. */
131
161
  UpdateObjectDefinitionsMethodsScripts(request: UpdateObjectDefinitionsMethodsScriptsRequest): Promise<UpdateObjectDefinitionsMethodsScriptsResponse>;
162
+ /** Validates whether an object definition can be safely deleted. */
163
+ ValidateObjectDefinitionDeletion(request: ValidateObjectDefinitionDeletionRequest): Promise<ValidateObjectDefinitionDeletionResponse>;
132
164
  }
133
165
  type ProtoMetaMessageOptions = {
134
166
  options?: {