atmn 2.0.41 → 2.0.43
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.
- package/dist/bin.js +405 -392
- package/dist/index.js +20 -21
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/actions/pull/webhooks/appendWebhook.ts +6 -4
- package/src/actions/pull/webhooks/applyWebhooksPull.ts +28 -105
- package/src/actions/pull/webhooks/deleteWebhook.ts +59 -0
- package/src/actions/pull/webhooks/locateWebhook.ts +9 -1
- package/src/actions/pull/webhooks/readWebhookEnvs.ts +7 -12
- package/src/actions/pull/webhooks/types.ts +3 -2
- package/src/actions/pull/webhooks/updateWebhook.ts +37 -42
- package/src/actions/pull/webhooks/webhookEnvSkipWarning.ts +29 -0
- package/src/actions/pull/webhooks/webhookPullEnvs.ts +5 -5
- package/src/actions/pull.ts +1 -1
- package/src/actions/push.ts +30 -12
- package/src/actions/webhooks/applyWebhooks.ts +41 -10
- package/src/actions/webhooks/previewWebhookEnvs.ts +213 -0
- package/src/actions/webhooks/resolveWebhooksForEnv.ts +5 -16
- package/src/actions/webhooks/types/webhookEnv.ts +1 -3
- package/src/actions/webhooks/webhookEnvFailures.ts +27 -0
- package/src/actions/webhooks/webhookSecretName.ts +10 -9
- package/src/actions/webhooks/writeWebhookSecrets.ts +5 -2
- package/src/auth/runOAuthFlow.ts +1 -1
- package/src/cli.ts +23 -25
- package/src/generated/apiRoutes.ts +43 -12
- package/src/generated/client.ts +10 -10
- package/src/generated/emit.ts +4 -4
- package/src/generated/emitRuntime.ts +3 -3
- package/src/generated/lintRules.ts +16 -20
- package/src/generated/lintRuntime.ts +10 -0
- package/src/generated/skills.ts +10 -10
- package/src/generated/webhooks.ts +7 -9
- package/src/generated/wire.ts +0 -1
- package/src/render/renderPreview.ts +25 -9
- package/src/render/renderWebhooks.ts +9 -3
- package/src/actions/pull/webhooks/removeWebhookEnv.ts +0 -141
- package/src/actions/webhooks/isDashboardWebhook.ts +0 -9
- package/src/actions/webhooks/newWebhookId.ts +0 -4
- package/src/actions/webhooks/previewWebhooks.ts +0 -40
- package/src/actions/webhooks/resolveWebhookEnv.ts +0 -34
|
@@ -955,7 +955,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
955
955
|
type: "string",
|
|
956
956
|
required: false,
|
|
957
957
|
description:
|
|
958
|
-
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.",
|
|
958
|
+
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
959
959
|
},
|
|
960
960
|
{
|
|
961
961
|
name: "redirect_mode",
|
|
@@ -1190,7 +1190,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1190
1190
|
type: "string",
|
|
1191
1191
|
required: false,
|
|
1192
1192
|
description:
|
|
1193
|
-
"Whether to prorate the immediate phase. 'none' skips proration charges and credits.",
|
|
1193
|
+
"Whether to prorate the immediate phase. 'none' skips proration charges and credits, 'bill_difference' charges/credits the full-period price difference.",
|
|
1194
1194
|
},
|
|
1195
1195
|
{
|
|
1196
1196
|
name: "no_billing_changes",
|
|
@@ -1300,7 +1300,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1300
1300
|
type: "string",
|
|
1301
1301
|
required: false,
|
|
1302
1302
|
description:
|
|
1303
|
-
"How to handle billing. 'prorate_immediately' charges/credits prorated amounts now, 'none' does not charge/credit anything.",
|
|
1303
|
+
"How to handle billing. 'prorate_immediately' charges/credits prorated amounts now, 'none' does not charge/credit anything, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
1304
1304
|
},
|
|
1305
1305
|
{
|
|
1306
1306
|
name: "billing_cycle_anchor",
|
|
@@ -1420,7 +1420,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1420
1420
|
type: "string",
|
|
1421
1421
|
required: false,
|
|
1422
1422
|
description:
|
|
1423
|
-
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.",
|
|
1423
|
+
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
1424
1424
|
},
|
|
1425
1425
|
{
|
|
1426
1426
|
name: "redirect_mode",
|
|
@@ -1648,7 +1648,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1648
1648
|
type: "string",
|
|
1649
1649
|
required: false,
|
|
1650
1650
|
description:
|
|
1651
|
-
"How to handle billing. 'prorate_immediately' charges/credits prorated amounts now, 'none' does not charge/credit anything.",
|
|
1651
|
+
"How to handle billing. 'prorate_immediately' charges/credits prorated amounts now, 'none' does not charge/credit anything, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
1652
1652
|
},
|
|
1653
1653
|
{
|
|
1654
1654
|
name: "billing_cycle_anchor",
|
|
@@ -1769,7 +1769,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1769
1769
|
type: "string",
|
|
1770
1770
|
required: false,
|
|
1771
1771
|
description:
|
|
1772
|
-
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.",
|
|
1772
|
+
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
1773
1773
|
},
|
|
1774
1774
|
{
|
|
1775
1775
|
name: "redirect_mode",
|
|
@@ -1929,7 +1929,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
1929
1929
|
type: "string",
|
|
1930
1930
|
required: false,
|
|
1931
1931
|
description:
|
|
1932
|
-
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.",
|
|
1932
|
+
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
1933
1933
|
},
|
|
1934
1934
|
{
|
|
1935
1935
|
name: "redirect_mode",
|
|
@@ -2198,7 +2198,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
2198
2198
|
type: "string",
|
|
2199
2199
|
required: false,
|
|
2200
2200
|
description:
|
|
2201
|
-
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.",
|
|
2201
|
+
"How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges, 'bill_difference' charges/credits the full-period price difference now without changing the billing cycle.",
|
|
2202
2202
|
},
|
|
2203
2203
|
{
|
|
2204
2204
|
name: "subscription_id",
|
|
@@ -2332,6 +2332,37 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
2332
2332
|
},
|
|
2333
2333
|
],
|
|
2334
2334
|
},
|
|
2335
|
+
{
|
|
2336
|
+
group: "billing",
|
|
2337
|
+
method: "verify",
|
|
2338
|
+
path: "/v1/billing.verify",
|
|
2339
|
+
description:
|
|
2340
|
+
"Checks a customer's Stripe subscriptions against Autumn's record of their plans and reports any drift. Read-only: it never changes Autumn or Stripe.",
|
|
2341
|
+
body: "object",
|
|
2342
|
+
fields: [
|
|
2343
|
+
{
|
|
2344
|
+
name: "customer_id",
|
|
2345
|
+
type: "string",
|
|
2346
|
+
required: true,
|
|
2347
|
+
description:
|
|
2348
|
+
"Autumn customer whose Stripe subscriptions should be checked against Autumn's customer_products.",
|
|
2349
|
+
},
|
|
2350
|
+
{
|
|
2351
|
+
name: "subscription_ids",
|
|
2352
|
+
type: "json",
|
|
2353
|
+
required: false,
|
|
2354
|
+
description:
|
|
2355
|
+
"Optional whitelist of Stripe subscription IDs to verify. Defaults to every subscription linked to the customer's plans, plus any other active Stripe subscription on the customer, which is reported as not linked to Autumn.",
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
name: "strict",
|
|
2359
|
+
type: "boolean",
|
|
2360
|
+
required: false,
|
|
2361
|
+
description:
|
|
2362
|
+
"When true, report missing usage-based items and unexpected metered Stripe items. Defaults to false.",
|
|
2363
|
+
},
|
|
2364
|
+
],
|
|
2365
|
+
},
|
|
2335
2366
|
{
|
|
2336
2367
|
group: "billing",
|
|
2337
2368
|
method: "import",
|
|
@@ -2873,7 +2904,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
2873
2904
|
method: "batch_track",
|
|
2874
2905
|
path: "/v1/balances.batch_track",
|
|
2875
2906
|
description:
|
|
2876
|
-
"Enqueue up to 1000 usage events for asynchronous processing. Items are validated synchronously up front; validated items are then enqueued via SQS for background deduction by workers. The response returns 202 immediately and does not include balance information. On partial enqueue failure (some items fail to enqueue, others succeed), the endpoint still returns 202 and logs the failures server-side; clients should NOT retry, because retrying re-enqueues the already-succeeded items. A 503 is returned only when zero items were successfully enqueued (queue entirely unavailable) — that case is safe to retry.",
|
|
2907
|
+
"Enqueue up to 1000 usage events for asynchronous processing. Items are validated synchronously up front; validated items are then enqueued via SQS for background deduction by workers. The response returns 200 (or 202) immediately and does not include balance information. On partial enqueue failure (some items fail to enqueue, others succeed), the endpoint still returns 200 (or 202) and logs the failures server-side; clients should NOT retry, because retrying re-enqueues the already-succeeded items. A 503 is returned only when zero items were successfully enqueued (queue entirely unavailable) — that case is safe to retry.",
|
|
2877
2908
|
body: "array",
|
|
2878
2909
|
fields: [],
|
|
2879
2910
|
},
|
|
@@ -4140,9 +4171,9 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
4140
4171
|
{
|
|
4141
4172
|
name: "events",
|
|
4142
4173
|
type: "json",
|
|
4143
|
-
required:
|
|
4174
|
+
required: false,
|
|
4144
4175
|
description:
|
|
4145
|
-
"The events sent to this webhook.
|
|
4176
|
+
"The events sent to this webhook. Leave it out to send every event. `vercel.*` events can't be mixed with other events.",
|
|
4146
4177
|
},
|
|
4147
4178
|
{
|
|
4148
4179
|
name: "description",
|
|
@@ -4211,7 +4242,7 @@ export const API_ROUTES: readonly ApiRoute[] = [
|
|
|
4211
4242
|
type: "json",
|
|
4212
4243
|
required: false,
|
|
4213
4244
|
description:
|
|
4214
|
-
"The events sent to this webhook.
|
|
4245
|
+
"The events sent to this webhook. Pass `[]` to send every event; omit it to keep the current list. `vercel.*` events can't be mixed with other events.",
|
|
4215
4246
|
},
|
|
4216
4247
|
{
|
|
4217
4248
|
name: "description",
|
package/src/generated/client.ts
CHANGED
|
@@ -97,8 +97,8 @@ webhooks: Array<{
|
|
|
97
97
|
id: string;
|
|
98
98
|
/** The https URL Autumn sends events to. Localhost and private-network addresses are rejected; tunnels such as ngrok work. */
|
|
99
99
|
url: string;
|
|
100
|
-
/** The events sent to this webhook.
|
|
101
|
-
events
|
|
100
|
+
/** The events sent to this webhook. Leave it out to send every event. `vercel.*` events can't be mixed with other events. Defaults to []. */
|
|
101
|
+
events?: Array<"customer.products.updated" | "customer.threshold_reached" | "balances.usage_alert_triggered" | "balances.limit_reached" | "billing.auto_topup_failed" | "billing.auto_topup_succeeded" | "billing.updated" | "invoice.finalized" | "vercel.resources.deleted" | "vercel.resources.provisioned" | "vercel.resources.rotate_secrets" | "vercel.webhooks.event">;
|
|
102
102
|
/** A note for your own reference. */
|
|
103
103
|
description?: string;
|
|
104
104
|
/** When true, no events are sent to the webhook. */
|
|
@@ -52515,7 +52515,7 @@ id: string;
|
|
|
52515
52515
|
url: string;
|
|
52516
52516
|
/** A note for your own reference. */
|
|
52517
52517
|
description: string | null;
|
|
52518
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52518
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52519
52519
|
events: Array<string>;
|
|
52520
52520
|
/** When true, no events are sent to the webhook. */
|
|
52521
52521
|
disabled: boolean;
|
|
@@ -52537,7 +52537,7 @@ id: string;
|
|
|
52537
52537
|
url: string;
|
|
52538
52538
|
/** A note for your own reference. */
|
|
52539
52539
|
description: string | null;
|
|
52540
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52540
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52541
52541
|
events: Array<string>;
|
|
52542
52542
|
/** When true, no events are sent to the webhook. */
|
|
52543
52543
|
disabled: boolean;
|
|
@@ -52556,7 +52556,7 @@ id: string;
|
|
|
52556
52556
|
url: string;
|
|
52557
52557
|
/** A note for your own reference. */
|
|
52558
52558
|
description: string | null;
|
|
52559
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52559
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52560
52560
|
events: Array<string>;
|
|
52561
52561
|
/** When true, no events are sent to the webhook. */
|
|
52562
52562
|
disabled: boolean;
|
|
@@ -52572,7 +52572,7 @@ id: string;
|
|
|
52572
52572
|
url: string;
|
|
52573
52573
|
/** A note for your own reference. */
|
|
52574
52574
|
description: string | null;
|
|
52575
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52575
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52576
52576
|
events: Array<string>;
|
|
52577
52577
|
/** When true, no events are sent to the webhook. */
|
|
52578
52578
|
disabled: boolean;
|
|
@@ -52591,7 +52591,7 @@ id: string;
|
|
|
52591
52591
|
url: string;
|
|
52592
52592
|
/** A note for your own reference. */
|
|
52593
52593
|
description: string | null;
|
|
52594
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52594
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52595
52595
|
events: Array<string>;
|
|
52596
52596
|
/** When true, no events are sent to the webhook. */
|
|
52597
52597
|
disabled: boolean;
|
|
@@ -52607,7 +52607,7 @@ id: string;
|
|
|
52607
52607
|
url: string;
|
|
52608
52608
|
/** A note for your own reference. */
|
|
52609
52609
|
description: string | null;
|
|
52610
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52610
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52611
52611
|
events: Array<string>;
|
|
52612
52612
|
/** When true, no events are sent to the webhook. */
|
|
52613
52613
|
disabled: boolean;
|
|
@@ -52626,7 +52626,7 @@ id: string;
|
|
|
52626
52626
|
url: string;
|
|
52627
52627
|
/** A note for your own reference. */
|
|
52628
52628
|
description: string | null;
|
|
52629
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52629
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52630
52630
|
events: Array<string>;
|
|
52631
52631
|
/** When true, no events are sent to the webhook. */
|
|
52632
52632
|
disabled: boolean;
|
|
@@ -52651,7 +52651,7 @@ id: string;
|
|
|
52651
52651
|
url: string;
|
|
52652
52652
|
/** A note for your own reference. */
|
|
52653
52653
|
description: string | null;
|
|
52654
|
-
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty
|
|
52654
|
+
/** The events sent to this webhook, as `WebhookEventType` names; a type newer than your client is returned as-is. Empty means the webhook receives every event. */
|
|
52655
52655
|
events: Array<string>;
|
|
52656
52656
|
/** When true, no events are sent to the webhook. */
|
|
52657
52657
|
disabled: boolean;
|
package/src/generated/emit.ts
CHANGED
|
@@ -1216,11 +1216,11 @@ export const SYNCED_LISTS: Readonly<Record<string, SyncedListSpec>> = {
|
|
|
1216
1216
|
builder: "webhook",
|
|
1217
1217
|
idField: "id",
|
|
1218
1218
|
responseIdField: "id",
|
|
1219
|
-
keys: ["id", "url", "events", "description", "disabled"],
|
|
1220
|
-
required: ["
|
|
1221
|
-
paths: ["description", "disabled", "events", "id", "url"],
|
|
1219
|
+
keys: ["id", "env", "url", "events", "description", "disabled"],
|
|
1220
|
+
required: ["env", "id", "url"],
|
|
1221
|
+
paths: ["description", "disabled", "env", "events", "id", "url"],
|
|
1222
1222
|
pull: true,
|
|
1223
|
-
|
|
1223
|
+
envField: "env",
|
|
1224
1224
|
},
|
|
1225
1225
|
};
|
|
1226
1226
|
|
|
@@ -94,11 +94,11 @@ export const branchSpecs = ({
|
|
|
94
94
|
spec.branches?.map((branch) => branchSpecOf({ spec, branch })) ?? [spec];
|
|
95
95
|
|
|
96
96
|
/** A list keyed by id outside the catalog: emitted like a collection item,
|
|
97
|
-
*
|
|
97
|
+
* one entry per environment. */
|
|
98
98
|
export type SyncedListSpec = CollectionSpec & {
|
|
99
99
|
readonly wireKey: string;
|
|
100
|
-
/**
|
|
101
|
-
readonly
|
|
100
|
+
/** The fixture field naming the entry's environment. */
|
|
101
|
+
readonly envField: string;
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
export type SingletonSpec = {
|
|
@@ -2206,30 +2206,41 @@ export const LINT_RULES: LintRules = {
|
|
|
2206
2206
|
webhooks: {
|
|
2207
2207
|
label: "webhook",
|
|
2208
2208
|
idField: "id",
|
|
2209
|
-
required: ["
|
|
2209
|
+
required: ["env", "id", "url"],
|
|
2210
2210
|
fields: {
|
|
2211
2211
|
id: {
|
|
2212
2212
|
minLength: 1,
|
|
2213
2213
|
maxLength: 256,
|
|
2214
2214
|
pattern: "^[a-zA-Z0-9_-]+$",
|
|
2215
2215
|
},
|
|
2216
|
-
|
|
2217
|
-
|
|
2216
|
+
env: {
|
|
2217
|
+
pattern: "^[a-z0-9_-]+$",
|
|
2218
|
+
},
|
|
2219
|
+
url: {
|
|
2220
|
+
pattern: "^[Hh][Tt][Tt][Pp][Ss]:\\/\\/",
|
|
2218
2221
|
},
|
|
2219
2222
|
},
|
|
2220
2223
|
rules: [
|
|
2224
|
+
{
|
|
2225
|
+
kind: "notMap",
|
|
2226
|
+
field: "url",
|
|
2227
|
+
because:
|
|
2228
|
+
'Each webhook() is one endpoint in one env: split into one webhook() per env, e.g. webhook({ id, env: "live", url }).',
|
|
2229
|
+
},
|
|
2221
2230
|
{
|
|
2222
2231
|
kind: "unique",
|
|
2223
2232
|
field: "id",
|
|
2233
|
+
alongside: "env",
|
|
2224
2234
|
because:
|
|
2225
|
-
"Two webhooks claiming one id race to define the same endpoint.",
|
|
2235
|
+
"Two webhooks claiming one id in one env race to define the same endpoint.",
|
|
2226
2236
|
},
|
|
2227
2237
|
{
|
|
2228
2238
|
kind: "unique",
|
|
2229
2239
|
field: "id",
|
|
2240
|
+
alongside: "env",
|
|
2230
2241
|
asEnvName: true,
|
|
2231
2242
|
because:
|
|
2232
|
-
"Each webhook's signing secret is saved
|
|
2243
|
+
"Each webhook's signing secret is saved under its id in an env var name, so these two would overwrite each other's secret. Rename one.",
|
|
2233
2244
|
},
|
|
2234
2245
|
{
|
|
2235
2246
|
kind: "rejects",
|
|
@@ -2245,13 +2256,6 @@ export const LINT_RULES: LintRules = {
|
|
|
2245
2256
|
because:
|
|
2246
2257
|
"vercel.* events can't be mixed with other events in one webhook: they're delivered from a separate app. Make one webhook for each.",
|
|
2247
2258
|
},
|
|
2248
|
-
{
|
|
2249
|
-
kind: "nonEmpty",
|
|
2250
|
-
field: "url",
|
|
2251
|
-
warning: true,
|
|
2252
|
-
because:
|
|
2253
|
-
"With no environment key the webhook is registered nowhere. Add `live`, `sandbox` or a sandbox's slug.",
|
|
2254
|
-
},
|
|
2255
2259
|
{
|
|
2256
2260
|
kind: "knownValues",
|
|
2257
2261
|
field: "events",
|
|
@@ -2274,12 +2278,4 @@ export const LINT_RULES: LintRules = {
|
|
|
2274
2278
|
},
|
|
2275
2279
|
],
|
|
2276
2280
|
},
|
|
2277
|
-
"webhooks.url": {
|
|
2278
|
-
keys: {
|
|
2279
|
-
pattern: "^[a-z0-9_-]+$",
|
|
2280
|
-
},
|
|
2281
|
-
values: {
|
|
2282
|
-
pattern: "^[Hh][Tt][Tt][Pp][Ss]:\\/\\/",
|
|
2283
|
-
},
|
|
2284
|
-
},
|
|
2285
2281
|
};
|
|
@@ -131,6 +131,12 @@ export type LintRule =
|
|
|
131
131
|
readonly warning?: true;
|
|
132
132
|
readonly because: string;
|
|
133
133
|
}
|
|
134
|
+
| {
|
|
135
|
+
/** A stated `field` must be a plain value, never an object map. */
|
|
136
|
+
readonly kind: "notMap";
|
|
137
|
+
readonly field: string;
|
|
138
|
+
readonly because: string;
|
|
139
|
+
}
|
|
134
140
|
| {
|
|
135
141
|
/** List `field` holds names starting with `prefix` only, or none of them. */
|
|
136
142
|
readonly kind: "uniformPrefix";
|
|
@@ -538,6 +544,10 @@ const entryRuleFailures = ({
|
|
|
538
544
|
)
|
|
539
545
|
.map((item) => `\`${item}\` ${rule.because}`);
|
|
540
546
|
}
|
|
547
|
+
case "notMap": {
|
|
548
|
+
const value = entry[rule.field];
|
|
549
|
+
return isEntry(value) ? [`${rule.field} is a map. ${rule.because}`] : [];
|
|
550
|
+
}
|
|
541
551
|
case "uniformPrefix": {
|
|
542
552
|
const value = entry[rule.field];
|
|
543
553
|
if (!Array.isArray(value)) return [];
|