@tightknitai/slack-block-kit-validator 0.1.0-alpha.1 → 0.1.7-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,24 @@
1
1
  # slack-block-kit-validator
2
2
 
3
3
  [![CI](https://github.com/TightknitAI/slack-block-kit-validator/actions/workflows/ci.yml/badge.svg)](https://github.com/TightknitAI/slack-block-kit-validator/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/TightknitAI/slack-block-kit-validator/branch/main/graph/badge.svg)](https://codecov.io/gh/TightknitAI/slack-block-kit-validator)
4
5
  [![npm version](https://img.shields.io/npm/v/@tightknitai/slack-block-kit-validator.svg)](https://www.npmjs.com/package/@tightknitai/slack-block-kit-validator)
6
+ [![bundle size](https://img.shields.io/bundlejs/size/@tightknitai/slack-block-kit-validator)](https://bundlejs.com/?q=%40tightknitai%2Fslack-block-kit-validator)
7
+ [![JSON Schema](https://img.shields.io/badge/JSON%20Schema-2020--12-blue)](https://json-schema.org/draft/2020-12/release-notes)
5
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
9
 
7
10
  JSON Schema (draft 2020-12) and validation helpers for Slack Block Kit JSON. Catches invalid block payloads before Slack silently swallows them.
8
11
 
12
+ **Try it live:** <https://block-kit-validator.tightknit.dev> — paste any payload, see every error in your browser.
13
+
9
14
  ## Why this exists
10
15
 
11
16
  Slack's API returns `200 OK` when you send malformed Block Kit JSON — the metadata is dropped and the message renders as plain text (or a modal opens blank). The only way to find out is to eyeball a real Slack channel. Slack hasn't open-sourced their validator.
12
17
 
13
18
  This package compiles every rule in <https://docs.slack.dev/reference/block-kit> into a single JSON Schema, plus a handful of helpers for the cross-payload rules JSON Schema can't express (duplicate `block_id`, cumulative markdown length, one-table-per-message, `focus_on_load` uniqueness, surface compatibility).
14
19
 
20
+ > Prefer an API call or an MCP server over an npm install? The repo also ships a Cloudflare Worker that exposes this package as a public, rate-limited HTTP endpoint plus a remote MCP server — see [`worker/`](./worker).
21
+
15
22
  ## Install
16
23
 
17
24
  ```sh
@@ -48,7 +55,7 @@ When `target` is `modal` or `home`, the surface-compatibility check is enforced
48
55
 
49
56
  ```ts
50
57
  validateBlockKit(blocks, { surface: "message" });
51
- // rejects input blocks, table on non-message surfaces, etc.
58
+ // rejects alert/file on messages, markdown/table on modals, etc.
52
59
  ```
53
60
 
54
61
  ### Example output
@@ -117,7 +124,7 @@ The schema uses `$defs` for every block, element, composition object, rich-text
117
124
  | `checkCumulativeMarkdownLength` | `(blocks) => string[]` | Sum of all `markdown` block text > 12,000 chars. |
118
125
  | `checkSingleTableBlock` | `(blocks) => string[]` | More than one `table` block per payload. |
119
126
  | `checkFocusOnLoadUniqueness` | `(blocks) => string[]` | More than one element with `focus_on_load: true` in a view (walks nested elements + accessories). |
120
- | `checkSurfaceCompatibility` | `(blocks, surface) => string[]` | Blocks not allowed on the target surface (e.g. `input` on message, `video` on modal, `file_input` outside modals). |
127
+ | `checkSurfaceCompatibility` | `(blocks, surface) => string[]` | Blocks not allowed on the target surface (e.g. `alert` on message, `markdown` on modal, `file_input` outside modals). |
121
128
  | `checkCardActionsMax` | `(blocks) => string[]` | More than `CARD_ACTIONS_MAX` action buttons on a card block. |
122
129
  | `checkNumberInputBounds` | `(blocks) => string[]` | `number_input` element with `min_value > max_value`. |
123
130
  | `checkResponseUrlEnabledContext` | `(blocks, surface?) => string[]` | `response_url_enabled` set in contexts that don't support it. |
@@ -155,27 +162,47 @@ Server-side rules that need app-config context or deep equality checks the schem
155
162
 
156
163
  `validateBlockKit` strips properties whose value is `undefined` before running Ajv. `JSON.stringify` drops these before the payload reaches Slack, so common builder patterns like `value: foo ?? undefined` are no-ops on the wire but would otherwise trip the schema's `additionalProperties: false`. Explicit `null` values are preserved — they survive `JSON.stringify` and may legitimately fail the schema.
157
164
 
158
- ## Runtime & bundle considerations
165
+ ## Entry points
159
166
 
160
- Ajv v8 + ajv-formats weigh ~50–60 KB gzipped, which is fine for Node test runs but noticeable in a Cloudflare Worker bundle. If you want runtime validation inside a Worker, use the package's `compile:standalone` script to emit a self-contained validator that doesn't import Ajv at runtime:
167
+ The package ships several entry points so you only pay for what you use:
161
168
 
162
- ```sh
163
- pnpm dlx ajv compile --spec=draft2020 --strict=false -c ajv-formats \
164
- -s node_modules/@tightknitai/slack-block-kit-validator/dist/slack-block-kit.schema.json \
165
- -o standalone-validator.js
169
+ | Entry | Pulls Ajv? | Use when |
170
+ |---|---|---|
171
+ | `@tightknitai/slack-block-kit-validator` | yes | The full wrapper. `validateBlockKit`, helpers, schema, types. |
172
+ | `@tightknitai/slack-block-kit-validator/helpers` | no | Just the pure helpers — compose with Zod, TypeBox, your own validator. |
173
+ | `@tightknitai/slack-block-kit-validator/schema` | no | Just `slackBlockKitSchema` as a JS module. |
174
+ | `@tightknitai/slack-block-kit-validator/schema.json` | no | The raw JSON Schema file (for non-JS consumers). |
175
+ | `@tightknitai/slack-block-kit-validator/standalone` | no — precompiled | Self-contained validators for environments where Ajv is too heavy (Cloudflare Workers, Deno deploy). Exports `validateBlocks`, `validateModal`, `validateHome`. |
176
+ | `@tightknitai/slack-block-kit-validator/types` | no — types only | TypeScript types generated from the schema. `Block`, `SectionBlock`, `ModalView`, etc. |
177
+
178
+ ```ts
179
+ // Worker-friendly: no Ajv at runtime
180
+ import { validateBlocks } from "@tightknitai/slack-block-kit-validator/standalone";
181
+
182
+ // Types straight from the schema (always in sync with what the validator accepts)
183
+ import type { Block, SectionBlock } from "@tightknitai/slack-block-kit-validator/types";
166
184
  ```
167
185
 
186
+ ## Runtime & bundle considerations
187
+
188
+ The wrapper entry pulls in Ajv v8 + ajv-formats. The standalone entry has no runtime dependencies (its Ajv usage is fully inlined at build time) but is larger as a single bundle.
189
+
168
190
  For most apps the recommended pattern is **validate in tests only** — use `validateBlockKit` in unit tests next to your block builders, and let CI catch regressions before they hit production.
169
191
 
170
- ## Keeping up with Slack
192
+ ## Hosted API & MCP
193
+
194
+ For when you'd rather call an endpoint than install the package:
195
+
196
+ - **`POST /v1/validate`** — JSON in / JSON out. Same return shape as `validateBlockKit`. OpenAPI 3.1 spec at `/openapi.json`.
197
+ - **Remote MCP server** — exposes a `validate_block_kit` tool over Streamable HTTP (`/mcp`) and SSE (`/sse`). Connects to Claude Code, Claude Desktop, and other MCP clients.
198
+
199
+ Hosted on Cloudflare Workers, rate-limited per IP via the Workers Rate Limiting binding. Source in [`worker/`](./worker); deployment + MCP client setup in [`worker/README.md`](./worker/README.md). For the interactive UI, the [live playground](https://block-kit-validator.tightknit.dev) covers that.
200
+
201
+ The published npm package is unaffected by the worker — install it directly for production / high-volume use to skip the network hop entirely.
171
202
 
172
- Slack adds new block types and fields over time. To update:
203
+ ## Contributing
173
204
 
174
- 1. Diff the latest at <https://docs.slack.dev/reference/block-kit> against the commit history of `src/slack-block-kit.schema.json`.
175
- 2. Add or amend the relevant `$defs/*` entry, including required / optional / maxLength / enum.
176
- 3. For new top-level blocks, add to `$defs/block.oneOf` and the `modal_view` / `home_view` inner arrays if applicable.
177
- 4. For new elements, add to the relevant parent-container whitelist (`actions_block_element`, `section_accessory_element`, `input_block_element`, `context_block_element`, or `context_actions_block_element`).
178
- 5. Add fixtures to `test/` covering both valid and invalid payloads.
205
+ See [MAINTAINING.md](./MAINTAINING.md) for how to keep the schema in sync with Slack's docs.
179
206
 
180
207
  ## License
181
208
 
@@ -0,0 +1,26 @@
1
+ import type { ErrorObject, ValidateFunction } from "ajv/dist/2020.js";
2
+ /**
3
+ * Look-aside validators keyed by `block.type`. Populated by the caller
4
+ * (validate-block-kit.ts) with one compiled validator per block def, so we
5
+ * can re-validate a misbehaving block against just its discriminator-matched
6
+ * branch and report focused errors instead of the full oneOf cascade.
7
+ */
8
+ export type FocusValidators = ReadonlyMap<string, ValidateFunction>;
9
+ /**
10
+ * Format AJV errors with normalized paths and friendly per-keyword messages.
11
+ *
12
+ * When a block fails its `oneOf` evaluation, AJV reports a failure against
13
+ * every branch (~80 errors for a single typo). We collapse this by
14
+ * re-validating each offending block against just the schema branch matching
15
+ * its declared `type`, replacing the union noise with the real reason that
16
+ * specific block didn't validate. Blocks whose `type` isn't a recognized block
17
+ * kind fall back to the raw (deduplicated) AJV output.
18
+ *
19
+ * @param errors - the raw `validator.errors` array from AJV
20
+ * @param root - the (normalized) input AJV ran against — used to read each
21
+ * block's `type` so we can pick the focused branch validator
22
+ * @param target - validation target, controls path-normalization rooting
23
+ * @param focusValidators - per-block-type compiled validators
24
+ */
25
+ export declare function formatAjvErrors(errors: readonly ErrorObject[], root: unknown, target: "blocks" | "modal" | "home", focusValidators: FocusValidators): string[];
26
+ //# sourceMappingURL=format-ajv-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-ajv-errors.d.ts","sourceRoot":"","sources":["../src/format-ajv-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAgHtE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAuDpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,EACnC,eAAe,EAAE,eAAe,GAC/B,MAAM,EAAE,CAwFV"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Convert a JSON-pointer instancePath into the user-facing `blocks[N].field`
3
+ * path the cross-payload helpers also use. RFC 6901 segment decoding is applied
4
+ * so `~1` / `~0` round-trip correctly.
5
+ *
6
+ * - target = "blocks": root is the blocks array → `/0/text` → `blocks[0].text`
7
+ * - target = "modal"/"home": root is the view → `/blocks/2/element` → `blocks[2].element`
8
+ */
9
+ const normalizePath = (instancePath, target) => {
10
+ if (!instancePath) {
11
+ return "(root)";
12
+ }
13
+ const segments = instancePath.split("/").slice(1).map(decodePointerSegment);
14
+ if (target === "blocks") {
15
+ if (segments.length === 0) {
16
+ return "(root)";
17
+ }
18
+ const head = segments[0];
19
+ const rest = segments.slice(1);
20
+ const idx = Number(head);
21
+ if (Number.isInteger(idx) && head !== "") {
22
+ return `blocks[${idx}]${formatTail(rest)}`;
23
+ }
24
+ return head + formatTail(rest);
25
+ }
26
+ if (segments.length === 0) {
27
+ return "(root)";
28
+ }
29
+ if (segments[0] === "blocks" && segments.length >= 2) {
30
+ const idx = Number(segments[1]);
31
+ if (Number.isInteger(idx) && segments[1] !== "") {
32
+ return `blocks[${idx}]${formatTail(segments.slice(2))}`;
33
+ }
34
+ }
35
+ return segments[0] + formatTail(segments.slice(1));
36
+ };
37
+ const decodePointerSegment = (seg) => seg.replace(/~1/g, "/").replace(/~0/g, "~");
38
+ const formatTail = (rest) => {
39
+ let out = "";
40
+ for (const seg of rest) {
41
+ const idx = Number(seg);
42
+ if (Number.isInteger(idx) && seg !== "") {
43
+ out += `[${idx}]`;
44
+ }
45
+ else {
46
+ out += `.${seg}`;
47
+ }
48
+ }
49
+ return out;
50
+ };
51
+ const lookupAt = (root, instancePath) => {
52
+ let node = root;
53
+ const segments = instancePath.split("/").slice(1).map(decodePointerSegment);
54
+ for (const seg of segments) {
55
+ if (node == null || typeof node !== "object") {
56
+ return undefined;
57
+ }
58
+ if (Array.isArray(node)) {
59
+ const idx = Number(seg);
60
+ if (!Number.isInteger(idx)) {
61
+ return undefined;
62
+ }
63
+ node = node[idx];
64
+ }
65
+ else {
66
+ node = node[seg];
67
+ }
68
+ }
69
+ return node;
70
+ };
71
+ const formatSingle = (err, path) => {
72
+ const params = (err.params ?? {});
73
+ switch (err.keyword) {
74
+ case "required":
75
+ return `${path}: missing required property '${String(params.missingProperty)}'`;
76
+ case "additionalProperties":
77
+ return `${path}: unknown property '${String(params.additionalProperty)}'`;
78
+ case "type":
79
+ return `${path}: expected ${String(params.type)}`;
80
+ case "const":
81
+ return `${path}: expected ${JSON.stringify(params.allowedValue)}`;
82
+ case "enum": {
83
+ const values = Array.isArray(params.allowedValues) ? params.allowedValues : [];
84
+ return `${path}: expected one of [${values.map((v) => JSON.stringify(v)).join(", ")}]`;
85
+ }
86
+ case "maxLength":
87
+ return `${path}: longer than ${String(params.limit)} characters`;
88
+ case "minLength":
89
+ return `${path}: shorter than ${String(params.limit)} characters`;
90
+ case "maxItems":
91
+ return `${path}: more than ${String(params.limit)} items`;
92
+ case "minItems":
93
+ return `${path}: fewer than ${String(params.limit)} items`;
94
+ case "minimum":
95
+ return `${path}: below minimum ${String(params.limit)}`;
96
+ case "maximum":
97
+ return `${path}: above maximum ${String(params.limit)}`;
98
+ case "pattern":
99
+ return `${path}: does not match ${String(params.pattern)}`;
100
+ case "format":
101
+ return `${path}: not a valid ${String(params.format)}`;
102
+ default:
103
+ return `${path}: ${err.message ?? "failed validation"}`;
104
+ }
105
+ };
106
+ /**
107
+ * Identify the canonical block-rooted path (`/N` for bare blocks, `/blocks/N`
108
+ * for views) for an error. Returns null for errors that aren't scoped to a
109
+ * particular block — they're emitted as-is.
110
+ */
111
+ const blockPathOf = (instancePath, target) => {
112
+ const segs = instancePath.split("/").slice(1);
113
+ if (target === "blocks") {
114
+ if (segs.length >= 1 && Number.isInteger(Number(segs[0])) && segs[0] !== "") {
115
+ return `/${segs[0]}`;
116
+ }
117
+ return null;
118
+ }
119
+ if (segs.length >= 2 && segs[0] === "blocks" && Number.isInteger(Number(segs[1])) && segs[1] !== "") {
120
+ return `/blocks/${segs[1]}`;
121
+ }
122
+ return null;
123
+ };
124
+ /**
125
+ * Apply umbrella `oneOf`/`anyOf` suppression and emit focused errors with
126
+ * their instancePath rewritten back into the original payload's coordinate
127
+ * space (`bp` is the block's `/N` or `/blocks/N` path). The umbrella keywords
128
+ * are dropped when other errors at the same instancePath (or deeper) are
129
+ * already in the bucket — those underlying errors say everything the umbrella
130
+ * does, with more detail.
131
+ */
132
+ const META_KEYWORDS = new Set(["oneOf", "anyOf", "if", "not"]);
133
+ const pushFocusedErrors = (focused, bp, target, push) => {
134
+ const detailedPaths = new Set();
135
+ for (const err of focused) {
136
+ if (!META_KEYWORDS.has(err.keyword)) {
137
+ detailedPaths.add(err.instancePath);
138
+ }
139
+ }
140
+ for (const err of focused) {
141
+ if (META_KEYWORDS.has(err.keyword)) {
142
+ const suppress = [...detailedPaths].some((p) => p === err.instancePath || p.startsWith(`${err.instancePath}/`));
143
+ if (suppress) {
144
+ continue;
145
+ }
146
+ }
147
+ const rewrittenPath = `${bp}${err.instancePath}`;
148
+ push(formatSingle({ ...err, instancePath: rewrittenPath }, normalizePath(rewrittenPath, target)));
149
+ }
150
+ };
151
+ /**
152
+ * Format AJV errors with normalized paths and friendly per-keyword messages.
153
+ *
154
+ * When a block fails its `oneOf` evaluation, AJV reports a failure against
155
+ * every branch (~80 errors for a single typo). We collapse this by
156
+ * re-validating each offending block against just the schema branch matching
157
+ * its declared `type`, replacing the union noise with the real reason that
158
+ * specific block didn't validate. Blocks whose `type` isn't a recognized block
159
+ * kind fall back to the raw (deduplicated) AJV output.
160
+ *
161
+ * @param errors - the raw `validator.errors` array from AJV
162
+ * @param root - the (normalized) input AJV ran against — used to read each
163
+ * block's `type` so we can pick the focused branch validator
164
+ * @param target - validation target, controls path-normalization rooting
165
+ * @param focusValidators - per-block-type compiled validators
166
+ */
167
+ export function formatAjvErrors(errors, root, target, focusValidators) {
168
+ // Group errors by block path so we can replace each block's union cascade
169
+ // with its focused-branch errors. Errors not scoped to a block (e.g. on the
170
+ // root array itself, or on the view's title) are kept as-is.
171
+ const byBlock = new Map();
172
+ const standalone = [];
173
+ for (const err of errors) {
174
+ const bp = blockPathOf(err.instancePath, target);
175
+ if (bp == null) {
176
+ standalone.push(err);
177
+ continue;
178
+ }
179
+ let bucket = byBlock.get(bp);
180
+ if (!bucket) {
181
+ bucket = [];
182
+ byBlock.set(bp, bucket);
183
+ }
184
+ bucket.push(err);
185
+ }
186
+ const out = [];
187
+ const seen = new Set();
188
+ const push = (msg) => {
189
+ if (!seen.has(msg)) {
190
+ seen.add(msg);
191
+ out.push(msg);
192
+ }
193
+ };
194
+ for (const err of standalone) {
195
+ push(formatSingle(err, normalizePath(err.instancePath, target)));
196
+ }
197
+ for (const [bp, bucket] of byBlock) {
198
+ const block = lookupAt(root, bp);
199
+ const blockType = block != null && typeof block === "object" && !Array.isArray(block)
200
+ ? block.type
201
+ : undefined;
202
+ const focus = typeof blockType === "string" ? focusValidators.get(blockType) : undefined;
203
+ if (focus) {
204
+ focus(block);
205
+ const focusedErrors = focus.errors ?? [];
206
+ pushFocusedErrors(focusedErrors, bp, target, push);
207
+ continue;
208
+ }
209
+ // No focus available — block.type is missing, non-string, or not a known
210
+ // kind. AJV will have emitted dozens of per-branch errors (each branch's
211
+ // const-on-type plus its own required fields). Collapse those into a
212
+ // single useful message keyed on what we know about block.type.
213
+ const blockPath = normalizePath(bp, target);
214
+ if (block != null && typeof block === "object" && !Array.isArray(block) && !("type" in block)) {
215
+ push(`${blockPath}: missing required property 'type'`);
216
+ continue;
217
+ }
218
+ if (typeof blockType === "string") {
219
+ // type is a string but isn't one of the 18 kinds we map.
220
+ push(`${blockPath}.type: '${blockType}' is not a recognized block kind`);
221
+ continue;
222
+ }
223
+ if (block != null && typeof block === "object" && !Array.isArray(block)) {
224
+ // type is present but the wrong shape.
225
+ const actual = blockType === null ? "null" : typeof blockType;
226
+ push(`${blockPath}.type: expected string, got ${actual}`);
227
+ continue;
228
+ }
229
+ // Block itself isn't an object — fall back to whatever shape errors AJV
230
+ // emitted (e.g. "expected object"), but skip meta-keyword umbrellas.
231
+ const concretePaths = new Set();
232
+ for (const err of bucket) {
233
+ if (!META_KEYWORDS.has(err.keyword)) {
234
+ concretePaths.add(err.instancePath);
235
+ }
236
+ }
237
+ for (const err of bucket) {
238
+ if (META_KEYWORDS.has(err.keyword)) {
239
+ const suppress = [...concretePaths].some((p) => p === err.instancePath || p.startsWith(`${err.instancePath}/`));
240
+ if (suppress) {
241
+ continue;
242
+ }
243
+ }
244
+ push(formatSingle(err, normalizePath(err.instancePath, target)));
245
+ }
246
+ }
247
+ return out;
248
+ }
249
+ //# sourceMappingURL=format-ajv-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-ajv-errors.js","sourceRoot":"","sources":["../src/format-ajv-errors.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"check-response-url-enabled-context.d.ts","sourceRoot":"","sources":["../../src/helpers/check-response-url-enabled-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAEhE,KAAK,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AACpE,KAAK,SAAS,GAAG;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;CACzB,CAAC;AAUF;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,CAgCnH"}
1
+ {"version":3,"file":"check-response-url-enabled-context.d.ts","sourceRoot":"","sources":["../../src/helpers/check-response-url-enabled-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAEhE,KAAK,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AACpE,KAAK,SAAS,GAAG;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;CACzB,CAAC;AAUF;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,CAqCnH"}
@@ -17,6 +17,11 @@ const hasResponseUrlEnabled = (node) => !!node &&
17
17
  export function checkResponseUrlEnabledContext(blocks, surface) {
18
18
  const errors = [];
19
19
  blocks.forEach((block, i) => {
20
+ // Normalization can leave `null` in array slots (matching JSON.stringify
21
+ // semantics) — guard before any property access.
22
+ if (block == null) {
23
+ return;
24
+ }
20
25
  // Section accessory — never a valid host.
21
26
  if (hasResponseUrlEnabled(block.accessory)) {
22
27
  errors.push(`blocks[${i}].accessory sets response_url_enabled — only valid on select menus inside input blocks in modals`);
@@ -1 +1 @@
1
- {"version":3,"file":"check-response-url-enabled-context.js","sourceRoot":"","sources":["../../src/helpers/check-response-url-enabled-context.ts"],"names":[],"mappings":"AAUA,MAAM,8BAA8B,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAE5F,MAAM,qBAAqB,GAAG,CAAC,IAA4B,EAAW,EAAE,CACtE,CAAC,CAAC,IAAI;IACN,IAAI,CAAC,oBAAoB,KAAK,IAAI;IAClC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;IAC7B,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,8BAA8B,CAAC,MAA4B,EAAE,OAA4B;IACvG,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,0CAA0C;QAC1C,IAAI,qBAAqB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,kGAAkG,CAC9G,CAAC;QACJ,CAAC;QACD,+CAA+C;QAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;gBAC/B,IAAI,qBAAqB,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC9B,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,cAAc,CAAC,wFAAwF,CACnH,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,uEAAuE;QACvE,qEAAqE;QACrE,yEAAyE;QACzE,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YAC1F,MAAM,YAAY,GAAG,OAAO,IAAI,aAAa,CAAC;YAC9C,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,mDAAmD,YAAY,mDAAmD,CAC9H,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"check-response-url-enabled-context.js","sourceRoot":"","sources":["../../src/helpers/check-response-url-enabled-context.ts"],"names":[],"mappings":"AAUA,MAAM,8BAA8B,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAE5F,MAAM,qBAAqB,GAAG,CAAC,IAA4B,EAAW,EAAE,CACtE,CAAC,CAAC,IAAI;IACN,IAAI,CAAC,oBAAoB,KAAK,IAAI;IAClC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;IAC7B,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,8BAA8B,CAAC,MAA4B,EAAE,OAA4B;IACvG,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,yEAAyE;QACzE,iDAAiD;QACjD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,0CAA0C;QAC1C,IAAI,qBAAqB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,kGAAkG,CAC9G,CAAC;QACJ,CAAC;QACD,+CAA+C;QAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;gBAC/B,IAAI,qBAAqB,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC9B,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,cAAc,CAAC,wFAAwF,CACnH,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,uEAAuE;QACvE,qEAAqE;QACrE,yEAAyE;QACzE,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YAC1F,MAAM,YAAY,GAAG,OAAO,IAAI,aAAa,CAAC;YAC9C,MAAM,CAAC,IAAI,CACT,UAAU,CAAC,mDAAmD,YAAY,mDAAmD,CAC9H,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export * from "./helpers/check-card-actions-max.js";
2
+ export * from "./helpers/check-cumulative-markdown-length.js";
3
+ export * from "./helpers/check-focus-on-load-uniqueness.js";
4
+ export * from "./helpers/check-number-input-bounds.js";
5
+ export * from "./helpers/check-response-url-enabled-context.js";
6
+ export * from "./helpers/check-single-table-block.js";
7
+ export * from "./helpers/check-surface-compatibility.js";
8
+ export * from "./helpers/find-duplicate-block-ids.js";
9
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAIA,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,wCAAwC,CAAC;AACvD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC"}
@@ -0,0 +1,12 @@
1
+ // Pure helper entry point: `@tightknitai/slack-block-kit-validator/helpers`.
2
+ // No Ajv at runtime — these helpers cover the cross-payload rules JSON Schema
3
+ // can't express, and can be composed with any other validator.
4
+ export * from "./helpers/check-card-actions-max.js";
5
+ export * from "./helpers/check-cumulative-markdown-length.js";
6
+ export * from "./helpers/check-focus-on-load-uniqueness.js";
7
+ export * from "./helpers/check-number-input-bounds.js";
8
+ export * from "./helpers/check-response-url-enabled-context.js";
9
+ export * from "./helpers/check-single-table-block.js";
10
+ export * from "./helpers/check-surface-compatibility.js";
11
+ export * from "./helpers/find-duplicate-block-ids.js";
12
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,+DAA+D;AAE/D,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,wCAAwC,CAAC;AACvD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,4 @@
1
- export * from "./helpers/check-card-actions-max.js";
2
- export * from "./helpers/check-cumulative-markdown-length.js";
3
- export * from "./helpers/check-focus-on-load-uniqueness.js";
4
- export * from "./helpers/check-number-input-bounds.js";
5
- export * from "./helpers/check-response-url-enabled-context.js";
6
- export * from "./helpers/check-single-table-block.js";
7
- export * from "./helpers/check-surface-compatibility.js";
8
- export * from "./helpers/find-duplicate-block-ids.js";
1
+ export * from "./helpers.js";
9
2
  export { default as slackBlockKitSchema } from "./slack-block-kit.schema.json";
10
3
  export * from "./validate-block-kit.js";
11
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,wCAAwC,CAAC;AACvD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAuB;AACrG,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAuB;AACrG,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- export * from "./helpers/check-card-actions-max.js";
2
- export * from "./helpers/check-cumulative-markdown-length.js";
3
- export * from "./helpers/check-focus-on-load-uniqueness.js";
4
- export * from "./helpers/check-number-input-bounds.js";
5
- export * from "./helpers/check-response-url-enabled-context.js";
6
- export * from "./helpers/check-single-table-block.js";
7
- export * from "./helpers/check-surface-compatibility.js";
8
- export * from "./helpers/find-duplicate-block-ids.js";
1
+ // Default entry point: `@tightknitai/slack-block-kit-validator`.
2
+ // Re-exports the full surface — Ajv-backed wrapper + helpers + raw schema.
3
+ // Tree-shake friendlier alternatives:
4
+ // - `/helpers` (pure helpers, no Ajv)
5
+ // - `/schema` (JSON schema only, no Ajv)
6
+ // - `/standalone` (precompiled validators, no Ajv at runtime)
7
+ // - `/types` (types only, generated from the schema)
8
+ export * from "./helpers.js";
9
9
  export { default as slackBlockKitSchema } from "./slack-block-kit.schema.json" with { type: "json" };
10
10
  export * from "./validate-block-kit.js";
11
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,wCAAwC,CAAC;AACvD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrG,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,2EAA2E;AAC3E,sCAAsC;AACtC,wCAAwC;AACxC,2CAA2C;AAC3C,gEAAgE;AAChE,uDAAuD;AAEvD,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrG,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { default as slackBlockKitSchema } from "./slack-block-kit.schema.json";
2
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAuB"}
package/dist/schema.js ADDED
@@ -0,0 +1,7 @@
1
+ // Schema-only entry: `@tightknitai/slack-block-kit-validator/schema`.
2
+ // Loads no Ajv runtime — for consumers wiring the schema into their own
3
+ // validator (TypeBox, Zod, another Ajv config, OpenAPI tooling, etc.).
4
+ // For non-JS consumers, the raw JSON is also available at
5
+ // `@tightknitai/slack-block-kit-validator/schema.json`.
6
+ export { default as slackBlockKitSchema } from "./slack-block-kit.schema.json" with { type: "json" };
7
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,wEAAwE;AACxE,uEAAuE;AACvE,0DAA0D;AAC1D,wDAAwD;AAExD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ // AUTO-GENERATED — DO NOT EDIT BY HAND.
2
+
3
+ export type StandaloneValidateFunction = ((data: unknown) => boolean) & {
4
+ errors?:
5
+ | {
6
+ instancePath: string;
7
+ schemaPath: string;
8
+ keyword: string;
9
+ params: Record<string, unknown>;
10
+ message?: string;
11
+ }[]
12
+ | null;
13
+ };
14
+
15
+ /** Validates a bare blocks array. */
16
+ export const validateBlocks: StandaloneValidateFunction;
17
+ /** Validates a modal view envelope. */
18
+ export const validateModal: StandaloneValidateFunction;
19
+ /** Validates a home view envelope. */
20
+ export const validateHome: StandaloneValidateFunction;