@shopify/ui-extensions-tester 0.0.1-alpha.0 → 2026.4.0-rc.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 (129) hide show
  1. package/admin.esnext +1 -0
  2. package/admin.js +1 -0
  3. package/admin.mjs +1 -0
  4. package/build/cjs/admin/factories.js +323 -0
  5. package/build/cjs/admin/index.js +70 -0
  6. package/build/cjs/api-version.js +22 -0
  7. package/build/cjs/checkout/factories.js +417 -0
  8. package/build/cjs/checkout/index.js +162 -0
  9. package/build/cjs/customer-account/factories.js +235 -0
  10. package/build/cjs/customer-account/index.js +89 -0
  11. package/build/cjs/fetch-polyfills.js +193 -0
  12. package/build/cjs/index.js +344 -0
  13. package/build/cjs/mocks/i18n.js +21 -0
  14. package/build/cjs/mocks/money.js +16 -0
  15. package/build/cjs/mocks/signals.js +34 -0
  16. package/build/cjs/mocks/target-apis.js +37 -0
  17. package/build/cjs/navigation.js +56 -0
  18. package/build/cjs/point-of-sale/factories.js +510 -0
  19. package/build/cjs/point-of-sale/index.js +85 -0
  20. package/build/cjs/targets.js +36 -0
  21. package/build/esm/admin/factories.mjs +318 -0
  22. package/build/esm/admin/index.mjs +65 -0
  23. package/build/esm/api-version.mjs +18 -0
  24. package/build/esm/checkout/factories.mjs +413 -0
  25. package/build/esm/checkout/index.mjs +153 -0
  26. package/build/esm/customer-account/factories.mjs +231 -0
  27. package/build/esm/customer-account/index.mjs +83 -0
  28. package/build/esm/fetch-polyfills.mjs +188 -0
  29. package/build/esm/index.mjs +319 -0
  30. package/build/esm/mocks/i18n.mjs +17 -0
  31. package/build/esm/mocks/money.mjs +12 -0
  32. package/build/esm/mocks/signals.mjs +29 -0
  33. package/build/esm/mocks/target-apis.mjs +33 -0
  34. package/build/esm/navigation.mjs +51 -0
  35. package/build/esm/point-of-sale/factories.mjs +506 -0
  36. package/build/esm/point-of-sale/index.mjs +79 -0
  37. package/build/esm/targets.mjs +29 -0
  38. package/build/esnext/admin/factories.esnext +318 -0
  39. package/build/esnext/admin/index.esnext +65 -0
  40. package/build/esnext/api-version.esnext +18 -0
  41. package/build/esnext/checkout/factories.esnext +413 -0
  42. package/build/esnext/checkout/index.esnext +153 -0
  43. package/build/esnext/customer-account/factories.esnext +231 -0
  44. package/build/esnext/customer-account/index.esnext +83 -0
  45. package/build/esnext/fetch-polyfills.esnext +188 -0
  46. package/build/esnext/index.esnext +319 -0
  47. package/build/esnext/mocks/i18n.esnext +17 -0
  48. package/build/esnext/mocks/money.esnext +12 -0
  49. package/build/esnext/mocks/signals.esnext +29 -0
  50. package/build/esnext/mocks/target-apis.esnext +33 -0
  51. package/build/esnext/navigation.esnext +51 -0
  52. package/build/esnext/point-of-sale/factories.esnext +506 -0
  53. package/build/esnext/point-of-sale/index.esnext +79 -0
  54. package/build/esnext/targets.esnext +29 -0
  55. package/build/ts/admin/factories.d.ts +19 -0
  56. package/build/ts/admin/factories.d.ts.map +1 -0
  57. package/build/ts/admin/index.d.ts +31 -0
  58. package/build/ts/admin/index.d.ts.map +1 -0
  59. package/build/ts/api-version.d.ts +11 -0
  60. package/build/ts/api-version.d.ts.map +1 -0
  61. package/build/ts/checkout/factories.d.ts +10 -0
  62. package/build/ts/checkout/factories.d.ts.map +1 -0
  63. package/build/ts/checkout/index.d.ts +53 -0
  64. package/build/ts/checkout/index.d.ts.map +1 -0
  65. package/build/ts/customer-account/factories.d.ts +8 -0
  66. package/build/ts/customer-account/factories.d.ts.map +1 -0
  67. package/build/ts/customer-account/index.d.ts +21 -0
  68. package/build/ts/customer-account/index.d.ts.map +1 -0
  69. package/build/ts/fetch-polyfills.d.ts +19 -0
  70. package/build/ts/fetch-polyfills.d.ts.map +1 -0
  71. package/build/ts/index.d.ts +90 -0
  72. package/build/ts/index.d.ts.map +1 -0
  73. package/build/ts/mocks/i18n.d.ts +14 -0
  74. package/build/ts/mocks/i18n.d.ts.map +1 -0
  75. package/build/ts/mocks/money.d.ts +9 -0
  76. package/build/ts/mocks/money.d.ts.map +1 -0
  77. package/build/ts/mocks/signals.d.ts +19 -0
  78. package/build/ts/mocks/signals.d.ts.map +1 -0
  79. package/build/ts/mocks/target-apis.d.ts +15 -0
  80. package/build/ts/mocks/target-apis.d.ts.map +1 -0
  81. package/build/ts/navigation.d.ts +41 -0
  82. package/build/ts/navigation.d.ts.map +1 -0
  83. package/build/ts/point-of-sale/factories.d.ts +20 -0
  84. package/build/ts/point-of-sale/factories.d.ts.map +1 -0
  85. package/build/ts/point-of-sale/index.d.ts +30 -0
  86. package/build/ts/point-of-sale/index.d.ts.map +1 -0
  87. package/build/ts/targets.d.ts +27 -0
  88. package/build/ts/targets.d.ts.map +1 -0
  89. package/build/tsconfig.tsbuildinfo +1 -0
  90. package/checkout.esnext +1 -0
  91. package/checkout.js +1 -0
  92. package/checkout.mjs +1 -0
  93. package/customer-account.esnext +1 -0
  94. package/customer-account.js +1 -0
  95. package/customer-account.mjs +1 -0
  96. package/index.esnext +1 -0
  97. package/index.js +1 -0
  98. package/index.mjs +1 -0
  99. package/package.json +84 -2
  100. package/point-of-sale.esnext +1 -0
  101. package/point-of-sale.js +1 -0
  102. package/point-of-sale.mjs +1 -0
  103. package/src/admin/README.md +78 -0
  104. package/src/admin/factories.ts +380 -0
  105. package/src/admin/index.ts +85 -0
  106. package/src/api-version.ts +23 -0
  107. package/src/checkout/README.md +152 -0
  108. package/src/checkout/factories.ts +483 -0
  109. package/src/checkout/index.ts +174 -0
  110. package/src/customer-account/README.md +86 -0
  111. package/src/customer-account/factories.ts +272 -0
  112. package/src/customer-account/index.ts +90 -0
  113. package/src/fetch-polyfills.ts +222 -0
  114. package/src/index.ts +456 -0
  115. package/src/mocks/i18n.ts +15 -0
  116. package/src/mocks/money.ts +7 -0
  117. package/src/mocks/signals.ts +37 -0
  118. package/src/mocks/target-apis.ts +56 -0
  119. package/src/navigation.ts +72 -0
  120. package/src/point-of-sale/README.md +100 -0
  121. package/src/point-of-sale/factories.ts +581 -0
  122. package/src/point-of-sale/index.ts +92 -0
  123. package/src/targets.ts +68 -0
  124. package/src/tests/admin-factories.test.ts +31 -0
  125. package/src/tests/fetch.test.ts +139 -0
  126. package/src/tests/fixtures/test-module.ts +1 -0
  127. package/src/tests/getExtension.test.ts +167 -0
  128. package/src/tests/helpers.ts +140 -0
  129. package/src/tests/navigation.test.ts +130 -0
