33A TypeScript validation library for Protobuf messages using [ Spine Validation] ( https://github.com/SpineEventEngine/validation/ ) options,
44built on [ @bufbuild/protobuf ] ( https://github.com/bufbuild/protobuf-es ) (Protobuf-ES v2).
55
6- ---
6+ > ** π§ This library is in its experimental stage, the public API should not be considered stable. **
77
88## π‘ Why Use This?
99
@@ -19,15 +19,15 @@ This library lets you:
1919
2020### For New Users
2121
22- Even if you're not using Spine Event Engine, this library provides a powerful way to add runtime validation to your Protobuf-based TypeScript applications:
22+ Even if you're not using Spine Event Engine, this library provides a powerful way
23+ to add runtime validation to your Protobuf-based TypeScript applications:
2324
24- - β
** Define validation in ` .proto ` files** using declarative Spine validation options.
25+ - β
** Define validation in ` .proto ` files** using declarative [ Spine Validation options] ( https://github.com/SpineEventEngine/base-libraries/blob/master/base/src/main/proto/spine/options.proto ) .
2526- β
** Type-safe, runtime validation** for your Protobuf messages.
2627- β
** Clear, customizable error messages** for better UX.
2728- β
** Works with Protobuf-ES v2** and modern tooling.
2829- β
** Extensible architecture** for custom validation logic.
2930
30- ---
3131
3232## β¨ Features
3333
@@ -41,7 +41,7 @@ Even if you're not using Spine Event Engine, this library provides a powerful wa
4141- ** ` (validate) ` ** β Recursive nested message validation.
4242- ** ` (goes) ` ** β Field dependency constraints.
4343- ** ` (require) ` ** β Complex required field combinations with boolean logic.
44- - ** ` (choice) ` ** β Require that a oneof group has at least one field set.
44+ - ** ` (choice) ` ** β Require that a ` oneof ` group has at least one field set.
4545
4646** Developer Experience**
4747
@@ -56,111 +56,17 @@ Even if you're not using Spine Event Engine, this library provides a powerful wa
5656- ** ` (set_once) ` ** β Not currently supported. This option requires state tracking across multiple validations,
5757which is outside the scope of single-message validation.
5858
59- ---
60-
61- ## π Quick Start
62-
63- ### Prerequisites
6459
65- This library requires:
66- - ** [ Buf] ( https://buf.build/ ) ** for Protobuf code generation
67- - ** [ @bufbuild/protobuf ] ( https://github.com/bufbuild/protobuf-es ) ** (Protobuf-ES v2) for TypeScript/JavaScript runtime
60+ ## π Getting Started
6861
69- Your TypeScript code must be generated using Buf's Protobuf-ES code generator (` @bufbuild/protoc-gen-es ` ).
70- This library is specifically designed to work with Buf-generated TypeScript code and will not work out-of-the-box
71- with other Protobuf code generators.
62+ See the [ package-level README] ( packages/spine-validation-ts/README.md ) for complete installation instructions and usage guide.
7263
73- ### Installation
74-
75- This package is currently published as a ** pre-release (snapshot)** version.
76- Install it using the ` @snapshot ` dist-tag:
64+ ** Quick install:**
7765
7866``` bash
7967npm install @spine-event-engine/validation-ts@snapshot @bufbuild/protobuf
8068```
8169
82- To install a specific snapshot version:
83-
84- ``` bash
85- npm install @spine-event-engine/validation-ts@2.0.0-snapshot.3 @bufbuild/protobuf
86- ```
87-
88- > ** Note:** This library is in active development and therefore it is published as a snapshot.
89-
90- ### Usage Guide
91-
92- #### Step 1: Configure Buf for code generation
93-
94- Create a ` buf.gen.yaml ` file in your project root:
95-
96- ``` yaml
97- version : v2
98- plugins :
99- - remote : buf.build/protocolbuffers/es:v2.2.3
100- out : src/generated
101- ` ` `
102-
103- #### Step 2: Define validation in your Proto files
104-
105- Create your ` .proto` file with Spine validation options:
106-
107- ` ` ` protobuf
108- syntax = "proto3";
109-
110- import "spine/options.proto";
111-
112- message User {
113- string name = 1 [(required) = true];
114-
115- string email = 2 [
116- (required) = true,
117- (pattern).regex = "^[^@]+@[^@]+\\ .[^@]+$",
118- (pattern).error_msg = "Email must be valid. Provided: ` {value}`."
119- ];
120-
121- int32 age = 3 [
122- (min).value = "0",
123- (max).value = "150"
124- ];
125-
126- repeated string tags = 4 [(distinct) = true];
127- }
128- ```
129-
130- #### Step 3: Generate TypeScript code
131-
132- Run Buf to generate TypeScript code from your proto files:
133-
134- ``` bash
135- buf generate
136- ```
137-
138- This generates TypeScript schemas in ` src/generated/ ` that include all validation metadata.
139-
140- #### Step 4: Use Validation library in your TypeScript code
141-
142- ``` typescript
143- import { create } from ' @bufbuild/protobuf' ;
144- import { validate , Violations } from ' @spine-event-engine/validation-ts' ;
145- import { UserSchema } from ' ./generated/user_pb' ;
146-
147- const user = create (UserSchema , {
148- name: ' ' , // Missing required field
149- email: ' invalid-email' // Invalid pattern
150- });
151-
152- const violations = validate (UserSchema , user );
153-
154- if (violations .length > 0 ) {
155- violations .forEach (violation => {
156- const fieldPath = Violations .failurePath (violation );
157- const message = Violations .formatMessage (violation );
158-
159- console .error (` ${violation .typeName }.${fieldPath }: ${message } ` );
160- });
161- }
162- ```
163-
16470---
16571
16672## π¦ What's Included
@@ -184,13 +90,10 @@ validation-ts/
18490βββ README.md # You are here
18591```
18692
187- ---
18893
18994## π Documentation
19095
191- - ** [ Package README] ( packages/spine-validation-ts/README.md ) ** - Complete API documentation and usage guide.
192- - ** [ Descriptor API Guide] ( packages/spine-validation-ts/DESCRIPTOR_API_GUIDE.md ) ** - Working with message and field descriptors.
193- - ** [ Quick Reference] ( packages/spine-validation-ts/QUICK_REFERENCE.md ) ** - Cheat sheet for common operations.
96+ See the [ package-level README] ( packages/spine-validation-ts/README.md ) for more details.
19497
19598---
19699
@@ -230,108 +133,6 @@ npm run example
230133
231134---
232135
233- ## π Validation Options Reference
234-
235- ### Field-Level Options
236-
237- | Option | Description | Example |
238- | --------| -------------| ---------|
239- | ` (required) ` | Field must have a non-default value | ` [(required) = true] ` |
240- | ` (if_missing) ` | Custom error for missing field | ` [(if_missing).error_msg = "Name is required"] ` |
241- | ` (pattern) ` | Regex pattern matching | ` [(pattern).regex = "^[A-Z].*"] ` |
242- | ` (min) ` / ` (max) ` | Numeric minimum/maximum | ` [(min).value = "0", (max).value = "100"] ` |
243- | ` (range) ` | Bounded numeric range | ` [(range) = "[0..100]"] ` |
244- | ` (distinct) ` | Unique repeated elements | ` [(distinct) = true] ` |
245- | ` (validate) ` | Validate nested messages | ` [(validate) = true] ` |
246- | ` (goes) ` | Field dependency | ` [(goes).with = "other_field"] ` |
247-
248- ### Message-Level Options
249-
250- | Option | Description | Example |
251- | --------| -------------| ---------|
252- | ` (require) ` | Required field combinations | ` option (require).fields = "id \| email"; ` |
253-
254- ### Oneof-Level Options
255-
256- | Option | Description | Example |
257- | --------| -------------| ---------|
258- | ` (choice) ` | Require oneof to have a field set | ` option (choice).required = true; ` |
259-
260- ### Not Supported
261-
262- | Option | Status | Notes |
263- | --------| --------| -------|
264- | ` (if_invalid) ` | β Not supported | Deprecated field-level option |
265- | ` (set_once) ` | β Not supported | Requires state tracking across validations. See [ limitations] ( #-known-limitations ) |
266- | ` (if_set_again) ` | β Not supported | Companion to ` (set_once) ` |
267- | ` (is_required) ` | β Not supported | Deprecated. Use ` (choice) ` instead |
268- | ` (required_field) ` | β Not supported | Deprecated. Use ` (require) ` instead |
269-
270- ---
271-
272- ## β
Test Coverage
273-
274- The package includes comprehensive test coverage:
275-
276- - ** 200+ tests** across 11 test suites
277- - ** All validation options** thoroughly tested
278- - ** Integration tests** combining multiple constraints
279- - ** Edge cases** and real-world scenarios
280- - ** 100% coverage** of validation logic
281-
282- Test suites:
283- - Basic validation
284- - Required fields
285- - Pattern matching
286- - Min/Max constraints
287- - Range validation
288- - Distinct elements
289- - Nested validation
290- - Field dependencies (` goes ` )
291- - Required field combinations (` require ` )
292- - ` fneof ` validation (` choice ` )
293- - Integration scenarios
294-
295- ---
296-
297- ## π Working with Violations
298-
299- When validation fails, you can access detailed information from each violation:
300-
301- ``` typescript
302- import { validate , Violations } from ' @spine-event-engine/validation-ts' ;
303-
304- const violations = validate (UserSchema , user );
305-
306- violations .forEach (violation => {
307- // Use Violations utility object for easy access to violation details
308- const field = Violations .failurePath (violation );
309- const message = Violations .formatMessage (violation );
310-
311- console .error (` ${violation .typeName }.${field }: ${message } ` );
312-
313- // Example outputs:
314- // "User.name: A value must be set."
315- // "User.email: Email must be valid. Provided: `invalid-email`."
316- // "User.age: Value must be at least 0. Provided: -5."
317- // "User.tags: Values must be distinct. Duplicates found: [\"test\"]."
318- });
319- ```
320-
321- ---
322-
323- ## ποΈ Architecture
324-
325- The validation system is built with extensibility in mind:
326-
327- - ** ` validation.ts ` ** β Core validation engine using the visitor pattern
328- - ** ` options-registry.ts ` ** β Dynamic registration of validation options
329- - ** ` options/ ` ** β Modular validators for each Spine option
330- - ** Proto-first** β Validation rules defined in ` .proto ` files
331- - ** Type-safe** β Full TypeScript support with generated types
332-
333- ---
334-
335136## π€ Contributing
336137
337138Contributions are welcome! Please ensure:
@@ -351,7 +152,6 @@ Apache 2.0.
351152
352153## π Related Projects
353154
354- - [ Spine Event Engine] ( https://spine.io/ ) β Event-driven framework for CQRS/ES applications
355155- [ Protobuf-ES] ( https://github.com/bufbuild/protobuf-es ) β Protocol Buffers for ECMAScript
356156- [ Buf] ( https://buf.build/ ) β Modern Protobuf tooling
357157
0 commit comments