fastify-ata 0.2.23 → 0.3.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,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="./assets/fastify-ata.svg" alt="fastify-ata" width="640" />
3
+ </p>
4
+
1
5
  # fastify-ata
2
6
 
3
7
  Fastify plugin for [ata-validator](https://ata-validator.com) - JSON Schema validation powered by simdjson.
@@ -44,11 +48,14 @@ All your existing JSON Schema route definitions work as-is.
44
48
 
45
49
  ```js
46
50
  fastify.register(fastifyAta, {
47
- coerceTypes: true, // convert "42" 42 for integer fields
51
+ coerceTypes: true, // convert "42" -> 42 for integer fields
48
52
  removeAdditional: true, // strip properties not in schema
53
+ abortEarly: true, // skip detailed error collection (faster invalid path)
49
54
  })
50
55
  ```
51
56
 
57
+ `abortEarly` replaces the error list with a shared stub. Good for public endpoints where only the accept/reject decision reaches the caller. On a 10-property schema the invalid path drops from roughly 15 ns/op to 3.7 ns/op.
58
+
52
59
  ## Standalone Mode (Pre-compiled)
53
60
 
54
61
  Drop-in replacement for `@fastify/ajv-compiler/standalone`. Same API.
@@ -107,37 +114,54 @@ Works with Fastify v5's Standard Schema support, tRPC, TanStack Form, Drizzle OR
107
114
 
108
115
  ## Performance
109
116
 
110
- ### Real-world HTTP benchmark (autocannon, 10 connections, 5s)
117
+ All numbers below are reproducible on M4 Pro / Node 25 with the benchmarks in this repo and in `ata-validator/benchmark`. Run-to-run noise is roughly +/- 5% at these scales.
111
118
 
112
- | Payload | ata | ajv | |
119
+ ### Fastify pipeline (autocannon, 10 connections, pipelining 10)
120
+
121
+ | Payload | ajv (default) | ata | delta |
113
122
  |---|---|---|---|
114
- | 1 user (0.1KB) | 65.7K req/sec | 65.7K req/sec | equal |
115
- | 10 users (0.9KB) | 57.2K | 55.3K | +3% |
116
- | 50 users (4.6KB) | 36.0K | 33.8K | +6% |
117
- | 100 users (9.1KB) | 24.6K | 22.6K | +9% |
123
+ | valid (10 fields) | ~70,000 req/s | ~70,500 req/s | tied |
124
+ | invalid (10 fields) | ~51,000 req/s | ~52,500 req/s | +3% |
125
+ | invalid (abortEarly) | ~51,000 req/s | ~52,800 req/s | +3.5% |
126
+
127
+ HTTP + JSON.parse + routing dominate the pipeline, so validator choice is small on throughput. The real difference is elsewhere.
118
128
 
119
- ### Where ata really shines
129
+ ### Where ata-validator moves the needle
120
130
 
121
- | Scenario | ata | ajv | |
131
+ | Scenario | ajv | ata | delta |
122
132
  |---|---|---|---|
123
- | **Constructor cold start** | 1.25M ops/sec | 873 ops/sec | **1,432x faster** |
124
- | **Serverless cold start** (50 schemas) | 0.1ms | 23ms | **242x faster** |
125
- | **First validation** (construct + validate) | 15.7K ops/sec | 855 ops/sec | **18x faster** |
126
- | **ReDoS protection** (catastrophic pattern) | 0.3ms | 765ms | **immune** |
127
- | **Batch NDJSON** (10K items, multi-core) | 13.4M/sec | 5.1M/sec | **2.6x faster** |
128
- | **validate(obj)** valid (isolated) | 14.6M ops/sec | 8.3M ops/sec | **1.8x faster** |
129
- | **validate(obj)** invalid (isolated) | 12.9M ops/sec | 8.0M ops/sec | **1.6x faster** |
130
- | **validateJSON(str)** valid | 2.1M ops/sec | 1.9M ops/sec | **1.1x faster** |
131
- | **Fastify startup** (5 routes) | 0.5ms | 6.0ms | **12x faster** |
132
- | **Schema compilation** | 136K ops/sec | 794 ops/sec | **171x faster** |
133
-
134
- ### Things only ata can do
135
-
136
- - **RE2 regex engine** - linear-time guaranteed, immune to ReDoS attacks
137
- - **Multi-core parallel validation** - NDJSON batch at 12.5M items/sec
138
- - **Standard Schema V1** - native support, ajv doesn't have it
139
- - **Lazy compilation** - near-zero constructor, 1,432x faster cold start
140
- - **171x faster compilation** - serverless cold starts, dynamic schemas
133
+ | **Serverless cold start** (10 routes, first request) | 12.4 ms | 0.5 ms | **24x faster** |
134
+ | **Startup** (200 routes) | 7.0 ms | 2.4 ms | **2.9x faster** |
135
+ | **Invalid validation** (with abortEarly) | ~15 ns/op | 3.7 ns/op | **4x faster** |
136
+ | **ReDoS pattern** `^(a+)+$` | 765 ms | 0.3 ms | **immune (RE2)** |
137
+
138
+ Serverless cold start is the scenario that matters for Vercel, Cloudflare Workers, Fly.io and similar platforms. On a long-running box the gap closes, so classic servers will not see a throughput jump.
139
+
140
+ ### Build-time compile (optional)
141
+
142
+ For browser / edge deployments, ata ships an `ata compile` CLI that turns a JSON Schema into a self-contained `.mjs` plus TypeScript declarations.
143
+
144
+ ```bash
145
+ npx ata compile schemas/user.json -o src/user.validator.mjs --name User
146
+ ```
147
+
148
+ A 10-field schema produces:
149
+
150
+ | Variant | Raw | Gzipped |
151
+ |---|---|---|
152
+ | ata runtime bundle | 117 KB | 27 KB |
153
+ | `ata compile` standard | 4.9 KB | **1.2 KB** |
154
+ | `ata compile --abort-early` | 1.3 KB | **0.6 KB** |
155
+
156
+ Generated file has zero runtime dependency on `ata-validator`. `isValid` is emitted as a TypeScript type predicate, so consumers get narrowing out of the box.
157
+
158
+ ### Features worth calling out
159
+
160
+ - **RE2 regex** - linear-time guaranteed, immune to catastrophic backtracking
161
+ - **simdjson** - SIMD-accelerated JSON parsing for buffer-input paths
162
+ - **Multi-core** - `countValid(ndjsonBuf)` validates many messages in one native call
163
+ - **Standard Schema V1** - native support, works with Fastify v5, tRPC, TanStack Form, Drizzle
164
+ - **Draft 2020-12 and Draft 7** - 98.5% compliance on the official JSON Schema Test Suite
141
165
 
142
166
  ## License
143
167
 
@@ -0,0 +1,28 @@
1
+ <svg width="100%" viewBox="0 0 1610 910" xmlns="http://www.w3.org/2000/svg" role="img" style="font-family: &quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;">
2
+ <title style="fill:rgb(0, 0, 0);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">fastify-ata</title>
3
+ <desc style="fill:rgb(0, 0, 0);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">Beyaz zemin üzerinde Fastify logosu ve ata yazısı</desc>
4
+
5
+ <rect x="0" y="0" width="1600" height="900" fill="#FFFFFF" style="fill:rgb(255, 255, 255);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
6
+
7
+ <!--
8
+ Kompozisyon: [FASTIFY LOGOSU] + "ata"
9
+ Logo harflerle aynı yükseklikte (optik olarak), yatay olarak akıyor.
10
+ Logonun aspect ratio'su 1:1 (300×300), ama görsel yoğunluğu sol tarafta.
11
+
12
+ Tipografi: ata — 240px, semibold, siyah
13
+ Logo yüksekliği yaklaşık 200px, ata harfleri ile baseline'da hizalı.
14
+
15
+ Layout:
16
+ [logo ~240px genişlik] [boşluk ~60px] "ata" [~330px genişlik]
17
+ Toplam ~630px, ortaya yerleşecek: x = (1600-630)/2 = 485
18
+ -->
19
+
20
+ <!-- Fastify logosu -->
21
+ <image x="410" y="330" width="260" height="260" href="data:image/png;base64,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" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
22
+
23
+ <!-- "ata" yazısı — logonun sağında, baseline hizalı -->
24
+ <g font-family="'IBM Plex Mono', 'Inter', -apple-system, monospace" fill="#0A0A0A" style="fill:rgb(10, 10, 10);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
25
+ <text x="730" y="520" font-size="240" font-weight="600" letter-spacing="-8" style="fill:rgb(10, 10, 10);stroke:none;color:rgb(255, 255, 255);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;IBM Plex Mono&quot;, Inter, -apple-system, monospace;font-size:240px;font-weight:600;text-anchor:start;dominant-baseline:auto">ata</text>
26
+ </g>
27
+
28
+ </svg>
package/index.d.ts CHANGED
@@ -1,14 +1,16 @@
1
1
  import { FastifyPluginCallback } from 'fastify'
2
2
 
3
3
  interface FastifyAtaOptions {
4
+ /** Convert "42" -> 42 for integer fields, etc. */
4
5
  coerceTypes?: boolean
6
+ /** Strip properties that are not declared in the schema. */
5
7
  removeAdditional?: boolean
6
8
  /**
7
- * Enable turbo mode: overrides the JSON content-type parser to receive
8
- * the raw Buffer and uses simdjson-backed validateJSON for validation
9
- * instead of V8's JSON.parse path. Incompatible with coerceTypes.
9
+ * Skip detailed error collection on validation failure. Returns a shared
10
+ * stub error object instead. Useful for high-throughput route guards that
11
+ * only care about reject/accept.
10
12
  */
11
- turbo?: boolean
13
+ abortEarly?: boolean
12
14
  }
13
15
 
14
16
  declare const fastifyAta: FastifyPluginCallback<FastifyAtaOptions>
package/index.js CHANGED
@@ -9,6 +9,7 @@ function fastifyAta(fastify, opts, done) {
9
9
  const validatorOpts = {
10
10
  coerceTypes: opts.coerceTypes || false,
11
11
  removeAdditional: opts.removeAdditional || false,
12
+ abortEarly: opts.abortEarly || false,
12
13
  }
13
14
 
14
15
  fastify.setValidatorCompiler(({ schema }) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fastify-ata",
3
- "version": "0.2.23",
4
- "description": "Fastify plugin for ata-validator beats ajv on every valid-path benchmark. 2.7x faster validate(obj), 151x faster compilation, simdjson + multi-core.",
3
+ "version": "0.3.1",
4
+ "description": "Fastify plugin for ata-validator. Runtime-competitive with the default, 24x faster serverless cold start, Standard Schema V1.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
@@ -19,15 +19,14 @@
19
19
  "ata-validator",
20
20
  "standard-schema"
21
21
  ],
22
- "author": "Mert Can Altin <mertcanaltin01@gmail.com>",
22
+ "author": "Mert Can Altin <mertgold60@gmail.com>",
23
23
  "license": "MIT",
24
24
  "bugs": {
25
25
  "url": "https://github.com/ata-core/fastify-ata/issues"
26
26
  },
27
27
  "homepage": "https://github.com/ata-core/fastify-ata#readme",
28
28
  "dependencies": {
29
- "ata-validator": "^0.11.0",
30
- "fastify-ata": "^0.2.21",
29
+ "ata-validator": "^0.12.2",
31
30
  "fastify-plugin": "^5.1.0",
32
31
  "sanitize-filename": "^1.6.4"
33
32
  },