package/admin.esnext ADDED
@@ -0,0 +1 @@
1
+ export * from "./build/esnext/admin/index.esnext";
package/admin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./build/cjs/admin/index.js");
package/admin.mjs ADDED
@@ -0,0 +1 @@
1
+ export * from "./build/esm/admin/index.mjs";
@@ -0,0 +1,323 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var signals = require('../mocks/signals.js');
6
+ var i18n = require('../mocks/i18n.js');
7
+ var index = require('./index.js');
8
+
9
+ /**
10
+ * Extracts the API type for a given admin extension target directly from the
11
+ * implementation's `ExtensionTargets` interface.
12
+ *
13
+ * Properties prefixed with `__` are private internal APIs and are excluded
14
+ * from the mock type so they cannot be relied on in test suites.
15
+ */
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Derived types — not directly exported from the admin surface barrel
19
+ // ---------------------------------------------------------------------------
20
+
21
+ function gidFromTarget(target) {
22
+ const resource = target.split('.')[1].replace(/-details$|-index$|-fulfilled-card$|-purchase-option$/, '').split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
23
+ return `gid://shopify/${resource}/1`;
24
+ }
25
+ function createData(selected = []) {
26
+ return {
27
+ selected
28
+ };
29
+ }
30
+ function createNavigation() {
31
+ return {
32
+ navigate: () => {}
33
+ };
34
+ }
35
+ function createConfigApp() {
36
+ return {
37
+ launchUrl: 'https://mock-app.test/launch',
38
+ applicationUrl: 'https://mock-app.test'
39
+ };
40
+ }
41
+ function createMockStandardApi(target) {
42
+ return {
43
+ extension: {
44
+ target
45
+ },
46
+ auth: {
47
+ idToken: async () => 'mock-id-token'
48
+ },
49
+ i18n: i18n.createMockI18n(),
50
+ intents: {
51
+ launchUrl: undefined,
52
+ invoke: async () => ({
53
+ complete: Promise.resolve({
54
+ code: 'closed'
55
+ })
56
+ })
57
+ },
58
+ storage: index.createStorage(),
59
+ query: async () => ({
60
+ data: undefined
61
+ })
62
+ };
63
+ }
64
+ function createMockStandardRenderingApi(target) {
65
+ return {
66
+ ...createMockStandardApi(target),
67
+ resourcePicker: async () => undefined,
68
+ picker: async () => ({
69
+ selected: Promise.resolve(undefined)
70
+ })
71
+ };
72
+ }
73
+ function createMockBlockApi(target) {
74
+ return {
75
+ ...createMockStandardRenderingApi(target),
76
+ data: createData([{
77
+ id: gidFromTarget(target)
78
+ }]),
79
+ navigation: createNavigation()
80
+ };
81
+ }
82
+ function createMockActionApi(target) {
83
+ return {
84
+ ...createMockStandardRenderingApi(target),
85
+ close: () => {},
86
+ data: createData([{
87
+ id: gidFromTarget(target)
88
+ }])
89
+ };
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Group factory functions — each composes the correct API for a target group
94
+ // ---------------------------------------------------------------------------
95
+
96
+ function createPrintActionMock(target) {
97
+ return {
98
+ ...createMockStandardRenderingApi(target),
99
+ data: createData()
100
+ };
101
+ }
102
+ function createShouldRenderMock(target) {
103
+ return {
104
+ ...createMockStandardApi(target),
105
+ data: createData()
106
+ };
107
+ }
108
+ function createProductDetailsConfigMock(target) {
109
+ return {
110
+ ...createMockBlockApi(target),
111
+ data: {
112
+ selected: [],
113
+ product: {
114
+ id: 'gid://shopify/Product/1',
115
+ title: 'Mock Product',
116
+ handle: 'mock-product',
117
+ status: 'ACTIVE',
118
+ totalVariants: 1,
119
+ totalInventory: 10,
120
+ hasOnlyDefaultVariant: true,
121
+ onlineStoreUrl: 'https://mock-shop.myshopify.com/products/mock-product',
122
+ options: [],
123
+ productType: '',
124
+ productComponents: []
125
+ },
126
+ app: createConfigApp()
127
+ }
128
+ };
129
+ }
130
+ function createProductVariantDetailsConfigMock(target) {
131
+ return {
132
+ ...createMockBlockApi(target),
133
+ data: {
134
+ selected: [],
135
+ variant: {
136
+ id: 'gid://shopify/ProductVariant/1',
137
+ sku: 'MOCK-SKU',
138
+ barcode: '',
139
+ title: 'Default',
140
+ displayName: 'Mock Product - Default',
141
+ price: '0.00',
142
+ compareAtPrice: '0.00',
143
+ taxable: true,
144
+ taxCode: '',
145
+ weight: 0,
146
+ selectedOptions: [],
147
+ productVariantComponents: []
148
+ },
149
+ app: createConfigApp()
150
+ }
151
+ };
152
+ }
153
+ function createDiscountFunctionSettingsMock(target) {
154
+ return {
155
+ ...createMockStandardRenderingApi(target),
156
+ navigation: createNavigation(),
157
+ applyMetafieldChange: async () => index.createResult('applyMetafieldChange'),
158
+ data: {
159
+ id: 'gid://shopify/DiscountAutomaticApp/1',
160
+ metafields: []
161
+ },
162
+ discounts: {
163
+ discountClasses: signals.createReadonlySignalLike([]),
164
+ updateDiscountClasses: () => index.createResult('updateDiscountClasses'),
165
+ discountMethod: signals.createReadonlySignalLike('automatic')
166
+ }
167
+ };
168
+ }
169
+ function createOrderRoutingRuleMock(target) {
170
+ return {
171
+ ...createMockStandardRenderingApi(target),
172
+ applyMetafieldsChange: () => {},
173
+ data: {
174
+ rule: {
175
+ label: 'Mock Routing Rule',
176
+ description: 'A mock order routing rule',
177
+ id: 'gid://shopify/DeliveryCustomization/1',
178
+ metafields: []
179
+ }
180
+ }
181
+ };
182
+ }
183
+ function createValidationSettingsMock(target) {
184
+ return {
185
+ ...createMockStandardRenderingApi(target),
186
+ applyMetafieldChange: async () => index.createResult('applyMetafieldChange'),
187
+ data: {
188
+ validation: undefined,
189
+ shopifyFunction: {
190
+ id: 'gid://shopify/ShopifyFunction/1'
191
+ }
192
+ }
193
+ };
194
+ }
195
+ function createPurchaseOptionsCardMock(target) {
196
+ return {
197
+ ...createMockActionApi(target),
198
+ data: {
199
+ selected: []
200
+ }
201
+ };
202
+ }
203
+ function createCustomerSegmentTemplateMock(target) {
204
+ return {
205
+ ...createMockStandardApi(target)
206
+ };
207
+ }
208
+
209
+ // ---------------------------------------------------------------------------
210
+ // Factory map — TypeScript verifies each entry against ApiForTarget<K>
211
+ // ---------------------------------------------------------------------------
212
+
213
+ const adminMockFactories = {
214
+ // Runnable targets
215
+ 'admin.customers.segmentation-templates.data': createCustomerSegmentTemplateMock,
216
+ 'admin.app.tools.data': createMockStandardApi,
217
+ // Block targets
218
+ 'admin.product-details.block.render': createMockBlockApi,
219
+ 'admin.order-details.block.render': createMockBlockApi,
220
+ 'admin.customer-details.block.render': createMockBlockApi,
221
+ 'admin.collection-details.block.render': createMockBlockApi,
222
+ 'admin.draft-order-details.block.render': createMockBlockApi,
223
+ 'admin.abandoned-checkout-details.block.render': createMockBlockApi,
224
+ 'admin.catalog-details.block.render': createMockBlockApi,
225
+ 'admin.company-details.block.render': createMockBlockApi,
226
+ 'admin.company-location-details.block.render': createMockBlockApi,
227
+ 'admin.gift-card-details.block.render': createMockBlockApi,
228
+ 'admin.product-variant-details.block.render': createMockBlockApi,
229
+ 'admin.product-details.reorder.render': createMockBlockApi,
230
+ // Action targets
231
+ 'admin.product-details.action.render': createMockActionApi,
232
+ 'admin.catalog-details.action.render': createMockActionApi,
233
+ 'admin.company-details.action.render': createMockActionApi,
234
+ 'admin.gift-card-details.action.render': createMockActionApi,
235
+ 'admin.order-details.action.render': createMockActionApi,
236
+ 'admin.customer-details.action.render': createMockActionApi,
237
+ 'admin.customer-segment-details.action.render': createMockActionApi,
238
+ 'admin.product-index.action.render': createMockActionApi,
239
+ 'admin.order-index.action.render': createMockActionApi,
240
+ 'admin.customer-index.action.render': createMockActionApi,
241
+ 'admin.discount-index.action.render': createMockActionApi,
242
+ 'admin.collection-details.action.render': createMockActionApi,
243
+ 'admin.collection-index.action.render': createMockActionApi,
244
+ 'admin.abandoned-checkout-details.action.render': createMockActionApi,
245
+ 'admin.product-variant-details.action.render': createMockActionApi,
246
+ 'admin.draft-order-details.action.render': createMockActionApi,
247
+ 'admin.draft-order-index.action.render': createMockActionApi,
248
+ 'admin.discount-details.action.render': createMockActionApi,
249
+ 'admin.order-fulfilled-card.action.render': createMockActionApi,
250
+ // Bulk action targets
251
+ 'admin.product-index.selection-action.render': createMockActionApi,
252
+ 'admin.order-index.selection-action.render': createMockActionApi,
253
+ 'admin.customer-index.selection-action.render': createMockActionApi,
254
+ 'admin.draft-order-index.selection-action.render': createMockActionApi,
255
+ 'admin.discount-index.selection-action.render': createMockActionApi,
256
+ // Purchase options card action targets
257
+ 'admin.product-purchase-option.action.render': createPurchaseOptionsCardMock,
258
+ 'admin.product-variant-purchase-option.action.render': createPurchaseOptionsCardMock,
259
+ // Print action targets
260
+ 'admin.order-details.print-action.render': createPrintActionMock,
261
+ 'admin.product-details.print-action.render': createPrintActionMock,
262
+ 'admin.order-index.selection-print-action.render': createPrintActionMock,
263
+ 'admin.product-index.selection-print-action.render': createPrintActionMock,
264
+ // Configuration targets
265
+ 'admin.product-details.configuration.render': createProductDetailsConfigMock,
266
+ 'admin.product-variant-details.configuration.render': createProductVariantDetailsConfigMock,
267
+ // Function settings targets
268
+ 'admin.discount-details.function-settings.render': createDiscountFunctionSettingsMock,
269
+ 'admin.settings.internal-order-routing-rule.render': createOrderRoutingRuleMock,
270
+ 'admin.settings.order-routing-rule.render': createOrderRoutingRuleMock,
271
+ 'admin.settings.validation.render': createValidationSettingsMock,
272
+ // Should-render targets (action)
273
+ 'admin.product-details.action.should-render': createShouldRenderMock,
274
+ 'admin.catalog-details.action.should-render': createShouldRenderMock,
275
+ 'admin.company-details.action.should-render': createShouldRenderMock,
276
+ 'admin.gift-card-details.action.should-render': createShouldRenderMock,
277
+ 'admin.order-details.action.should-render': createShouldRenderMock,
278
+ 'admin.customer-details.action.should-render': createShouldRenderMock,
279
+ 'admin.customer-segment-details.action.should-render': createShouldRenderMock,
280
+ 'admin.product-index.action.should-render': createShouldRenderMock,
281
+ 'admin.order-index.action.should-render': createShouldRenderMock,
282
+ 'admin.customer-index.action.should-render': createShouldRenderMock,
283
+ 'admin.discount-index.action.should-render': createShouldRenderMock,
284
+ 'admin.collection-details.action.should-render': createShouldRenderMock,
285
+ 'admin.collection-index.action.should-render': createShouldRenderMock,
286
+ 'admin.abandoned-checkout-details.action.should-render': createShouldRenderMock,
287
+ 'admin.product-variant-details.action.should-render': createShouldRenderMock,
288
+ 'admin.draft-order-details.action.should-render': createShouldRenderMock,
289
+ 'admin.draft-order-index.action.should-render': createShouldRenderMock,
290
+ 'admin.discount-details.action.should-render': createShouldRenderMock,
291
+ 'admin.order-fulfilled-card.action.should-render': createShouldRenderMock,
292
+ // Should-render targets (bulk action)
293
+ 'admin.product-index.selection-action.should-render': createShouldRenderMock,
294
+ 'admin.order-index.selection-action.should-render': createShouldRenderMock,
295
+ 'admin.customer-index.selection-action.should-render': createShouldRenderMock,
296
+ 'admin.draft-order-index.selection-action.should-render': createShouldRenderMock,
297
+ 'admin.discount-index.selection-action.should-render': createShouldRenderMock,
298
+ // Should-render targets (print action)
299
+ 'admin.order-details.print-action.should-render': createShouldRenderMock,
300
+ 'admin.product-details.print-action.should-render': createShouldRenderMock,
301
+ 'admin.order-index.selection-print-action.should-render': createShouldRenderMock,
302
+ 'admin.product-index.selection-print-action.should-render': createShouldRenderMock
303
+ };
304
+
305
+ // ---------------------------------------------------------------------------
306
+ // Main factory
307
+ // ---------------------------------------------------------------------------
308
+
309
+ /**
310
+ * Creates a complete mock API for an admin extension target.
311
+ * Each entry in the factory map is type-checked by TypeScript against
312
+ * the concrete API type for that target.
313
+ */
314
+ function createMockAdminTargetApi(target) {
315
+ const factory = adminMockFactories[target];
316
+ if (!factory) {
317
+ throw new Error(`Unsupported admin target: "${target}". ` + 'Add an entry for this target in adminMockFactories.');
318
+ }
319
+ return factory(target);
320
+ }
321
+
322
+ exports.createMockAdminTargetApi = createMockAdminTargetApi;
323
+ exports.gidFromTarget = gidFromTarget;
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * Creates a mock `Storage` instance.
7
+ *
8
+ * Optionally accepts a `Record<string, unknown>` of initial entries.
9
+ */
10
+ function createStorage(initialEntries) {
11
+ const store = new Map(initialEntries ? Object.entries(initialEntries) : []);
12
+ return {
13
+ set: async (key, value) => {
14
+ store.set(key, value);
15
+ },
16
+ setMany: async entries => {
17
+ for (const [entryKey, entryValue] of Object.entries(entries)) {
18
+ store.set(entryKey, entryValue);
19
+ }
20
+ },
21
+ get: async key => store.get(key),
22
+ getMany: async keys => keys.map(entry => store.get(entry)),
23
+ clear: async () => {
24
+ store.clear();
25
+ },
26
+ delete: async key => store.delete(key),
27
+ deleteMany: async keys => {
28
+ const result = {};
29
+ for (const entry of keys) {
30
+ result[entry] = store.delete(entry);
31
+ }
32
+ return result;
33
+ },
34
+ entries: async () => store.entries()
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Maps each admin mutation API name to its result type.
40
+ */
41
+
42
+ const adminMutationDefaults = {
43
+ applyMetafieldChange: () => ({
44
+ type: 'success'
45
+ }),
46
+ updateDiscountClasses: () => ({
47
+ success: true,
48
+ value: []
49
+ })
50
+ };
51
+
52
+ /**
53
+ * Creates a typed mock result for an admin mutation API.
54
+ *
55
+ * @param mutation - The mutation API name (e.g. `'applyMetafieldChange'`).
56
+ * @param result - Optional partial override merged with the default.
57
+ *
58
+ * @example
59
+ * createResult('applyMetafieldChange');
60
+ * createResult('updateDiscountClasses', {value: ['ORDER']});
61
+ */
62
+ function createResult(mutation, result) {
63
+ return {
64
+ ...adminMutationDefaults[mutation](),
65
+ ...result
66
+ };
67
+ }
68
+
69
+ exports.createResult = createResult;
70
+ exports.createStorage = createStorage;
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * The API version supported by this version of the library.
7
+ *
8
+ * At build time, `"2026.4.0-rc.2"` is replaced by rollup with the
9
+ * raw NPM version string from package.json (e.g. `"2026.4.0-rc.1"`).
10
+ *
11
+ * When running from source (e.g. in tests), the placeholder is still
12
+ * present, so we fall back to reading package.json via require.
13
+ */
14
+
15
+ const npmVersion = "2026.4.0-rc.2";
16
+ function npmVersionToApiVersion(version) {
17
+ const [year, minor] = version.split('.');
18
+ return `${year}-${minor.padStart(2, '0')}`;
19
+ }
20
+ const API_VERSION = npmVersionToApiVersion(npmVersion);
21
+
22
+ exports.API_VERSION = API_VERSION;