atmn 1.1.25 → 2.0.0

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 (117) hide show
  1. package/README.md +120 -0
  2. package/dist/bin.js +23102 -0
  3. package/dist/index.js +2906 -0
  4. package/dist/tsconfig.tsbuildinfo +1 -1
  5. package/package.json +27 -74
  6. package/src/actions/api/callApi.ts +280 -0
  7. package/src/actions/api/registerApiCommands.ts +121 -0
  8. package/src/actions/env/fetchOrgInfo.ts +32 -0
  9. package/src/actions/env/types/orgInfo.ts +18 -0
  10. package/src/actions/env.ts +94 -0
  11. package/src/actions/init/runInit.ts +401 -0
  12. package/src/actions/login/keyless.ts +135 -0
  13. package/src/actions/login.ts +144 -0
  14. package/src/actions/pull/appendPlanVersionFixture.ts +373 -0
  15. package/src/actions/pull/applyPreview.ts +553 -0
  16. package/src/actions/pull/applySettingsPreview.ts +114 -0
  17. package/src/actions/pull/changedFixtureKeys.ts +88 -0
  18. package/src/actions/pull/listSourceFiles.ts +29 -0
  19. package/src/actions/pull/locateFixture.ts +78 -0
  20. package/src/actions/pull/resolveCollectionTarget.ts +198 -0
  21. package/src/actions/pull/rewriteConfig.ts +57 -0
  22. package/src/actions/pull/scaffoldConfig.ts +118 -0
  23. package/src/actions/pull.ts +399 -0
  24. package/src/actions/push/backfillInternalIds.ts +394 -0
  25. package/src/actions/push/deprecatedFields.ts +55 -0
  26. package/src/actions/push.ts +294 -0
  27. package/src/actions/reset/runReset.ts +58 -0
  28. package/src/actions/sandbox/createSandbox.ts +83 -0
  29. package/src/actions/sandbox/deleteSandbox.ts +91 -0
  30. package/src/actions/sandbox/listSandboxes.ts +28 -0
  31. package/src/actions/sandbox/types/sandboxClient.ts +16 -0
  32. package/src/actions/sandbox/useSandbox.ts +157 -0
  33. package/src/actions/sandbox/withSandboxScopeHint.ts +27 -0
  34. package/src/actions/skills/skills.ts +246 -0
  35. package/src/auth/announceAuthorizationUrl.ts +26 -0
  36. package/src/auth/browser/openSystemBrowser.ts +7 -0
  37. package/src/auth/browser/tryOpenBrowser.ts +17 -0
  38. package/src/auth/browser/watchLauncher.ts +46 -0
  39. package/src/auth/buildAuthorizationUrl.ts +36 -0
  40. package/src/auth/callbackPages.ts +126 -0
  41. package/src/auth/createOrgApiKeys.ts +46 -0
  42. package/src/auth/keyless.ts +119 -0
  43. package/src/auth/oauthConfig.ts +63 -0
  44. package/src/auth/runOAuthFlow.ts +230 -0
  45. package/src/auth/types/browserOpener.ts +5 -0
  46. package/src/auth/types/impersonationTokens.ts +23 -0
  47. package/src/auth/types/oauthTokens.ts +13 -0
  48. package/src/auth/types/orgApiKeys.ts +6 -0
  49. package/src/bin.ts +9 -0
  50. package/src/cli.ts +648 -0
  51. package/src/config/configPackageName.ts +9 -0
  52. package/src/config/legacyConfig.ts +25 -0
  53. package/src/config/loadConfig.ts +231 -0
  54. package/src/env/assertSandboxTarget.ts +20 -0
  55. package/src/env/loadEnv.ts +184 -0
  56. package/src/env/resolveTarget.ts +134 -0
  57. package/src/env/sandboxKeyName.ts +18 -0
  58. package/src/generated/apiRoutes.ts +3787 -0
  59. package/src/generated/client.ts +51564 -0
  60. package/src/generated/emit.ts +1163 -0
  61. package/src/generated/emitRuntime.ts +522 -0
  62. package/src/generated/features.ts +146 -0
  63. package/src/generated/labels.ts +29 -0
  64. package/src/generated/licenses.ts +287 -0
  65. package/src/generated/lintRules.ts +2207 -0
  66. package/src/generated/lintRuntime.ts +865 -0
  67. package/src/generated/plans.ts +1628 -0
  68. package/src/generated/referralPrograms.ts +22 -0
  69. package/src/generated/rewards.ts +58 -0
  70. package/src/generated/settings.ts +21 -0
  71. package/src/generated/skills.ts +305 -0
  72. package/src/generated/variants.ts +934 -0
  73. package/src/generated/wire.ts +334 -0
  74. package/src/http/autumnFetch.ts +30 -0
  75. package/src/index.ts +20 -0
  76. package/src/project/chooseConfigDir.ts +41 -0
  77. package/src/project/resolveProject.ts +115 -0
  78. package/src/project/rootMarker.ts +40 -0
  79. package/src/prompt/prompt.ts +186 -0
  80. package/src/prompt/select.ts +162 -0
  81. package/src/render/renderEnv.ts +77 -0
  82. package/src/render/renderPreview.ts +945 -0
  83. package/src/render/renderSandboxes.ts +92 -0
  84. package/src/render/stripTerminalControls.ts +19 -0
  85. package/src/repo/findRepoRoot.ts +79 -0
  86. package/src/surgery/appendPropertyEdit.ts +67 -0
  87. package/src/surgery/appendToArray.ts +87 -0
  88. package/src/surgery/appendToBinding.ts +19 -0
  89. package/src/surgery/appendToCollection.ts +40 -0
  90. package/src/surgery/appendToFixtureArray.ts +71 -0
  91. package/src/surgery/arrayBinding.ts +30 -0
  92. package/src/surgery/deleteFixtureLiteral.ts +81 -0
  93. package/src/surgery/deleteReference.ts +48 -0
  94. package/src/surgery/ensureBuilderImport.ts +65 -0
  95. package/src/surgery/findFixture.ts +238 -0
  96. package/src/surgery/fixtureEdit.ts +156 -0
  97. package/src/surgery/fixtureLocation.ts +32 -0
  98. package/src/surgery/insertCollection.ts +86 -0
  99. package/src/surgery/insertFirstProperty.ts +73 -0
  100. package/src/surgery/patchFixtureProperty.ts +152 -0
  101. package/src/surgery/patchSingletonProperty.ts +221 -0
  102. package/src/surgery/replaceFixture.ts +28 -0
  103. package/src/surgery/setFixtureProperty.ts +55 -0
  104. package/src/surgery/staticFixtureRule.ts +48 -0
  105. package/src/version.ts +5 -0
  106. package/dist/cli.js +0 -146296
  107. package/dist/compose/index.js +0 -122
  108. package/dist/src/compose/builders/builderFunctions.d.ts +0 -84
  109. package/dist/src/compose/builders/rewardFunctions.d.ts +0 -5
  110. package/dist/src/compose/builders/variantFunctions.d.ts +0 -2
  111. package/dist/src/compose/index.d.ts +0 -19
  112. package/dist/src/compose/models/featureModels.d.ts +0 -262
  113. package/dist/src/compose/models/index.d.ts +0 -3
  114. package/dist/src/compose/models/planModels.d.ts +0 -562
  115. package/dist/src/compose/models/rewardModels.d.ts +0 -52
  116. package/dist/src/compose/models/variantModels.d.ts +0 -34
  117. package/readme.md +0 -186
package/dist/index.js ADDED
@@ -0,0 +1,2906 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
4
+ // src/generated/features.ts
5
+ var feature = (input) => input;
6
+ // src/generated/licenses.ts
7
+ var license = (input) => input;
8
+ // src/generated/plans.ts
9
+ var plan = (input) => input;
10
+ // src/generated/referralPrograms.ts
11
+ var referralProgram = (input) => input;
12
+ // src/generated/rewards.ts
13
+ var coupon = (input) => ({ coupon: input });
14
+ var featureGrant = (input) => ({
15
+ featureGrant: input
16
+ });
17
+ // src/generated/variants.ts
18
+ var variant = (input) => input;
19
+ // src/generated/lintRules.ts
20
+ var LINT_RULES = {
21
+ features: {
22
+ label: "feature",
23
+ idField: "featureId",
24
+ required: ["featureId", "name", "type"],
25
+ fields: {
26
+ type: {
27
+ enum: ["boolean", "metered", "credit_system", "ai_credit_system"]
28
+ },
29
+ defaultMarkup: {
30
+ minimum: -100
31
+ },
32
+ internalId: {
33
+ minLength: 1
34
+ }
35
+ },
36
+ rules: [
37
+ {
38
+ kind: "requiredWhen",
39
+ when: "type",
40
+ equals: "metered",
41
+ require: ["consumable"],
42
+ because: "Omitting it silently creates a non-consumable feature, which never resets."
43
+ },
44
+ {
45
+ kind: "unique",
46
+ field: "featureId",
47
+ because: "Two features claiming one id race to define the same row."
48
+ },
49
+ {
50
+ kind: "unique",
51
+ field: "internalId",
52
+ because: "A stable id names exactly one row; two fixtures cannot both be it."
53
+ }
54
+ ]
55
+ },
56
+ "features.creditSchema": {
57
+ variants: {
58
+ on: "tierBehavior",
59
+ byValue: {
60
+ graduated: {
61
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
62
+ fields: {
63
+ meteredFeatureId: {
64
+ minLength: 1
65
+ },
66
+ billingUnits: {
67
+ exclusiveMinimum: 0
68
+ },
69
+ tierBehavior: {
70
+ enum: ["graduated"]
71
+ },
72
+ tiers: {
73
+ minItems: 1
74
+ }
75
+ }
76
+ }
77
+ },
78
+ fallback: {
79
+ required: ["creditCost", "meteredFeatureId"],
80
+ fields: {
81
+ meteredFeatureId: {
82
+ minLength: 1
83
+ },
84
+ billingUnits: {
85
+ exclusiveMinimum: 0
86
+ },
87
+ creditCost: {
88
+ minimum: 0
89
+ }
90
+ }
91
+ }
92
+ }
93
+ },
94
+ "features.creditSchema.dimensions": {
95
+ keys: {
96
+ minLength: 1,
97
+ maxLength: 64
98
+ }
99
+ },
100
+ "features.creditSchema.dimensions.*": {
101
+ variants: {
102
+ on: "tierBehavior",
103
+ byValue: {
104
+ graduated: {
105
+ required: ["match", "tierBehavior", "tiers"],
106
+ fields: {
107
+ priority: {
108
+ minimum: -9007199254740991,
109
+ maximum: 9007199254740991
110
+ },
111
+ tierBehavior: {
112
+ enum: ["graduated"]
113
+ },
114
+ tiers: {
115
+ minItems: 1
116
+ }
117
+ }
118
+ }
119
+ },
120
+ fallback: {
121
+ required: ["creditCost", "match"],
122
+ fields: {
123
+ priority: {
124
+ minimum: -9007199254740991,
125
+ maximum: 9007199254740991
126
+ },
127
+ creditCost: {
128
+ minimum: 0
129
+ }
130
+ }
131
+ }
132
+ }
133
+ },
134
+ "features.creditSchema.dimensions.*.tiers": {
135
+ required: ["creditCost", "to"],
136
+ fields: {
137
+ to: {
138
+ exclusiveMinimum: 0
139
+ },
140
+ creditCost: {
141
+ minimum: 0
142
+ }
143
+ }
144
+ },
145
+ "features.creditSchema.multipliers": {
146
+ keys: {
147
+ minLength: 1,
148
+ maxLength: 64
149
+ }
150
+ },
151
+ "features.creditSchema.multipliers.*": {
152
+ required: ["match"],
153
+ fields: {
154
+ factor: {
155
+ exclusiveMinimum: 0
156
+ }
157
+ }
158
+ },
159
+ "features.creditSchema.tiers": {
160
+ required: ["creditCost", "to"],
161
+ fields: {
162
+ to: {
163
+ exclusiveMinimum: 0
164
+ },
165
+ creditCost: {
166
+ minimum: 0
167
+ }
168
+ }
169
+ },
170
+ "features.display": {
171
+ required: ["plural", "singular"]
172
+ },
173
+ "features.modelMarkups": {
174
+ keys: {
175
+ pattern: ".+\\/.+"
176
+ }
177
+ },
178
+ "features.modelMarkups.*": {
179
+ fields: {
180
+ markup: {
181
+ minimum: -100
182
+ },
183
+ inputCost: {
184
+ minimum: 0
185
+ },
186
+ outputCost: {
187
+ minimum: 0
188
+ }
189
+ }
190
+ },
191
+ "features.providerMarkups.*": {
192
+ required: ["markup"],
193
+ fields: {
194
+ markup: {
195
+ minimum: -100
196
+ }
197
+ }
198
+ },
199
+ plans: {
200
+ label: "plan",
201
+ idField: "planId",
202
+ required: ["planId", "versionSlug"],
203
+ fields: {
204
+ planId: {
205
+ minLength: 1,
206
+ pattern: "^[a-zA-Z0-9_-]+$"
207
+ },
208
+ newPlanId: {
209
+ minLength: 1,
210
+ pattern: "^[a-zA-Z0-9_-]+$"
211
+ },
212
+ internalId: {
213
+ minLength: 1
214
+ },
215
+ name: {
216
+ minLength: 1
217
+ },
218
+ version: {
219
+ minimum: 1,
220
+ maximum: 9007199254740991
221
+ },
222
+ versionSlug: {
223
+ minLength: 1,
224
+ pattern: "^[a-zA-Z0-9_-]+$"
225
+ },
226
+ newVersionSlug: {
227
+ minLength: 1,
228
+ pattern: "^[a-zA-Z0-9_-]+$"
229
+ },
230
+ versioning: {
231
+ enum: ["existing", "new_version", "all_versions"]
232
+ },
233
+ baseVariantId: {
234
+ minLength: 1,
235
+ pattern: "^[a-zA-Z0-9_-]+$"
236
+ }
237
+ },
238
+ rules: [
239
+ {
240
+ kind: "unique",
241
+ field: "internalId",
242
+ because: "A stable id names exactly one row; two fixtures cannot both be it."
243
+ },
244
+ {
245
+ kind: "unique",
246
+ field: "planId",
247
+ alongside: "versionSlug",
248
+ because: "A plan id plus a version slug names exactly one version."
249
+ },
250
+ {
251
+ kind: "linkedOnce",
252
+ groupBy: "planId",
253
+ namedBy: "versionSlug",
254
+ absentMeans: "v1",
255
+ collection: "variants",
256
+ identity: "variantPlanId",
257
+ pins: ["versionSlug", "version"],
258
+ because: "When versioning a base plan with variants linked, you also need to version the variant, and relink the new version to the new variant version."
259
+ },
260
+ {
261
+ kind: "exactlyOneActive",
262
+ groupBy: "planId",
263
+ field: "active",
264
+ label: "Plan",
265
+ because: "Every version of a plan lives in plans; mark the one customers can buy active: true and the rest active: false."
266
+ }
267
+ ]
268
+ },
269
+ "plans.billingControls.autoTopups": {
270
+ required: ["featureId", "quantity", "threshold"],
271
+ fields: {
272
+ quantity: {
273
+ minimum: 1
274
+ }
275
+ }
276
+ },
277
+ "plans.billingControls.autoTopups.purchaseLimit": {
278
+ required: ["interval", "limit"],
279
+ fields: {
280
+ interval: {
281
+ enum: ["hour", "day", "week", "month"]
282
+ },
283
+ intervalCount: {
284
+ minimum: 1
285
+ },
286
+ limit: {
287
+ minimum: 1
288
+ },
289
+ count: {
290
+ minimum: 0
291
+ }
292
+ }
293
+ },
294
+ "plans.billingControls.overageAllowed": {
295
+ required: ["featureId"]
296
+ },
297
+ "plans.billingControls.spendLimits": {
298
+ fields: {
299
+ limitType: {
300
+ enum: ["absolute", "usage_percentage"]
301
+ },
302
+ overageLimit: {
303
+ minimum: 0
304
+ }
305
+ }
306
+ },
307
+ "plans.billingControls.usageAlerts": {
308
+ required: ["threshold", "thresholdType"],
309
+ fields: {
310
+ threshold: {
311
+ minimum: 0
312
+ },
313
+ thresholdType: {
314
+ enum: [
315
+ "usage",
316
+ "usage_percentage",
317
+ "remaining",
318
+ "remaining_percentage"
319
+ ]
320
+ },
321
+ basis: {
322
+ enum: ["balance", "included", "recurring", "usage_limit"]
323
+ }
324
+ }
325
+ },
326
+ "plans.billingControls.usageAlerts.filter": {
327
+ required: ["properties"]
328
+ },
329
+ "plans.billingControls.usageAlerts.filter.properties": {
330
+ keys: {
331
+ minLength: 1,
332
+ maxLength: 64
333
+ }
334
+ },
335
+ "plans.billingControls.usageLimits": {
336
+ required: ["featureId", "interval", "limit"],
337
+ fields: {
338
+ limit: {
339
+ minimum: 0
340
+ },
341
+ interval: {
342
+ enum: ["day", "week", "month", "year"]
343
+ },
344
+ anchor: {
345
+ enum: ["billing_cycle", "utc"]
346
+ }
347
+ }
348
+ },
349
+ "plans.billingControls.usageLimits.filter": {
350
+ required: ["properties"]
351
+ },
352
+ "plans.billingControls.usageLimits.filter.properties": {
353
+ keys: {
354
+ minLength: 1,
355
+ maxLength: 64
356
+ }
357
+ },
358
+ "plans.freeTrial": {
359
+ required: ["durationLength"],
360
+ fields: {
361
+ durationType: {
362
+ enum: ["day", "month", "year"]
363
+ },
364
+ onEnd: {
365
+ enum: ["bill", "revert"]
366
+ }
367
+ }
368
+ },
369
+ "plans.items": {
370
+ label: "item",
371
+ idField: "featureId",
372
+ required: ["featureId"],
373
+ fields: {
374
+ included: {
375
+ maximum: 10000000000000
376
+ }
377
+ },
378
+ rules: [
379
+ {
380
+ kind: "exists",
381
+ field: "featureId",
382
+ in: "features",
383
+ matching: "featureId",
384
+ because: "A plan item meters a feature this config does not declare."
385
+ },
386
+ {
387
+ kind: "targetHas",
388
+ when: "featureOverride",
389
+ field: "featureId",
390
+ in: "features",
391
+ matching: "featureId",
392
+ target: "type",
393
+ equals: "credit_system",
394
+ because: "featureOverride is only honoured on classic credit-system features."
395
+ },
396
+ {
397
+ kind: "targetLacks",
398
+ field: "featureId",
399
+ in: "features",
400
+ matching: "featureId",
401
+ target: "archived",
402
+ label: "Feature",
403
+ parentGuard: "archived",
404
+ parentIdField: "planId",
405
+ parentLabel: "plan",
406
+ because: "An archived feature should not gain new customers through a live plan."
407
+ }
408
+ ]
409
+ },
410
+ "plans.items.featureOverride.creditSchema": {
411
+ variants: {
412
+ on: "tierBehavior",
413
+ byValue: {
414
+ graduated: {
415
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
416
+ fields: {
417
+ meteredFeatureId: {
418
+ minLength: 1
419
+ },
420
+ billingUnits: {
421
+ exclusiveMinimum: 0
422
+ },
423
+ tierBehavior: {
424
+ enum: ["graduated"]
425
+ },
426
+ tiers: {
427
+ minItems: 1
428
+ }
429
+ }
430
+ }
431
+ },
432
+ fallback: {
433
+ required: ["creditCost", "meteredFeatureId"],
434
+ fields: {
435
+ meteredFeatureId: {
436
+ minLength: 1
437
+ },
438
+ billingUnits: {
439
+ exclusiveMinimum: 0
440
+ },
441
+ creditCost: {
442
+ minimum: 0
443
+ }
444
+ }
445
+ }
446
+ }
447
+ },
448
+ "plans.items.featureOverride.creditSchema.dimensions": {
449
+ keys: {
450
+ minLength: 1,
451
+ maxLength: 64
452
+ }
453
+ },
454
+ "plans.items.featureOverride.creditSchema.dimensions.*": {
455
+ variants: {
456
+ on: "tierBehavior",
457
+ byValue: {
458
+ graduated: {
459
+ required: ["match", "tierBehavior", "tiers"],
460
+ fields: {
461
+ priority: {
462
+ minimum: -9007199254740991,
463
+ maximum: 9007199254740991
464
+ },
465
+ tierBehavior: {
466
+ enum: ["graduated"]
467
+ },
468
+ tiers: {
469
+ minItems: 1
470
+ }
471
+ }
472
+ }
473
+ },
474
+ fallback: {
475
+ required: ["creditCost", "match"],
476
+ fields: {
477
+ priority: {
478
+ minimum: -9007199254740991,
479
+ maximum: 9007199254740991
480
+ },
481
+ creditCost: {
482
+ minimum: 0
483
+ }
484
+ }
485
+ }
486
+ }
487
+ },
488
+ "plans.items.featureOverride.creditSchema.dimensions.*.tiers": {
489
+ required: ["creditCost", "to"],
490
+ fields: {
491
+ to: {
492
+ exclusiveMinimum: 0
493
+ },
494
+ creditCost: {
495
+ minimum: 0
496
+ }
497
+ }
498
+ },
499
+ "plans.items.featureOverride.creditSchema.multipliers": {
500
+ keys: {
501
+ minLength: 1,
502
+ maxLength: 64
503
+ }
504
+ },
505
+ "plans.items.featureOverride.creditSchema.multipliers.*": {
506
+ required: ["match"],
507
+ fields: {
508
+ factor: {
509
+ exclusiveMinimum: 0
510
+ }
511
+ }
512
+ },
513
+ "plans.items.featureOverride.creditSchema.tiers": {
514
+ required: ["creditCost", "to"],
515
+ fields: {
516
+ to: {
517
+ exclusiveMinimum: 0
518
+ },
519
+ creditCost: {
520
+ minimum: 0
521
+ }
522
+ }
523
+ },
524
+ "plans.items.featureOverride.markups": {
525
+ fields: {
526
+ defaultMarkup: {
527
+ minimum: -100
528
+ }
529
+ }
530
+ },
531
+ "plans.items.featureOverride.markups.modelMarkups": {
532
+ keys: {
533
+ pattern: ".+\\/.+"
534
+ }
535
+ },
536
+ "plans.items.featureOverride.markups.modelMarkups.*": {
537
+ fields: {
538
+ markup: {
539
+ minimum: -100
540
+ },
541
+ inputCost: {
542
+ minimum: 0
543
+ },
544
+ outputCost: {
545
+ minimum: 0
546
+ }
547
+ }
548
+ },
549
+ "plans.items.featureOverride.markups.providerMarkups.*": {
550
+ required: ["markup"],
551
+ fields: {
552
+ markup: {
553
+ minimum: -100
554
+ }
555
+ }
556
+ },
557
+ "plans.items.price": {
558
+ label: "price",
559
+ required: ["billingMethod", "interval"],
560
+ fields: {
561
+ tierBehavior: {
562
+ enum: ["graduated", "volume"]
563
+ },
564
+ interval: {
565
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
566
+ },
567
+ billingMethod: {
568
+ enum: ["prepaid", "usage_based"]
569
+ },
570
+ allocatedBilling: {
571
+ enum: ["arrear", "prorated_legacy"]
572
+ }
573
+ },
574
+ rules: [
575
+ {
576
+ kind: "valueWhen",
577
+ when: "tierBehavior",
578
+ equals: "volume",
579
+ field: "billingMethod",
580
+ mustBe: "prepaid",
581
+ because: "Volume tiers are prepaid-only."
582
+ }
583
+ ]
584
+ },
585
+ "plans.items.price.additionalCurrencies": {
586
+ required: ["amount", "currency"]
587
+ },
588
+ "plans.items.price.processors.stripe": {
589
+ required: ["priceId"]
590
+ },
591
+ "plans.items.price.tiers": {
592
+ required: ["to"]
593
+ },
594
+ "plans.items.price.tiers.additionalCurrencies": {
595
+ required: ["currency"]
596
+ },
597
+ "plans.items.proration": {
598
+ required: ["onDecrease", "onIncrease"],
599
+ fields: {
600
+ onIncrease: {
601
+ enum: [
602
+ "bill_immediately",
603
+ "prorate_immediately",
604
+ "prorate_next_cycle",
605
+ "bill_next_cycle"
606
+ ]
607
+ },
608
+ onDecrease: {
609
+ enum: [
610
+ "prorate",
611
+ "prorate_immediately",
612
+ "prorate_next_cycle",
613
+ "none",
614
+ "no_prorations"
615
+ ]
616
+ }
617
+ }
618
+ },
619
+ "plans.items.reset": {
620
+ required: ["interval"],
621
+ fields: {
622
+ interval: {
623
+ enum: [
624
+ "one_off",
625
+ "minute",
626
+ "hour",
627
+ "day",
628
+ "week",
629
+ "month",
630
+ "quarter",
631
+ "semi_annual",
632
+ "year"
633
+ ]
634
+ }
635
+ }
636
+ },
637
+ "plans.items.rollover": {
638
+ required: ["expiryDurationType"],
639
+ fields: {
640
+ expiryDurationType: {
641
+ enum: ["month", "forever"]
642
+ }
643
+ }
644
+ },
645
+ "plans.items.thresholdBilling": {
646
+ required: ["threshold"],
647
+ fields: {
648
+ threshold: {
649
+ exclusiveMinimum: 0
650
+ }
651
+ }
652
+ },
653
+ "plans.licenses": {
654
+ label: "license",
655
+ idField: "licensePlanId",
656
+ required: ["licensePlanId", "versionSlug"],
657
+ fields: {
658
+ included: {
659
+ minimum: 0,
660
+ maximum: 9007199254740991
661
+ }
662
+ }
663
+ },
664
+ "plans.licenses.customize.addItems": {
665
+ required: ["featureId"],
666
+ fields: {
667
+ included: {
668
+ maximum: 10000000000000
669
+ }
670
+ }
671
+ },
672
+ "plans.licenses.customize.addItems.featureOverride.creditSchema": {
673
+ variants: {
674
+ on: "tierBehavior",
675
+ byValue: {
676
+ graduated: {
677
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
678
+ fields: {
679
+ meteredFeatureId: {
680
+ minLength: 1
681
+ },
682
+ billingUnits: {
683
+ exclusiveMinimum: 0
684
+ },
685
+ tierBehavior: {
686
+ enum: ["graduated"]
687
+ },
688
+ tiers: {
689
+ minItems: 1
690
+ }
691
+ }
692
+ }
693
+ },
694
+ fallback: {
695
+ required: ["creditCost", "meteredFeatureId"],
696
+ fields: {
697
+ meteredFeatureId: {
698
+ minLength: 1
699
+ },
700
+ billingUnits: {
701
+ exclusiveMinimum: 0
702
+ },
703
+ creditCost: {
704
+ minimum: 0
705
+ }
706
+ }
707
+ }
708
+ }
709
+ },
710
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.dimensions": {
711
+ keys: {
712
+ minLength: 1,
713
+ maxLength: 64
714
+ }
715
+ },
716
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.dimensions.*": {
717
+ variants: {
718
+ on: "tierBehavior",
719
+ byValue: {
720
+ graduated: {
721
+ required: ["match", "tierBehavior", "tiers"],
722
+ fields: {
723
+ priority: {
724
+ minimum: -9007199254740991,
725
+ maximum: 9007199254740991
726
+ },
727
+ tierBehavior: {
728
+ enum: ["graduated"]
729
+ },
730
+ tiers: {
731
+ minItems: 1
732
+ }
733
+ }
734
+ }
735
+ },
736
+ fallback: {
737
+ required: ["creditCost", "match"],
738
+ fields: {
739
+ priority: {
740
+ minimum: -9007199254740991,
741
+ maximum: 9007199254740991
742
+ },
743
+ creditCost: {
744
+ minimum: 0
745
+ }
746
+ }
747
+ }
748
+ }
749
+ },
750
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.dimensions.*.tiers": {
751
+ required: ["creditCost", "to"],
752
+ fields: {
753
+ to: {
754
+ exclusiveMinimum: 0
755
+ },
756
+ creditCost: {
757
+ minimum: 0
758
+ }
759
+ }
760
+ },
761
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.multipliers": {
762
+ keys: {
763
+ minLength: 1,
764
+ maxLength: 64
765
+ }
766
+ },
767
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.multipliers.*": {
768
+ required: ["match"],
769
+ fields: {
770
+ factor: {
771
+ exclusiveMinimum: 0
772
+ }
773
+ }
774
+ },
775
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.tiers": {
776
+ required: ["creditCost", "to"],
777
+ fields: {
778
+ to: {
779
+ exclusiveMinimum: 0
780
+ },
781
+ creditCost: {
782
+ minimum: 0
783
+ }
784
+ }
785
+ },
786
+ "plans.licenses.customize.addItems.featureOverride.markups": {
787
+ fields: {
788
+ defaultMarkup: {
789
+ minimum: -100
790
+ }
791
+ }
792
+ },
793
+ "plans.licenses.customize.addItems.featureOverride.markups.modelMarkups": {
794
+ keys: {
795
+ pattern: ".+\\/.+"
796
+ }
797
+ },
798
+ "plans.licenses.customize.addItems.featureOverride.markups.modelMarkups.*": {
799
+ fields: {
800
+ markup: {
801
+ minimum: -100
802
+ },
803
+ inputCost: {
804
+ minimum: 0
805
+ },
806
+ outputCost: {
807
+ minimum: 0
808
+ }
809
+ }
810
+ },
811
+ "plans.licenses.customize.addItems.featureOverride.markups.providerMarkups.*": {
812
+ required: ["markup"],
813
+ fields: {
814
+ markup: {
815
+ minimum: -100
816
+ }
817
+ }
818
+ },
819
+ "plans.licenses.customize.addItems.price": {
820
+ required: ["billingMethod", "interval"],
821
+ fields: {
822
+ tierBehavior: {
823
+ enum: ["graduated", "volume"]
824
+ },
825
+ interval: {
826
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
827
+ },
828
+ billingMethod: {
829
+ enum: ["prepaid", "usage_based"]
830
+ },
831
+ allocatedBilling: {
832
+ enum: ["arrear", "prorated_legacy"]
833
+ }
834
+ }
835
+ },
836
+ "plans.licenses.customize.addItems.price.additionalCurrencies": {
837
+ required: ["amount", "currency"]
838
+ },
839
+ "plans.licenses.customize.addItems.price.tiers": {
840
+ required: ["to"]
841
+ },
842
+ "plans.licenses.customize.addItems.price.tiers.additionalCurrencies": {
843
+ required: ["currency"]
844
+ },
845
+ "plans.licenses.customize.addItems.proration": {
846
+ required: ["onDecrease", "onIncrease"],
847
+ fields: {
848
+ onIncrease: {
849
+ enum: [
850
+ "bill_immediately",
851
+ "prorate_immediately",
852
+ "prorate_next_cycle",
853
+ "bill_next_cycle"
854
+ ]
855
+ },
856
+ onDecrease: {
857
+ enum: [
858
+ "prorate",
859
+ "prorate_immediately",
860
+ "prorate_next_cycle",
861
+ "none",
862
+ "no_prorations"
863
+ ]
864
+ }
865
+ }
866
+ },
867
+ "plans.licenses.customize.addItems.reset": {
868
+ required: ["interval"],
869
+ fields: {
870
+ interval: {
871
+ enum: [
872
+ "one_off",
873
+ "minute",
874
+ "hour",
875
+ "day",
876
+ "week",
877
+ "month",
878
+ "quarter",
879
+ "semi_annual",
880
+ "year"
881
+ ]
882
+ }
883
+ }
884
+ },
885
+ "plans.licenses.customize.addItems.rollover": {
886
+ required: ["expiryDurationType"],
887
+ fields: {
888
+ expiryDurationType: {
889
+ enum: ["month", "forever"]
890
+ }
891
+ }
892
+ },
893
+ "plans.licenses.customize.addItems.thresholdBilling": {
894
+ required: ["threshold"],
895
+ fields: {
896
+ threshold: {
897
+ exclusiveMinimum: 0
898
+ }
899
+ }
900
+ },
901
+ "plans.licenses.customize.price": {
902
+ required: ["amount", "interval"],
903
+ fields: {
904
+ interval: {
905
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
906
+ }
907
+ }
908
+ },
909
+ "plans.licenses.customize.price.additionalCurrencies": {
910
+ required: ["amount", "currency"]
911
+ },
912
+ "plans.licenses.customize.removeItems": {
913
+ fields: {
914
+ billingMethod: {
915
+ enum: ["prepaid", "usage_based"]
916
+ },
917
+ interval: {
918
+ enum: [
919
+ "one_off",
920
+ "week",
921
+ "month",
922
+ "quarter",
923
+ "semi_annual",
924
+ "year",
925
+ "minute",
926
+ "hour",
927
+ "day"
928
+ ]
929
+ },
930
+ intervalCount: {
931
+ minimum: -9007199254740991,
932
+ maximum: 9007199254740991,
933
+ exclusiveMinimum: 0
934
+ },
935
+ included: {
936
+ maximum: 10000000000000
937
+ }
938
+ }
939
+ },
940
+ "plans.price": {
941
+ required: ["amount", "interval"],
942
+ fields: {
943
+ interval: {
944
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
945
+ }
946
+ }
947
+ },
948
+ "plans.price.additionalCurrencies": {
949
+ required: ["amount", "currency"]
950
+ },
951
+ "plans.price.processors.stripe": {
952
+ required: ["priceId"]
953
+ },
954
+ "plans.processors.revenuecat": {
955
+ required: ["products"]
956
+ },
957
+ "plans.processors.revenuecat.products": {
958
+ required: ["productId"]
959
+ },
960
+ "plans.processors.revenuecat.products.featureQuantities": {
961
+ required: ["featureId"],
962
+ fields: {
963
+ quantity: {
964
+ minimum: 0
965
+ }
966
+ }
967
+ },
968
+ "plans.processors.stripe": {
969
+ required: ["productId"]
970
+ },
971
+ "plans.propagate.licenseParents": {
972
+ required: ["planId"],
973
+ fields: {
974
+ planId: {
975
+ minLength: 1,
976
+ pattern: "^[a-zA-Z0-9_-]+$"
977
+ },
978
+ version: {
979
+ minimum: 1,
980
+ maximum: 9007199254740991
981
+ },
982
+ versionSlug: {
983
+ minLength: 1,
984
+ pattern: "^[a-zA-Z0-9_-]+$"
985
+ },
986
+ newVersionSlug: {
987
+ minLength: 1,
988
+ pattern: "^[a-zA-Z0-9_-]+$"
989
+ }
990
+ }
991
+ },
992
+ "plans.propagate.variants": {
993
+ required: ["planId"],
994
+ fields: {
995
+ planId: {
996
+ minLength: 1,
997
+ pattern: "^[a-zA-Z0-9_-]+$"
998
+ },
999
+ version: {
1000
+ minimum: 1,
1001
+ maximum: 9007199254740991
1002
+ },
1003
+ versionSlug: {
1004
+ minLength: 1,
1005
+ pattern: "^[a-zA-Z0-9_-]+$"
1006
+ },
1007
+ newVersionSlug: {
1008
+ minLength: 1,
1009
+ pattern: "^[a-zA-Z0-9_-]+$"
1010
+ }
1011
+ }
1012
+ },
1013
+ "plans.variants": {
1014
+ label: "variant",
1015
+ idField: "variantPlanId",
1016
+ required: ["variantPlanId", "versionSlug"],
1017
+ fields: {
1018
+ variantPlanId: {
1019
+ minLength: 1,
1020
+ pattern: "^[a-zA-Z0-9_-]+$"
1021
+ },
1022
+ internalId: {
1023
+ minLength: 1
1024
+ },
1025
+ version: {
1026
+ minimum: 1,
1027
+ maximum: 9007199254740991
1028
+ },
1029
+ versionSlug: {
1030
+ minLength: 1,
1031
+ pattern: "^[a-zA-Z0-9_-]+$"
1032
+ },
1033
+ name: {
1034
+ minLength: 1
1035
+ },
1036
+ newPlanId: {
1037
+ minLength: 1,
1038
+ pattern: "^[a-zA-Z0-9_-]+$"
1039
+ },
1040
+ newVersionSlug: {
1041
+ minLength: 1,
1042
+ pattern: "^[a-zA-Z0-9_-]+$"
1043
+ },
1044
+ baseVariantId: {
1045
+ minLength: 1,
1046
+ pattern: "^[a-zA-Z0-9_-]+$"
1047
+ }
1048
+ }
1049
+ },
1050
+ "plans.variants.customize.addItems": {
1051
+ required: ["featureId"],
1052
+ fields: {
1053
+ included: {
1054
+ maximum: 10000000000000
1055
+ }
1056
+ }
1057
+ },
1058
+ "plans.variants.customize.addItems.featureOverride.creditSchema": {
1059
+ variants: {
1060
+ on: "tierBehavior",
1061
+ byValue: {
1062
+ graduated: {
1063
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
1064
+ fields: {
1065
+ meteredFeatureId: {
1066
+ minLength: 1
1067
+ },
1068
+ billingUnits: {
1069
+ exclusiveMinimum: 0
1070
+ },
1071
+ tierBehavior: {
1072
+ enum: ["graduated"]
1073
+ },
1074
+ tiers: {
1075
+ minItems: 1
1076
+ }
1077
+ }
1078
+ }
1079
+ },
1080
+ fallback: {
1081
+ required: ["creditCost", "meteredFeatureId"],
1082
+ fields: {
1083
+ meteredFeatureId: {
1084
+ minLength: 1
1085
+ },
1086
+ billingUnits: {
1087
+ exclusiveMinimum: 0
1088
+ },
1089
+ creditCost: {
1090
+ minimum: 0
1091
+ }
1092
+ }
1093
+ }
1094
+ }
1095
+ },
1096
+ "plans.variants.customize.addItems.featureOverride.creditSchema.dimensions": {
1097
+ keys: {
1098
+ minLength: 1,
1099
+ maxLength: 64
1100
+ }
1101
+ },
1102
+ "plans.variants.customize.addItems.featureOverride.creditSchema.dimensions.*": {
1103
+ variants: {
1104
+ on: "tierBehavior",
1105
+ byValue: {
1106
+ graduated: {
1107
+ required: ["match", "tierBehavior", "tiers"],
1108
+ fields: {
1109
+ priority: {
1110
+ minimum: -9007199254740991,
1111
+ maximum: 9007199254740991
1112
+ },
1113
+ tierBehavior: {
1114
+ enum: ["graduated"]
1115
+ },
1116
+ tiers: {
1117
+ minItems: 1
1118
+ }
1119
+ }
1120
+ }
1121
+ },
1122
+ fallback: {
1123
+ required: ["creditCost", "match"],
1124
+ fields: {
1125
+ priority: {
1126
+ minimum: -9007199254740991,
1127
+ maximum: 9007199254740991
1128
+ },
1129
+ creditCost: {
1130
+ minimum: 0
1131
+ }
1132
+ }
1133
+ }
1134
+ }
1135
+ },
1136
+ "plans.variants.customize.addItems.featureOverride.creditSchema.dimensions.*.tiers": {
1137
+ required: ["creditCost", "to"],
1138
+ fields: {
1139
+ to: {
1140
+ exclusiveMinimum: 0
1141
+ },
1142
+ creditCost: {
1143
+ minimum: 0
1144
+ }
1145
+ }
1146
+ },
1147
+ "plans.variants.customize.addItems.featureOverride.creditSchema.multipliers": {
1148
+ keys: {
1149
+ minLength: 1,
1150
+ maxLength: 64
1151
+ }
1152
+ },
1153
+ "plans.variants.customize.addItems.featureOverride.creditSchema.multipliers.*": {
1154
+ required: ["match"],
1155
+ fields: {
1156
+ factor: {
1157
+ exclusiveMinimum: 0
1158
+ }
1159
+ }
1160
+ },
1161
+ "plans.variants.customize.addItems.featureOverride.creditSchema.tiers": {
1162
+ required: ["creditCost", "to"],
1163
+ fields: {
1164
+ to: {
1165
+ exclusiveMinimum: 0
1166
+ },
1167
+ creditCost: {
1168
+ minimum: 0
1169
+ }
1170
+ }
1171
+ },
1172
+ "plans.variants.customize.addItems.featureOverride.markups": {
1173
+ fields: {
1174
+ defaultMarkup: {
1175
+ minimum: -100
1176
+ }
1177
+ }
1178
+ },
1179
+ "plans.variants.customize.addItems.featureOverride.markups.modelMarkups": {
1180
+ keys: {
1181
+ pattern: ".+\\/.+"
1182
+ }
1183
+ },
1184
+ "plans.variants.customize.addItems.featureOverride.markups.modelMarkups.*": {
1185
+ fields: {
1186
+ markup: {
1187
+ minimum: -100
1188
+ },
1189
+ inputCost: {
1190
+ minimum: 0
1191
+ },
1192
+ outputCost: {
1193
+ minimum: 0
1194
+ }
1195
+ }
1196
+ },
1197
+ "plans.variants.customize.addItems.featureOverride.markups.providerMarkups.*": {
1198
+ required: ["markup"],
1199
+ fields: {
1200
+ markup: {
1201
+ minimum: -100
1202
+ }
1203
+ }
1204
+ },
1205
+ "plans.variants.customize.addItems.price": {
1206
+ required: ["billingMethod", "interval"],
1207
+ fields: {
1208
+ tierBehavior: {
1209
+ enum: ["graduated", "volume"]
1210
+ },
1211
+ interval: {
1212
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
1213
+ },
1214
+ billingMethod: {
1215
+ enum: ["prepaid", "usage_based"]
1216
+ },
1217
+ allocatedBilling: {
1218
+ enum: ["arrear", "prorated_legacy"]
1219
+ }
1220
+ }
1221
+ },
1222
+ "plans.variants.customize.addItems.price.additionalCurrencies": {
1223
+ required: ["amount", "currency"]
1224
+ },
1225
+ "plans.variants.customize.addItems.price.tiers": {
1226
+ required: ["to"]
1227
+ },
1228
+ "plans.variants.customize.addItems.price.tiers.additionalCurrencies": {
1229
+ required: ["currency"]
1230
+ },
1231
+ "plans.variants.customize.addItems.proration": {
1232
+ required: ["onDecrease", "onIncrease"],
1233
+ fields: {
1234
+ onIncrease: {
1235
+ enum: [
1236
+ "bill_immediately",
1237
+ "prorate_immediately",
1238
+ "prorate_next_cycle",
1239
+ "bill_next_cycle"
1240
+ ]
1241
+ },
1242
+ onDecrease: {
1243
+ enum: [
1244
+ "prorate",
1245
+ "prorate_immediately",
1246
+ "prorate_next_cycle",
1247
+ "none",
1248
+ "no_prorations"
1249
+ ]
1250
+ }
1251
+ }
1252
+ },
1253
+ "plans.variants.customize.addItems.reset": {
1254
+ required: ["interval"],
1255
+ fields: {
1256
+ interval: {
1257
+ enum: [
1258
+ "one_off",
1259
+ "minute",
1260
+ "hour",
1261
+ "day",
1262
+ "week",
1263
+ "month",
1264
+ "quarter",
1265
+ "semi_annual",
1266
+ "year"
1267
+ ]
1268
+ }
1269
+ }
1270
+ },
1271
+ "plans.variants.customize.addItems.rollover": {
1272
+ required: ["expiryDurationType"],
1273
+ fields: {
1274
+ expiryDurationType: {
1275
+ enum: ["month", "forever"]
1276
+ }
1277
+ }
1278
+ },
1279
+ "plans.variants.customize.addItems.thresholdBilling": {
1280
+ required: ["threshold"],
1281
+ fields: {
1282
+ threshold: {
1283
+ exclusiveMinimum: 0
1284
+ }
1285
+ }
1286
+ },
1287
+ "plans.variants.customize.billingControls.autoTopups": {
1288
+ required: ["featureId", "quantity", "threshold"],
1289
+ fields: {
1290
+ quantity: {
1291
+ minimum: 1
1292
+ }
1293
+ }
1294
+ },
1295
+ "plans.variants.customize.billingControls.autoTopups.purchaseLimit": {
1296
+ required: ["interval", "limit"],
1297
+ fields: {
1298
+ interval: {
1299
+ enum: ["hour", "day", "week", "month"]
1300
+ },
1301
+ intervalCount: {
1302
+ minimum: 1
1303
+ },
1304
+ limit: {
1305
+ minimum: 1
1306
+ },
1307
+ count: {
1308
+ minimum: 0
1309
+ }
1310
+ }
1311
+ },
1312
+ "plans.variants.customize.billingControls.overageAllowed": {
1313
+ required: ["featureId"]
1314
+ },
1315
+ "plans.variants.customize.billingControls.spendLimits": {
1316
+ fields: {
1317
+ limitType: {
1318
+ enum: ["absolute", "usage_percentage"]
1319
+ },
1320
+ overageLimit: {
1321
+ minimum: 0
1322
+ }
1323
+ }
1324
+ },
1325
+ "plans.variants.customize.billingControls.usageAlerts": {
1326
+ required: ["threshold", "thresholdType"],
1327
+ fields: {
1328
+ threshold: {
1329
+ minimum: 0
1330
+ },
1331
+ thresholdType: {
1332
+ enum: [
1333
+ "usage",
1334
+ "usage_percentage",
1335
+ "remaining",
1336
+ "remaining_percentage"
1337
+ ]
1338
+ },
1339
+ basis: {
1340
+ enum: ["balance", "included", "recurring", "usage_limit"]
1341
+ }
1342
+ }
1343
+ },
1344
+ "plans.variants.customize.billingControls.usageAlerts.filter": {
1345
+ required: ["properties"]
1346
+ },
1347
+ "plans.variants.customize.billingControls.usageAlerts.filter.properties": {
1348
+ keys: {
1349
+ minLength: 1,
1350
+ maxLength: 64
1351
+ }
1352
+ },
1353
+ "plans.variants.customize.billingControls.usageLimits": {
1354
+ required: ["featureId", "interval", "limit"],
1355
+ fields: {
1356
+ limit: {
1357
+ minimum: 0
1358
+ },
1359
+ interval: {
1360
+ enum: ["day", "week", "month", "year"]
1361
+ },
1362
+ anchor: {
1363
+ enum: ["billing_cycle", "utc"]
1364
+ }
1365
+ }
1366
+ },
1367
+ "plans.variants.customize.billingControls.usageLimits.filter": {
1368
+ required: ["properties"]
1369
+ },
1370
+ "plans.variants.customize.billingControls.usageLimits.filter.properties": {
1371
+ keys: {
1372
+ minLength: 1,
1373
+ maxLength: 64
1374
+ }
1375
+ },
1376
+ "plans.variants.customize.freeTrial": {
1377
+ required: ["durationLength"],
1378
+ fields: {
1379
+ durationType: {
1380
+ enum: ["day", "month", "year"]
1381
+ },
1382
+ onEnd: {
1383
+ enum: ["bill", "revert"]
1384
+ }
1385
+ }
1386
+ },
1387
+ "plans.variants.customize.items": {
1388
+ required: ["featureId"],
1389
+ fields: {
1390
+ included: {
1391
+ maximum: 10000000000000
1392
+ }
1393
+ }
1394
+ },
1395
+ "plans.variants.customize.items.featureOverride.creditSchema": {
1396
+ variants: {
1397
+ on: "tierBehavior",
1398
+ byValue: {
1399
+ graduated: {
1400
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
1401
+ fields: {
1402
+ meteredFeatureId: {
1403
+ minLength: 1
1404
+ },
1405
+ billingUnits: {
1406
+ exclusiveMinimum: 0
1407
+ },
1408
+ tierBehavior: {
1409
+ enum: ["graduated"]
1410
+ },
1411
+ tiers: {
1412
+ minItems: 1
1413
+ }
1414
+ }
1415
+ }
1416
+ },
1417
+ fallback: {
1418
+ required: ["creditCost", "meteredFeatureId"],
1419
+ fields: {
1420
+ meteredFeatureId: {
1421
+ minLength: 1
1422
+ },
1423
+ billingUnits: {
1424
+ exclusiveMinimum: 0
1425
+ },
1426
+ creditCost: {
1427
+ minimum: 0
1428
+ }
1429
+ }
1430
+ }
1431
+ }
1432
+ },
1433
+ "plans.variants.customize.items.featureOverride.creditSchema.dimensions": {
1434
+ keys: {
1435
+ minLength: 1,
1436
+ maxLength: 64
1437
+ }
1438
+ },
1439
+ "plans.variants.customize.items.featureOverride.creditSchema.dimensions.*": {
1440
+ variants: {
1441
+ on: "tierBehavior",
1442
+ byValue: {
1443
+ graduated: {
1444
+ required: ["match", "tierBehavior", "tiers"],
1445
+ fields: {
1446
+ priority: {
1447
+ minimum: -9007199254740991,
1448
+ maximum: 9007199254740991
1449
+ },
1450
+ tierBehavior: {
1451
+ enum: ["graduated"]
1452
+ },
1453
+ tiers: {
1454
+ minItems: 1
1455
+ }
1456
+ }
1457
+ }
1458
+ },
1459
+ fallback: {
1460
+ required: ["creditCost", "match"],
1461
+ fields: {
1462
+ priority: {
1463
+ minimum: -9007199254740991,
1464
+ maximum: 9007199254740991
1465
+ },
1466
+ creditCost: {
1467
+ minimum: 0
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+ },
1473
+ "plans.variants.customize.items.featureOverride.creditSchema.dimensions.*.tiers": {
1474
+ required: ["creditCost", "to"],
1475
+ fields: {
1476
+ to: {
1477
+ exclusiveMinimum: 0
1478
+ },
1479
+ creditCost: {
1480
+ minimum: 0
1481
+ }
1482
+ }
1483
+ },
1484
+ "plans.variants.customize.items.featureOverride.creditSchema.multipliers": {
1485
+ keys: {
1486
+ minLength: 1,
1487
+ maxLength: 64
1488
+ }
1489
+ },
1490
+ "plans.variants.customize.items.featureOverride.creditSchema.multipliers.*": {
1491
+ required: ["match"],
1492
+ fields: {
1493
+ factor: {
1494
+ exclusiveMinimum: 0
1495
+ }
1496
+ }
1497
+ },
1498
+ "plans.variants.customize.items.featureOverride.creditSchema.tiers": {
1499
+ required: ["creditCost", "to"],
1500
+ fields: {
1501
+ to: {
1502
+ exclusiveMinimum: 0
1503
+ },
1504
+ creditCost: {
1505
+ minimum: 0
1506
+ }
1507
+ }
1508
+ },
1509
+ "plans.variants.customize.items.featureOverride.markups": {
1510
+ fields: {
1511
+ defaultMarkup: {
1512
+ minimum: -100
1513
+ }
1514
+ }
1515
+ },
1516
+ "plans.variants.customize.items.featureOverride.markups.modelMarkups": {
1517
+ keys: {
1518
+ pattern: ".+\\/.+"
1519
+ }
1520
+ },
1521
+ "plans.variants.customize.items.featureOverride.markups.modelMarkups.*": {
1522
+ fields: {
1523
+ markup: {
1524
+ minimum: -100
1525
+ },
1526
+ inputCost: {
1527
+ minimum: 0
1528
+ },
1529
+ outputCost: {
1530
+ minimum: 0
1531
+ }
1532
+ }
1533
+ },
1534
+ "plans.variants.customize.items.featureOverride.markups.providerMarkups.*": {
1535
+ required: ["markup"],
1536
+ fields: {
1537
+ markup: {
1538
+ minimum: -100
1539
+ }
1540
+ }
1541
+ },
1542
+ "plans.variants.customize.items.price": {
1543
+ required: ["billingMethod", "interval"],
1544
+ fields: {
1545
+ tierBehavior: {
1546
+ enum: ["graduated", "volume"]
1547
+ },
1548
+ interval: {
1549
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
1550
+ },
1551
+ billingMethod: {
1552
+ enum: ["prepaid", "usage_based"]
1553
+ },
1554
+ allocatedBilling: {
1555
+ enum: ["arrear", "prorated_legacy"]
1556
+ }
1557
+ }
1558
+ },
1559
+ "plans.variants.customize.items.price.additionalCurrencies": {
1560
+ required: ["amount", "currency"]
1561
+ },
1562
+ "plans.variants.customize.items.price.tiers": {
1563
+ required: ["to"]
1564
+ },
1565
+ "plans.variants.customize.items.price.tiers.additionalCurrencies": {
1566
+ required: ["currency"]
1567
+ },
1568
+ "plans.variants.customize.items.proration": {
1569
+ required: ["onDecrease", "onIncrease"],
1570
+ fields: {
1571
+ onIncrease: {
1572
+ enum: [
1573
+ "bill_immediately",
1574
+ "prorate_immediately",
1575
+ "prorate_next_cycle",
1576
+ "bill_next_cycle"
1577
+ ]
1578
+ },
1579
+ onDecrease: {
1580
+ enum: [
1581
+ "prorate",
1582
+ "prorate_immediately",
1583
+ "prorate_next_cycle",
1584
+ "none",
1585
+ "no_prorations"
1586
+ ]
1587
+ }
1588
+ }
1589
+ },
1590
+ "plans.variants.customize.items.reset": {
1591
+ required: ["interval"],
1592
+ fields: {
1593
+ interval: {
1594
+ enum: [
1595
+ "one_off",
1596
+ "minute",
1597
+ "hour",
1598
+ "day",
1599
+ "week",
1600
+ "month",
1601
+ "quarter",
1602
+ "semi_annual",
1603
+ "year"
1604
+ ]
1605
+ }
1606
+ }
1607
+ },
1608
+ "plans.variants.customize.items.rollover": {
1609
+ required: ["expiryDurationType"],
1610
+ fields: {
1611
+ expiryDurationType: {
1612
+ enum: ["month", "forever"]
1613
+ }
1614
+ }
1615
+ },
1616
+ "plans.variants.customize.items.thresholdBilling": {
1617
+ required: ["threshold"],
1618
+ fields: {
1619
+ threshold: {
1620
+ exclusiveMinimum: 0
1621
+ }
1622
+ }
1623
+ },
1624
+ "plans.variants.customize.price": {
1625
+ required: ["amount", "interval"],
1626
+ fields: {
1627
+ interval: {
1628
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
1629
+ }
1630
+ }
1631
+ },
1632
+ "plans.variants.customize.price.additionalCurrencies": {
1633
+ required: ["amount", "currency"]
1634
+ },
1635
+ "plans.variants.customize.removeItems": {
1636
+ fields: {
1637
+ billingMethod: {
1638
+ enum: ["prepaid", "usage_based"]
1639
+ },
1640
+ interval: {
1641
+ enum: [
1642
+ "one_off",
1643
+ "week",
1644
+ "month",
1645
+ "quarter",
1646
+ "semi_annual",
1647
+ "year",
1648
+ "minute",
1649
+ "hour",
1650
+ "day"
1651
+ ]
1652
+ },
1653
+ intervalCount: {
1654
+ minimum: -9007199254740991,
1655
+ maximum: 9007199254740991,
1656
+ exclusiveMinimum: 0
1657
+ },
1658
+ included: {
1659
+ maximum: 10000000000000
1660
+ }
1661
+ }
1662
+ },
1663
+ "plans.variants.customize.removeLicenses": {
1664
+ required: ["licensePlanId"]
1665
+ },
1666
+ "plans.variants.customize.upsertLicenses": {
1667
+ required: ["licensePlanId"],
1668
+ fields: {
1669
+ included: {
1670
+ minimum: 0,
1671
+ maximum: 9007199254740991
1672
+ }
1673
+ }
1674
+ },
1675
+ "plans.variants.customize.upsertLicenses.customize.addItems": {
1676
+ required: ["featureId"],
1677
+ fields: {
1678
+ included: {
1679
+ maximum: 10000000000000
1680
+ }
1681
+ }
1682
+ },
1683
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema": {
1684
+ variants: {
1685
+ on: "tierBehavior",
1686
+ byValue: {
1687
+ graduated: {
1688
+ required: ["meteredFeatureId", "tierBehavior", "tiers"],
1689
+ fields: {
1690
+ meteredFeatureId: {
1691
+ minLength: 1
1692
+ },
1693
+ billingUnits: {
1694
+ exclusiveMinimum: 0
1695
+ },
1696
+ tierBehavior: {
1697
+ enum: ["graduated"]
1698
+ },
1699
+ tiers: {
1700
+ minItems: 1
1701
+ }
1702
+ }
1703
+ }
1704
+ },
1705
+ fallback: {
1706
+ required: ["creditCost", "meteredFeatureId"],
1707
+ fields: {
1708
+ meteredFeatureId: {
1709
+ minLength: 1
1710
+ },
1711
+ billingUnits: {
1712
+ exclusiveMinimum: 0
1713
+ },
1714
+ creditCost: {
1715
+ minimum: 0
1716
+ }
1717
+ }
1718
+ }
1719
+ }
1720
+ },
1721
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.dimensions": {
1722
+ keys: {
1723
+ minLength: 1,
1724
+ maxLength: 64
1725
+ }
1726
+ },
1727
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.dimensions.*": {
1728
+ variants: {
1729
+ on: "tierBehavior",
1730
+ byValue: {
1731
+ graduated: {
1732
+ required: ["match", "tierBehavior", "tiers"],
1733
+ fields: {
1734
+ priority: {
1735
+ minimum: -9007199254740991,
1736
+ maximum: 9007199254740991
1737
+ },
1738
+ tierBehavior: {
1739
+ enum: ["graduated"]
1740
+ },
1741
+ tiers: {
1742
+ minItems: 1
1743
+ }
1744
+ }
1745
+ }
1746
+ },
1747
+ fallback: {
1748
+ required: ["creditCost", "match"],
1749
+ fields: {
1750
+ priority: {
1751
+ minimum: -9007199254740991,
1752
+ maximum: 9007199254740991
1753
+ },
1754
+ creditCost: {
1755
+ minimum: 0
1756
+ }
1757
+ }
1758
+ }
1759
+ }
1760
+ },
1761
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.dimensions.*.tiers": {
1762
+ required: ["creditCost"],
1763
+ fields: {
1764
+ creditCost: {
1765
+ minimum: 0
1766
+ }
1767
+ }
1768
+ },
1769
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.multipliers": {
1770
+ keys: {
1771
+ minLength: 1,
1772
+ maxLength: 64
1773
+ }
1774
+ },
1775
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.multipliers.*": {
1776
+ required: ["match"],
1777
+ fields: {
1778
+ factor: {
1779
+ exclusiveMinimum: 0
1780
+ }
1781
+ }
1782
+ },
1783
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.tiers": {
1784
+ required: ["creditCost", "to"],
1785
+ fields: {
1786
+ to: {
1787
+ exclusiveMinimum: 0
1788
+ },
1789
+ creditCost: {
1790
+ minimum: 0
1791
+ }
1792
+ }
1793
+ },
1794
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups": {
1795
+ fields: {
1796
+ defaultMarkup: {
1797
+ minimum: -100
1798
+ }
1799
+ }
1800
+ },
1801
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups.modelMarkups": {
1802
+ keys: {
1803
+ pattern: ".+\\/.+"
1804
+ }
1805
+ },
1806
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups.modelMarkups.*": {
1807
+ fields: {
1808
+ markup: {
1809
+ minimum: -100
1810
+ },
1811
+ inputCost: {
1812
+ minimum: 0
1813
+ },
1814
+ outputCost: {
1815
+ minimum: 0
1816
+ }
1817
+ }
1818
+ },
1819
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups.providerMarkups.*": {
1820
+ required: ["markup"],
1821
+ fields: {
1822
+ markup: {
1823
+ minimum: -100
1824
+ }
1825
+ }
1826
+ },
1827
+ "plans.variants.customize.upsertLicenses.customize.addItems.price": {
1828
+ required: ["billingMethod", "interval"],
1829
+ fields: {
1830
+ tierBehavior: {
1831
+ enum: ["graduated", "volume"]
1832
+ },
1833
+ interval: {
1834
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
1835
+ },
1836
+ billingMethod: {
1837
+ enum: ["prepaid", "usage_based"]
1838
+ },
1839
+ allocatedBilling: {
1840
+ enum: ["arrear", "prorated_legacy"]
1841
+ }
1842
+ }
1843
+ },
1844
+ "plans.variants.customize.upsertLicenses.customize.addItems.price.additionalCurrencies": {
1845
+ required: ["amount", "currency"]
1846
+ },
1847
+ "plans.variants.customize.upsertLicenses.customize.addItems.price.tiers": {
1848
+ required: ["to"]
1849
+ },
1850
+ "plans.variants.customize.upsertLicenses.customize.addItems.price.tiers.additionalCurrencies": {
1851
+ required: ["currency"]
1852
+ },
1853
+ "plans.variants.customize.upsertLicenses.customize.addItems.proration": {
1854
+ required: ["onDecrease", "onIncrease"],
1855
+ fields: {
1856
+ onIncrease: {
1857
+ enum: [
1858
+ "bill_immediately",
1859
+ "prorate_immediately",
1860
+ "prorate_next_cycle",
1861
+ "bill_next_cycle"
1862
+ ]
1863
+ },
1864
+ onDecrease: {
1865
+ enum: [
1866
+ "prorate",
1867
+ "prorate_immediately",
1868
+ "prorate_next_cycle",
1869
+ "none",
1870
+ "no_prorations"
1871
+ ]
1872
+ }
1873
+ }
1874
+ },
1875
+ "plans.variants.customize.upsertLicenses.customize.addItems.reset": {
1876
+ required: ["interval"],
1877
+ fields: {
1878
+ interval: {
1879
+ enum: [
1880
+ "one_off",
1881
+ "minute",
1882
+ "hour",
1883
+ "day",
1884
+ "week",
1885
+ "month",
1886
+ "quarter",
1887
+ "semi_annual",
1888
+ "year"
1889
+ ]
1890
+ }
1891
+ }
1892
+ },
1893
+ "plans.variants.customize.upsertLicenses.customize.addItems.rollover": {
1894
+ required: ["expiryDurationType"],
1895
+ fields: {
1896
+ expiryDurationType: {
1897
+ enum: ["month", "forever"]
1898
+ }
1899
+ }
1900
+ },
1901
+ "plans.variants.customize.upsertLicenses.customize.addItems.thresholdBilling": {
1902
+ required: ["threshold"],
1903
+ fields: {
1904
+ threshold: {
1905
+ exclusiveMinimum: 0
1906
+ }
1907
+ }
1908
+ },
1909
+ "plans.variants.customize.upsertLicenses.customize.price": {
1910
+ required: ["amount", "interval"],
1911
+ fields: {
1912
+ interval: {
1913
+ enum: ["one_off", "week", "month", "quarter", "semi_annual", "year"]
1914
+ }
1915
+ }
1916
+ },
1917
+ "plans.variants.customize.upsertLicenses.customize.price.additionalCurrencies": {
1918
+ required: ["amount", "currency"]
1919
+ },
1920
+ "plans.variants.customize.upsertLicenses.customize.removeItems": {
1921
+ fields: {
1922
+ billingMethod: {
1923
+ enum: ["prepaid", "usage_based"]
1924
+ },
1925
+ interval: {
1926
+ enum: [
1927
+ "one_off",
1928
+ "week",
1929
+ "month",
1930
+ "quarter",
1931
+ "semi_annual",
1932
+ "year",
1933
+ "minute",
1934
+ "hour",
1935
+ "day"
1936
+ ]
1937
+ },
1938
+ intervalCount: {
1939
+ minimum: -9007199254740991,
1940
+ maximum: 9007199254740991,
1941
+ exclusiveMinimum: 0
1942
+ },
1943
+ included: {
1944
+ maximum: 10000000000000
1945
+ }
1946
+ }
1947
+ },
1948
+ "plans.variants.processors.revenuecat": {
1949
+ required: ["products"]
1950
+ },
1951
+ "plans.variants.processors.revenuecat.products": {
1952
+ required: ["productId"]
1953
+ },
1954
+ "plans.variants.processors.revenuecat.products.featureQuantities": {
1955
+ required: ["featureId"],
1956
+ fields: {
1957
+ quantity: {
1958
+ minimum: 0
1959
+ }
1960
+ }
1961
+ },
1962
+ "plans.variants.processors.stripe": {
1963
+ required: ["productId"]
1964
+ },
1965
+ referralPrograms: {
1966
+ label: "referral program",
1967
+ idField: "id",
1968
+ required: ["id", "receivedBy", "redeemOn", "rewardId"],
1969
+ fields: {
1970
+ id: {
1971
+ minLength: 1
1972
+ },
1973
+ rewardId: {
1974
+ minLength: 1
1975
+ },
1976
+ redeemOn: {
1977
+ enum: ["customer_creation", "checkout"]
1978
+ },
1979
+ receivedBy: {
1980
+ enum: ["referrer", "all"]
1981
+ },
1982
+ maxRedemptions: {
1983
+ minimum: -9007199254740991,
1984
+ maximum: 9007199254740991,
1985
+ exclusiveMinimum: 0
1986
+ },
1987
+ internalId: {
1988
+ minLength: 1
1989
+ }
1990
+ },
1991
+ rules: [
1992
+ {
1993
+ kind: "unique",
1994
+ field: "id",
1995
+ because: "Two referral programs claiming one id race to define the same row."
1996
+ },
1997
+ {
1998
+ kind: "unique",
1999
+ field: "internalId",
2000
+ because: "A stable id names exactly one row; two fixtures cannot both be it."
2001
+ },
2002
+ {
2003
+ kind: "exists",
2004
+ field: "rewardId",
2005
+ in: "rewards",
2006
+ matching: ["coupon.id", "featureGrant.id"],
2007
+ because: "A referral program grants a reward this config does not declare."
2008
+ },
2009
+ {
2010
+ kind: "exists",
2011
+ field: "planIds",
2012
+ in: "plans",
2013
+ matching: "planId",
2014
+ because: "A referral program triggers on checkout of a plan this config does not declare."
2015
+ }
2016
+ ]
2017
+ },
2018
+ removeFeatures: {
2019
+ required: ["featureId"]
2020
+ },
2021
+ removePlans: {
2022
+ required: ["planId"],
2023
+ fields: {
2024
+ version: {
2025
+ minimum: 1,
2026
+ maximum: 9007199254740991
2027
+ }
2028
+ }
2029
+ },
2030
+ rewards: {
2031
+ label: "reward",
2032
+ rules: [
2033
+ {
2034
+ kind: "unique",
2035
+ field: ["coupon.id", "featureGrant.id"],
2036
+ because: "Two rewards claiming one id race to define the same row."
2037
+ },
2038
+ {
2039
+ kind: "unique",
2040
+ field: ["coupon.internalId", "featureGrant.internalId"],
2041
+ because: "A stable id names exactly one row; two fixtures cannot both be it."
2042
+ }
2043
+ ]
2044
+ },
2045
+ "rewards.coupon": {
2046
+ label: "coupon",
2047
+ idField: "id",
2048
+ required: [
2049
+ "duration",
2050
+ "id",
2051
+ "name",
2052
+ "planIds",
2053
+ "promoCodes",
2054
+ "type",
2055
+ "value"
2056
+ ],
2057
+ fields: {
2058
+ id: {
2059
+ minLength: 1
2060
+ },
2061
+ name: {
2062
+ minLength: 1
2063
+ },
2064
+ planIds: {
2065
+ minItems: 1
2066
+ },
2067
+ internalId: {
2068
+ minLength: 1
2069
+ },
2070
+ type: {
2071
+ enum: ["percentage_discount", "fixed_discount"]
2072
+ },
2073
+ value: {
2074
+ exclusiveMinimum: 0
2075
+ }
2076
+ },
2077
+ rules: [
2078
+ {
2079
+ kind: "exists",
2080
+ field: "planIds",
2081
+ in: "plans",
2082
+ matching: "planId",
2083
+ because: "A coupon discounts a plan this config does not declare."
2084
+ }
2085
+ ]
2086
+ },
2087
+ "rewards.coupon.duration": {
2088
+ required: ["length", "type"],
2089
+ fields: {
2090
+ type: {
2091
+ enum: ["one_off", "months", "forever"]
2092
+ },
2093
+ length: {
2094
+ minimum: -9007199254740991,
2095
+ maximum: 9007199254740991,
2096
+ exclusiveMinimum: 0
2097
+ }
2098
+ }
2099
+ },
2100
+ "rewards.coupon.promoCodes": {
2101
+ required: ["code"],
2102
+ fields: {
2103
+ code: {
2104
+ minLength: 1
2105
+ },
2106
+ globalMaxRedemption: {
2107
+ minimum: -9007199254740991,
2108
+ maximum: 9007199254740991,
2109
+ exclusiveMinimum: 0
2110
+ }
2111
+ }
2112
+ },
2113
+ "rewards.featureGrant": {
2114
+ label: "feature grant",
2115
+ idField: "id",
2116
+ required: ["grants", "id", "name", "promoCodes"],
2117
+ fields: {
2118
+ id: {
2119
+ minLength: 1
2120
+ },
2121
+ name: {
2122
+ minLength: 1
2123
+ },
2124
+ grants: {
2125
+ minItems: 1
2126
+ },
2127
+ promoCodes: {
2128
+ minItems: 1
2129
+ },
2130
+ internalId: {
2131
+ minLength: 1
2132
+ }
2133
+ }
2134
+ },
2135
+ "rewards.featureGrant.grants": {
2136
+ label: "grant",
2137
+ idField: "featureId",
2138
+ required: ["expiry", "featureId", "included"],
2139
+ fields: {
2140
+ featureId: {
2141
+ minLength: 1
2142
+ },
2143
+ included: {
2144
+ minimum: 0
2145
+ }
2146
+ },
2147
+ rules: [
2148
+ {
2149
+ kind: "exists",
2150
+ field: "featureId",
2151
+ in: "features",
2152
+ matching: "featureId",
2153
+ because: "A feature grant awards a feature this config does not declare."
2154
+ }
2155
+ ]
2156
+ },
2157
+ "rewards.featureGrant.grants.expiry": {
2158
+ required: ["length", "type"],
2159
+ fields: {
2160
+ type: {
2161
+ enum: ["day", "week", "month", "year"]
2162
+ },
2163
+ length: {
2164
+ minimum: -9007199254740991,
2165
+ maximum: 9007199254740991,
2166
+ exclusiveMinimum: 0
2167
+ }
2168
+ }
2169
+ },
2170
+ "rewards.featureGrant.promoCodes": {
2171
+ required: ["code", "maxUses"],
2172
+ fields: {
2173
+ code: {
2174
+ minLength: 1
2175
+ },
2176
+ maxUses: {
2177
+ minimum: -9007199254740991,
2178
+ maximum: 9007199254740991,
2179
+ exclusiveMinimum: 0
2180
+ }
2181
+ }
2182
+ }
2183
+ };
2184
+
2185
+ // src/generated/lintRuntime.ts
2186
+ class ConfigError extends Error {
2187
+ issues;
2188
+ constructor(issues) {
2189
+ super([
2190
+ `${issues.length} problem${issues.length === 1 ? "" : "s"} in your config:`,
2191
+ "",
2192
+ ...issues.map((issue) => ` ${issue.path}
2193
+ ${issue.message}`)
2194
+ ].join(`
2195
+ `));
2196
+ this.name = "ConfigError";
2197
+ this.issues = issues;
2198
+ }
2199
+ }
2200
+ var isEntry = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
2201
+ var valueAtPath = ({
2202
+ entry,
2203
+ path
2204
+ }) => {
2205
+ let current = entry;
2206
+ for (const segment of path.split(".")) {
2207
+ if (!isEntry(current))
2208
+ return;
2209
+ current = current[segment];
2210
+ }
2211
+ return current;
2212
+ };
2213
+ var firstValueAtPaths = ({
2214
+ entry,
2215
+ paths
2216
+ }) => {
2217
+ for (const path of typeof paths === "string" ? [paths] : paths) {
2218
+ const value = valueAtPath({ entry, path });
2219
+ if (value !== undefined)
2220
+ return value;
2221
+ }
2222
+ return;
2223
+ };
2224
+ var show = (value) => JSON.stringify(value);
2225
+ var list = (values) => values.map(show).join(", ");
2226
+ var regexCache = new Map;
2227
+ var regexFor = (pattern) => {
2228
+ const cached = regexCache.get(pattern);
2229
+ if (cached)
2230
+ return cached;
2231
+ const compiled = new RegExp(pattern);
2232
+ regexCache.set(pattern, compiled);
2233
+ return compiled;
2234
+ };
2235
+ var constraintFailures = ({
2236
+ name,
2237
+ value,
2238
+ constraints
2239
+ }) => {
2240
+ const failures = [];
2241
+ const c = constraints;
2242
+ if (c.enum && !c.enum.includes(value)) {
2243
+ failures.push(`${name} must be one of ${list(c.enum)} — got ${show(value)}.`);
2244
+ }
2245
+ if (typeof value === "number") {
2246
+ if (c.minimum !== undefined && value < c.minimum)
2247
+ failures.push(`${name} must be at least ${c.minimum} — got ${value}.`);
2248
+ if (c.maximum !== undefined && value > c.maximum)
2249
+ failures.push(`${name} must be at most ${c.maximum} — got ${value}.`);
2250
+ if (c.exclusiveMinimum !== undefined && value <= c.exclusiveMinimum)
2251
+ failures.push(`${name} must be greater than ${c.exclusiveMinimum} — got ${value}.`);
2252
+ if (c.exclusiveMaximum !== undefined && value >= c.exclusiveMaximum)
2253
+ failures.push(`${name} must be less than ${c.exclusiveMaximum} — got ${value}.`);
2254
+ }
2255
+ if (typeof value === "string") {
2256
+ if (c.minLength !== undefined && value.length < c.minLength) {
2257
+ failures.push(c.minLength === 1 ? `${name} must not be empty.` : `${name} must be at least ${c.minLength} characters — got ${value.length}.`);
2258
+ }
2259
+ if (c.maxLength !== undefined && value.length > c.maxLength)
2260
+ failures.push(`${name} must be at most ${c.maxLength} characters — got ${value.length}.`);
2261
+ if (c.pattern !== undefined && !regexFor(c.pattern).test(value))
2262
+ failures.push(`${name} must match ${c.pattern} — got ${show(value)}.`);
2263
+ }
2264
+ if (Array.isArray(value)) {
2265
+ if (c.minItems !== undefined && value.length < c.minItems)
2266
+ failures.push(`${name} must have at least ${c.minItems} ${c.minItems === 1 ? "entry" : "entries"}.`);
2267
+ if (c.maxItems !== undefined && value.length > c.maxItems)
2268
+ failures.push(`${name} must have at most ${c.maxItems} entries.`);
2269
+ }
2270
+ return failures;
2271
+ };
2272
+ var checkShape = ({
2273
+ entry,
2274
+ shape,
2275
+ at,
2276
+ issues
2277
+ }) => {
2278
+ for (const field of shape.required ?? []) {
2279
+ if (entry[field] === undefined)
2280
+ issues.push({ path: at, message: `${field} is required.` });
2281
+ }
2282
+ for (const [field, constraints] of Object.entries(shape.fields ?? {})) {
2283
+ if (entry[field] === undefined)
2284
+ continue;
2285
+ for (const message of constraintFailures({
2286
+ name: field,
2287
+ value: entry[field],
2288
+ constraints
2289
+ })) {
2290
+ issues.push({ path: at, message });
2291
+ }
2292
+ }
2293
+ };
2294
+ var checkVariants = ({
2295
+ entry,
2296
+ variants,
2297
+ at,
2298
+ issues
2299
+ }) => {
2300
+ const selector = entry[variants.on];
2301
+ if (selector === undefined) {
2302
+ if (variants.fallback) {
2303
+ checkShape({ entry, shape: variants.fallback, at, issues });
2304
+ } else {
2305
+ issues.push({ path: at, message: `${variants.on} is required.` });
2306
+ }
2307
+ return;
2308
+ }
2309
+ const chosen = typeof selector === "string" ? variants.byValue[selector] : undefined;
2310
+ if (!chosen) {
2311
+ issues.push({
2312
+ path: at,
2313
+ message: `${variants.on} must be one of ${list(Object.keys(variants.byValue))} — got ${show(selector)}.`
2314
+ });
2315
+ return;
2316
+ }
2317
+ checkShape({ entry, shape: chosen, at, issues });
2318
+ };
2319
+ var crumbFor = ({
2320
+ node,
2321
+ key,
2322
+ entry,
2323
+ index
2324
+ }) => {
2325
+ const label = node?.label ?? key;
2326
+ const id = node?.idField ? entry[node.idField] : undefined;
2327
+ return typeof id === "string" && id ? `${label} ${show(id)}` : `${label}[${index}]`;
2328
+ };
2329
+ var render = (trail) => trail.length === 0 ? "config" : trail.join(" › ");
2330
+ var setFields = ({
2331
+ entry,
2332
+ fields
2333
+ }) => fields.filter((field) => entry[field] !== undefined);
2334
+ var joinNames = (names) => names.length <= 1 ? names.join("") : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
2335
+ var COMPARE = {
2336
+ "<": { holds: (a, b) => a < b, words: "less than" },
2337
+ "<=": { holds: (a, b) => a <= b, words: "at most" },
2338
+ ">": { holds: (a, b) => a > b, words: "greater than" },
2339
+ ">=": { holds: (a, b) => a >= b, words: "at least" }
2340
+ };
2341
+ var entryRuleFailures = ({
2342
+ entry,
2343
+ rule,
2344
+ document,
2345
+ parent
2346
+ }) => {
2347
+ switch (rule.kind) {
2348
+ case "requiredWhen": {
2349
+ if (entry[rule.when] !== rule.equals)
2350
+ return [];
2351
+ return rule.require.filter((field) => entry[field] === undefined).map((field) => `${field} is required when ${rule.when} is ${show(rule.equals)}. ${rule.because}`);
2352
+ }
2353
+ case "forbiddenWhen": {
2354
+ if (entry[rule.when] !== rule.equals)
2355
+ return [];
2356
+ return setFields({ entry, fields: rule.forbid }).map((field) => `${field} cannot be set when ${rule.when} is ${show(rule.equals)}. ${rule.because}`);
2357
+ }
2358
+ case "mutex": {
2359
+ const set = setFields({ entry, fields: rule.fields });
2360
+ if (set.length <= 1)
2361
+ return [];
2362
+ return [`${joinNames(set)} cannot be set together. ${rule.because}`];
2363
+ }
2364
+ case "exactlyOne": {
2365
+ const set = setFields({ entry, fields: rule.fields });
2366
+ if (set.length === 1)
2367
+ return [];
2368
+ if (set.length === 0)
2369
+ return [
2370
+ `One of ${joinNames(rule.fields)} is required. ${rule.because}`
2371
+ ];
2372
+ return [`${joinNames(set)} cannot be set together. ${rule.because}`];
2373
+ }
2374
+ case "exists": {
2375
+ const value = valueAtPath({ entry, path: rule.field });
2376
+ const target = document[rule.in];
2377
+ if (value === undefined || value === null || !Array.isArray(target))
2378
+ return [];
2379
+ const names = (wanted) => target.some((candidate) => isEntry(candidate) && firstValueAtPaths({ entry: candidate, paths: rule.matching }) === wanted);
2380
+ const missing = (Array.isArray(value) ? value : [value]).filter((wanted) => !names(wanted));
2381
+ return missing.map((wanted) => `${rule.field} ${show(wanted)} is not in ${rule.in}. ${rule.because}`);
2382
+ }
2383
+ case "compare": {
2384
+ const a = entry[rule.field];
2385
+ const b = entry[rule.than];
2386
+ if (typeof a !== "number" || typeof b !== "number")
2387
+ return [];
2388
+ const { holds, words } = COMPARE[rule.op];
2389
+ return holds(a, b) ? [] : [
2390
+ `${rule.field} must be ${words} ${rule.than} — got ${a} and ${b}. ${rule.because}`
2391
+ ];
2392
+ }
2393
+ case "valueWhen": {
2394
+ if (entry[rule.when] !== rule.equals)
2395
+ return [];
2396
+ const value = entry[rule.field];
2397
+ if (value === undefined || value === rule.mustBe)
2398
+ return [];
2399
+ return [
2400
+ `${rule.field} must be ${show(rule.mustBe)} when ${rule.when} is ${show(rule.equals)}. ${rule.because}`
2401
+ ];
2402
+ }
2403
+ case "targetHas": {
2404
+ if (entry[rule.when] === undefined)
2405
+ return [];
2406
+ const target = document[rule.in];
2407
+ if (!Array.isArray(target))
2408
+ return [];
2409
+ const row = target.find((candidate) => isEntry(candidate) && candidate[rule.matching] === entry[rule.field]);
2410
+ if (!row || row[rule.target] === rule.equals)
2411
+ return [];
2412
+ return [
2413
+ `${rule.when} needs ${rule.in} ${show(entry[rule.field])} to have ${rule.target} ${show(rule.equals)} — got ${show(row[rule.target])}. ${rule.because}`
2414
+ ];
2415
+ }
2416
+ case "targetLacks": {
2417
+ const target = document[rule.in];
2418
+ if (!Array.isArray(target))
2419
+ return [];
2420
+ const row = target.find((candidate) => isEntry(candidate) && candidate[rule.matching] === entry[rule.field]);
2421
+ if (!row || row[rule.target] !== true)
2422
+ return [];
2423
+ if (parent?.[rule.parentGuard] === true)
2424
+ return [];
2425
+ return [
2426
+ `${rule.label} ${show(entry[rule.field])} is ${rule.target}. Unarchive it, or archive ${rule.parentLabel} ${show(parent?.[rule.parentIdField])}. ${rule.because}`
2427
+ ];
2428
+ }
2429
+ case "unique":
2430
+ case "linkedOnce":
2431
+ case "exactlyOneActive":
2432
+ return [];
2433
+ }
2434
+ };
2435
+ var checkUnique = ({
2436
+ entries,
2437
+ rule,
2438
+ node,
2439
+ key,
2440
+ trail,
2441
+ issues
2442
+ }) => {
2443
+ const seen = new Set;
2444
+ for (const [index, entry] of entries.entries()) {
2445
+ if (!isEntry(entry))
2446
+ continue;
2447
+ const value = firstValueAtPaths({ entry, paths: rule.field });
2448
+ if (typeof value !== "string")
2449
+ continue;
2450
+ const fieldName = typeof rule.field === "string" ? rule.field : rule.field.join(" / ");
2451
+ const pair = rule.alongside === undefined ? undefined : entry[rule.alongside];
2452
+ if (rule.alongside !== undefined && typeof pair !== "string")
2453
+ continue;
2454
+ const composite = rule.alongside === undefined ? value : `${value}@${pair}`;
2455
+ if (seen.has(composite)) {
2456
+ const label = rule.alongside === undefined ? `${fieldName} ${show(value)}` : `${fieldName} ${show(value)} with ${rule.alongside} ${show(pair)}`;
2457
+ issues.push({
2458
+ path: render([...trail, crumbFor({ node, key, entry, index })]),
2459
+ message: `${label} is used more than once. ${rule.because}`
2460
+ });
2461
+ }
2462
+ seen.add(composite);
2463
+ }
2464
+ };
2465
+ var pinOf = ({
2466
+ entry,
2467
+ pins
2468
+ }) => {
2469
+ for (const pin of pins) {
2470
+ const value = entry[pin];
2471
+ if (typeof value === "string")
2472
+ return { key: `${pin}:${value}`, display: value };
2473
+ if (typeof value === "number")
2474
+ return { key: `${pin}:${value}`, display: `v${value}` };
2475
+ }
2476
+ return;
2477
+ };
2478
+ var checkLinkedOnce = ({
2479
+ entries,
2480
+ rule,
2481
+ node,
2482
+ key,
2483
+ trail,
2484
+ issues
2485
+ }) => {
2486
+ const ownerByLink = new Map;
2487
+ for (const [index, entry] of entries.entries()) {
2488
+ if (!isEntry(entry))
2489
+ continue;
2490
+ const group = entry[rule.groupBy];
2491
+ const links = entry[rule.collection];
2492
+ if (typeof group !== "string" || !Array.isArray(links))
2493
+ continue;
2494
+ const owner = pinOf({ entry, pins: [rule.namedBy] })?.display ?? rule.absentMeans;
2495
+ for (const link of links) {
2496
+ if (!isEntry(link))
2497
+ continue;
2498
+ const id = link[rule.identity];
2499
+ if (typeof id !== "string")
2500
+ continue;
2501
+ const pin = pinOf({ entry: link, pins: rule.pins });
2502
+ const label = pin === undefined ? id : `${id} ${pin.display}`;
2503
+ const composite = `${group} ${id} ${pin?.key ?? "latest"}`;
2504
+ const previous = ownerByLink.get(composite);
2505
+ if (previous === undefined) {
2506
+ ownerByLink.set(composite, { owner, index });
2507
+ continue;
2508
+ }
2509
+ const at = render([...trail, crumbFor({ node, key, entry, index })]);
2510
+ if (previous.index === index) {
2511
+ issues.push({
2512
+ path: at,
2513
+ message: `${label} is linked twice from ${group} ${owner}. ${rule.because}`
2514
+ });
2515
+ continue;
2516
+ }
2517
+ if (previous.owner === owner)
2518
+ continue;
2519
+ issues.push({
2520
+ path: at,
2521
+ message: `${label} is linked from ${group} ${previous.owner} and ${group} ${owner}. ${rule.because}`
2522
+ });
2523
+ }
2524
+ }
2525
+ };
2526
+ var checkExactlyOneActive = ({
2527
+ entries,
2528
+ rule,
2529
+ node,
2530
+ key,
2531
+ trail,
2532
+ issues
2533
+ }) => {
2534
+ const rowsByGroup = new Map;
2535
+ for (const [index, entry] of entries.entries()) {
2536
+ if (!isEntry(entry))
2537
+ continue;
2538
+ const group = entry[rule.groupBy];
2539
+ if (typeof group !== "string")
2540
+ continue;
2541
+ rowsByGroup.set(group, [
2542
+ ...rowsByGroup.get(group) ?? [],
2543
+ { entry, index, active: entry[rule.field] === true }
2544
+ ]);
2545
+ }
2546
+ for (const [group, members] of rowsByGroup) {
2547
+ const active = members.filter((member) => member.active);
2548
+ if (active.length === 1)
2549
+ continue;
2550
+ const at = active.length === 0 ? members[0] : active[1];
2551
+ if (at === undefined)
2552
+ continue;
2553
+ const versions = `${members.length} version${members.length === 1 ? "" : "s"}`;
2554
+ const count = active.length === 0 ? "none is active" : `${active.length} are active`;
2555
+ issues.push({
2556
+ path: render([
2557
+ ...trail,
2558
+ crumbFor({ node, key, entry: at.entry, index: at.index })
2559
+ ]),
2560
+ message: `${rule.label} ${show(group)} has ${versions} and ${count}. ${rule.because}${renameHint({ active, members })}`
2561
+ });
2562
+ }
2563
+ };
2564
+ var renameHint = ({
2565
+ active,
2566
+ members
2567
+ }) => {
2568
+ if (active.length !== 0)
2569
+ return "";
2570
+ const everyRowIsKnown = members.every((member) => typeof member.entry.internalId === "string");
2571
+ if (!everyRowIsKnown)
2572
+ return "";
2573
+ return " If you are renaming a plan, change the planId on every one of its versions, not just some.";
2574
+ };
2575
+ var checkCollection = ({
2576
+ entries,
2577
+ node,
2578
+ key,
2579
+ trail,
2580
+ issues
2581
+ }) => {
2582
+ for (const rule of node.rules ?? []) {
2583
+ if (rule.kind === "unique")
2584
+ checkUnique({ entries, rule, node, key, trail, issues });
2585
+ if (rule.kind === "linkedOnce")
2586
+ checkLinkedOnce({ entries, rule, node, key, trail, issues });
2587
+ if (rule.kind === "exactlyOneActive")
2588
+ checkExactlyOneActive({ entries, rule, node, key, trail, issues });
2589
+ }
2590
+ };
2591
+ var checkEntry = ({
2592
+ entry,
2593
+ node,
2594
+ at,
2595
+ walk,
2596
+ parent
2597
+ }) => {
2598
+ checkShape({ entry, shape: node, at, issues: walk.issues });
2599
+ if (node.variants) {
2600
+ checkVariants({ entry, variants: node.variants, at, issues: walk.issues });
2601
+ }
2602
+ for (const rule of node.rules ?? []) {
2603
+ for (const message of entryRuleFailures({
2604
+ entry,
2605
+ rule,
2606
+ document: walk.document,
2607
+ parent
2608
+ })) {
2609
+ walk.issues.push({ path: at, message });
2610
+ }
2611
+ }
2612
+ };
2613
+ var walkEntry = ({
2614
+ entry,
2615
+ path,
2616
+ trail,
2617
+ walk,
2618
+ parent
2619
+ }) => {
2620
+ const node = walk.rules[path];
2621
+ if (node)
2622
+ checkEntry({ entry, node, at: render(trail), walk, parent });
2623
+ for (const [key, child] of Object.entries(entry)) {
2624
+ walkValue({
2625
+ value: child,
2626
+ path: path ? `${path}.${key}` : key,
2627
+ key,
2628
+ trail,
2629
+ walk,
2630
+ parent: entry
2631
+ });
2632
+ }
2633
+ };
2634
+ var walkValue = ({
2635
+ value,
2636
+ path,
2637
+ key,
2638
+ trail,
2639
+ walk,
2640
+ parent
2641
+ }) => {
2642
+ if (walk.hints.frozenPaths.has(path))
2643
+ return;
2644
+ if (Array.isArray(value)) {
2645
+ const node = walk.rules[path];
2646
+ if (node) {
2647
+ checkCollection({
2648
+ entries: value,
2649
+ node,
2650
+ key,
2651
+ trail,
2652
+ issues: walk.issues
2653
+ });
2654
+ }
2655
+ for (const [index, entry] of value.entries()) {
2656
+ if (!isEntry(entry))
2657
+ continue;
2658
+ walkEntry({
2659
+ entry,
2660
+ path,
2661
+ trail: [...trail, crumbFor({ node, key, entry, index })],
2662
+ walk,
2663
+ parent
2664
+ });
2665
+ }
2666
+ return;
2667
+ }
2668
+ if (!isEntry(value))
2669
+ return;
2670
+ if (walk.hints.recordPaths.has(path)) {
2671
+ const keys = walk.rules[path]?.keys;
2672
+ for (const [recordKey, child] of Object.entries(value)) {
2673
+ if (keys) {
2674
+ for (const message of constraintFailures({
2675
+ name: `${key} key ${show(recordKey)}`,
2676
+ value: recordKey,
2677
+ constraints: keys
2678
+ })) {
2679
+ walk.issues.push({ path: render(trail), message });
2680
+ }
2681
+ }
2682
+ walkValue({
2683
+ value: child,
2684
+ path: `${path}.*`,
2685
+ key: `${key}[${show(recordKey)}]`,
2686
+ trail,
2687
+ walk,
2688
+ parent
2689
+ });
2690
+ }
2691
+ return;
2692
+ }
2693
+ walkEntry({ entry: value, path, trail: [...trail, key], walk, parent });
2694
+ };
2695
+ var lintDocument = ({
2696
+ document,
2697
+ rules,
2698
+ hints
2699
+ }) => {
2700
+ const walk = { document, rules, hints, issues: [] };
2701
+ walkEntry({ entry: document, path: "", trail: [], walk });
2702
+ return walk.issues;
2703
+ };
2704
+
2705
+ // src/generated/wire.ts
2706
+ var isOperatorKey = (key) => key.startsWith("$");
2707
+ var toSnakeCase = (key) => isOperatorKey(key) ? key : key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
2708
+ var toCamelCase = (key) => isOperatorKey(key) ? key : key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
2709
+ var clearOmittedRelationshipCustomizes = (row) => {
2710
+ if (row === null || typeof row !== "object")
2711
+ return row;
2712
+ const source = row;
2713
+ const normalize = (entries) => Array.isArray(entries) ? entries.map((entry) => entry !== null && typeof entry === "object" ? {
2714
+ ...entry,
2715
+ customize: entry.customize ?? null
2716
+ } : entry) : entries;
2717
+ return {
2718
+ ...source,
2719
+ ...source.licenses !== undefined ? { licenses: normalize(source.licenses) } : {},
2720
+ ...source.variants !== undefined ? { variants: normalize(source.variants) } : {}
2721
+ };
2722
+ };
2723
+ var toWire = ({
2724
+ value,
2725
+ path,
2726
+ hints
2727
+ }) => {
2728
+ if (hints.frozenPaths.has(path))
2729
+ return value;
2730
+ if (Array.isArray(value)) {
2731
+ return value.map((entry) => toWire({ value: entry, path, hints }));
2732
+ }
2733
+ if (value === null || typeof value !== "object")
2734
+ return value;
2735
+ const source = value;
2736
+ if (hints.recordPaths.has(path)) {
2737
+ return Object.fromEntries(Object.entries(source).map(([key, entry]) => [
2738
+ key,
2739
+ toWire({ value: entry, path: `${path}.*`, hints })
2740
+ ]));
2741
+ }
2742
+ return Object.fromEntries(Object.entries(source).map(([key, entry]) => {
2743
+ const childPath = path ? `${path}.${key}` : key;
2744
+ return [
2745
+ hints.renamedPaths.get(childPath) ?? toSnakeCase(key),
2746
+ toWire({ value: entry, path: childPath, hints })
2747
+ ];
2748
+ }));
2749
+ };
2750
+ var toFixture = ({
2751
+ value,
2752
+ path,
2753
+ hints
2754
+ }) => {
2755
+ if (hints.frozenPaths.has(path))
2756
+ return value;
2757
+ if (Array.isArray(value)) {
2758
+ return value.map((entry) => toFixture({ value: entry, path, hints }));
2759
+ }
2760
+ if (value === null || typeof value !== "object")
2761
+ return value;
2762
+ const source = value;
2763
+ if (hints.recordPaths.has(path)) {
2764
+ return Object.fromEntries(Object.entries(source).map(([key, entry]) => [
2765
+ key,
2766
+ toFixture({ value: entry, path: `${path}.*`, hints })
2767
+ ]));
2768
+ }
2769
+ return Object.fromEntries(Object.entries(source).map(([key, entry]) => {
2770
+ const name = hints.renamedWirePaths.get(path ? `${path}.${key}` : key) ?? toCamelCase(key);
2771
+ return [
2772
+ name,
2773
+ toFixture({
2774
+ value: entry,
2775
+ path: path ? `${path}.${name}` : name,
2776
+ hints
2777
+ })
2778
+ ];
2779
+ }));
2780
+ };
2781
+ var hintsOf = (hints) => ({
2782
+ recordPaths: new Set(hints.recordPaths),
2783
+ frozenPaths: new Set(hints.frozenPaths),
2784
+ renamedPaths: new Map(Object.entries(hints.renamedPaths)),
2785
+ renamedWirePaths: new Map(Object.entries(hints.renamedPaths).map(([fixturePath, wireKey]) => {
2786
+ const segments = fixturePath.split(".");
2787
+ const parent = segments.slice(0, -1);
2788
+ return [
2789
+ [...parent, wireKey].join("."),
2790
+ segments[segments.length - 1] ?? ""
2791
+ ];
2792
+ }))
2793
+ });
2794
+ var CATALOG_HINTS = hintsOf({
2795
+ recordPaths: [
2796
+ "features.creditSchema.dimensions",
2797
+ "features.creditSchema.dimensions.*.match",
2798
+ "features.creditSchema.multipliers",
2799
+ "features.creditSchema.multipliers.*.match",
2800
+ "features.modelMarkups",
2801
+ "features.providerMarkups",
2802
+ "plans.billingControls.usageAlerts.filter.properties",
2803
+ "plans.billingControls.usageLimits.filter.properties",
2804
+ "plans.items.featureOverride.creditSchema.dimensions",
2805
+ "plans.items.featureOverride.creditSchema.dimensions.*.match",
2806
+ "plans.items.featureOverride.creditSchema.multipliers",
2807
+ "plans.items.featureOverride.creditSchema.multipliers.*.match",
2808
+ "plans.items.featureOverride.markups.modelMarkups",
2809
+ "plans.items.featureOverride.markups.providerMarkups",
2810
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.dimensions",
2811
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.dimensions.*.match",
2812
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.multipliers",
2813
+ "plans.licenses.customize.addItems.featureOverride.creditSchema.multipliers.*.match",
2814
+ "plans.licenses.customize.addItems.featureOverride.markups.modelMarkups",
2815
+ "plans.licenses.customize.addItems.featureOverride.markups.providerMarkups",
2816
+ "plans.variants.customize.addItems.featureOverride.creditSchema.dimensions",
2817
+ "plans.variants.customize.addItems.featureOverride.creditSchema.dimensions.*.match",
2818
+ "plans.variants.customize.addItems.featureOverride.creditSchema.multipliers",
2819
+ "plans.variants.customize.addItems.featureOverride.creditSchema.multipliers.*.match",
2820
+ "plans.variants.customize.addItems.featureOverride.markups.modelMarkups",
2821
+ "plans.variants.customize.addItems.featureOverride.markups.providerMarkups",
2822
+ "plans.variants.customize.billingControls.usageAlerts.filter.properties",
2823
+ "plans.variants.customize.billingControls.usageLimits.filter.properties",
2824
+ "plans.variants.customize.items.featureOverride.creditSchema.dimensions",
2825
+ "plans.variants.customize.items.featureOverride.creditSchema.dimensions.*.match",
2826
+ "plans.variants.customize.items.featureOverride.creditSchema.multipliers",
2827
+ "plans.variants.customize.items.featureOverride.creditSchema.multipliers.*.match",
2828
+ "plans.variants.customize.items.featureOverride.markups.modelMarkups",
2829
+ "plans.variants.customize.items.featureOverride.markups.providerMarkups",
2830
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.dimensions",
2831
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.dimensions.*.match",
2832
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.multipliers",
2833
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.creditSchema.multipliers.*.match",
2834
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups.modelMarkups",
2835
+ "plans.variants.customize.upsertLicenses.customize.addItems.featureOverride.markups.providerMarkups"
2836
+ ],
2837
+ frozenPaths: [
2838
+ "plans.licenses.metadata",
2839
+ "plans.metadata",
2840
+ "plans.variants.customize.upsertLicenses.metadata"
2841
+ ],
2842
+ renamedPaths: { "settings.paydownOverages": "persist_free_overage" }
2843
+ });
2844
+ var stated = (config) => ({
2845
+ ...config.features !== undefined ? { features: config.features } : {},
2846
+ ...config.plans !== undefined ? {
2847
+ plans: config.plans.map(clearOmittedRelationshipCustomizes),
2848
+ skip_version_deletions: false
2849
+ } : {},
2850
+ ...config.rewards !== undefined ? { rewards: config.rewards } : {},
2851
+ ...config.referralPrograms !== undefined ? { referralPrograms: config.referralPrograms } : {},
2852
+ ...config.settings !== undefined ? { settings: config.settings } : {}
2853
+ });
2854
+ var SINGLETON_KEYS = ["settings"];
2855
+ var CONFIG_KEYS = [
2856
+ "features",
2857
+ "plans",
2858
+ "rewards",
2859
+ "referralPrograms",
2860
+ "settings"
2861
+ ];
2862
+ var unknownKeyIssue = (key) => key === "planVersions" ? {
2863
+ path: key,
2864
+ message: "planVersions is gone: every version is now a row in plans, with versionSlug and active. Rebuild the config from your org with `atmn pull --overwrite --yes` (commit first), or move the rows into plans."
2865
+ } : {
2866
+ path: key,
2867
+ message: `${key} is not a config field. The fields are ${CONFIG_KEYS.join(", ")}.`
2868
+ };
2869
+ var splitWire = (document) => ({
2870
+ catalog: Object.fromEntries(Object.entries(document).filter(([key]) => !SINGLETON_KEYS.includes(key))),
2871
+ singletons: {
2872
+ settings: document.settings === undefined ? undefined : { config: document.settings }
2873
+ }
2874
+ });
2875
+ var atmn = (config) => {
2876
+ const unknownKeys = Object.keys(config).filter((key) => !CONFIG_KEYS.includes(key));
2877
+ if (unknownKeys.length > 0)
2878
+ throw new ConfigError(unknownKeys.map(unknownKeyIssue));
2879
+ const document = stated(config);
2880
+ const issues = lintDocument({
2881
+ document,
2882
+ rules: LINT_RULES,
2883
+ hints: CATALOG_HINTS
2884
+ });
2885
+ if (issues.length > 0)
2886
+ throw new ConfigError(issues);
2887
+ return {
2888
+ ...toWire({
2889
+ value: document,
2890
+ path: "",
2891
+ hints: CATALOG_HINTS
2892
+ }),
2893
+ skip_deletions: false,
2894
+ migration: { draft: true }
2895
+ };
2896
+ };
2897
+ export {
2898
+ variant,
2899
+ referralProgram,
2900
+ plan,
2901
+ license,
2902
+ featureGrant,
2903
+ feature,
2904
+ coupon,
2905
+ atmn
2906
+ };