
Security News
Vite Releases Technical Preview of Rolldown-Vite, a Rust-Based Bundler
Vite releases Rolldown-Vite, a Rust-based bundler preview offering faster builds and lower memory usage as a drop-in replacement for Vite.
flow-validator
Advanced tools
Object validation with proper flow types and more.
npm install flow-validator
import { arrayOf, string, number, object, instanceOf, Type, Vobject, asyncArrayOf, tuple, takes, match } from 'flow-validator';
import { express } from 'flow-validator/express';
describe("readme code", () => {
it("works", () => {
// { name: string, age: ?number, toys: Array<string> }
const Person = object({
name: string,
age: number.optional(),
toys: arrayOf(string)
});
const fred = Person.parse({
name: "Fred",
age: 89,
toys: ["teddy bear", "shotgun"]
});
console.log(fred); // eslint-disable-line no-console
// Array<string> validated asynchronously
const InventoryObjects = asyncArrayOf(
string.async().refine(checkInventory)
);
const shoppingCart = InventoryObjects.parse(["AK47", "stuffed bunny"]);
shoppingCart.then(items => console.log(items)); // eslint-disable-line no-console
async function checkInventory(item: string, error): Promise<string> {
if (~["AK47", "stuffed bunny"].indexOf(item)) return item;
return Promise.reject(error("no supplies"));
}
// pattern matching -- MORE WORK NEEDED
// const x = match(1,
// number, n => new Date(n*2),
// Person, ({ name }) => [name, name]
// );
// (x: Date);
// express middleware example
const middleware = express.middleware(
object({ headers: object({ "my-custom-header": string }) }),
(req, res, next) => next()
);
// express endpoint matching middleware (inspired to Spring RequestMapping)
const requestMap1 = express.requestMapping(
object({ body: Person }),
(req, res) => res.json(req.body.age)
);
const requestMap2 = express.requestMapping(
object({ body: object({ username: string, password: string }) }),
(req, res) => {
/* authenticate */
}
);
// app.use('/user', requestMap1);
// app.use('/user', requestMap2);
const Contact = object({
name: string,
birth: string.toDate(),
email: string.isEmail().optional()
});
console.log(
// eslint-disable-line no-console
Contact.parse({
name: "fred",
birth: String(new Date()),
email: "gobi301@gmail.com"
})
);
// ensure functions params, useful on user input functions
const signUpUser = takes(string.isEmail(), number)(
(email, secretCoupon) =>
`user ${email} added with coupon: ${secretCoupon}`
);
signUpUser("gobi301@gmail.com", 666);
// Don't Repeat Yourself
// you can use a type of a defined schema, instead of
// var yogi: { name: string, age: ?number, toys: Array<string> }
var yogi: typeof Person.type;
// runtime introspection
const Name: Type<string> = Person.schema.name;
const Age: Type<?number> = Person.schema.age;
// const tup: [string, number, Date] = ...
const tup = tuple([string, number, instanceOf(Date)]).parse([
"hello",
4,
new Date()
]);
// { a: string, b: number, c: Array<string | number | Date>, d: string, e: Date }
const Schema = object({
a: string,
b: number.optional(),
c: arrayOf(string.or(number).or(instanceOf(Date))),
d: string
.refine((s, error) => {
// refinements must return the same type
if (/el/.test(s)) return s;
throw error(String(/el/)); // this throws proper error
})
.revalidate(), // add a revalidate if want to be sure not changed type during refinement
e: string.to(s => new Date(s)) // with .to() you can convert types
});
const toBeValidated = {
a: "hi",
c: [1, new Date(), "2017"],
d: "hello",
e: "Mon Feb 27 2017 10:00:15 GMT-0800 (PST)"
};
// validate input object, returns original object if valid, throws otherwise
// VType object has .validate() method that returns original object
// arrayOf, tuple, mapping, object, objectExact ha V prefixed variants,
// and can't contain validators that change input
Vobject({ a: string }).validate({ a: "hello" }) === toBeValidated; // = true
// same as validate, but it make a copy in case of: arrayOf, tuple, mapping, object, objectExact
// it can be used when using refinemnts that return not the original value
// and with .to() for conversions
Schema.parse(toBeValidated) === toBeValidated; // = false
// deepEqual(Schema.parse(toBeValidated), toBeValidated); // = true
// shortcuts
Vobject({ a: string }).isValid({ a: "hello" }); // : boolean
Vobject({ a: string }).validateResult({ a: "hello" }); // : { value: ... } | { error: ... }
Schema.parseResult(toBeValidated); // : { value: ... } | { error: ... }
// you can chain validators, to reuse them or check if your custom type converter works
string.to(s => new Date(s)).chain(instanceOf(Date));
// to get JSON serializable error report
try {
Schema.parse();
} catch (e) {
console.log(e.toJSON()); // eslint-disable-line no-console
}
// sometimes flow will not remember types, ex:
object({ x: number.to(n => new Date(n)) }).parse({ x: 4 }); // unknown type
// solution
const x2: Type<Date> = number.to(n => new Date(n));
object({ x2 }).parse({ x2: 4 }); // : { x: Date }
// type-safe composition
const str2num = (s: string) => Number(s);
const div = (n: number) => n / 2;
const num2str = (n: number) => String(n);
const str2arr = (s: string) => s.split("1");
const nonSense = string
.compose(str2num)
.compose(div)
.compose(num2str)
.compose(str2arr);
nonSense.parseResult("1234567890"); // : Array<string>
// you can convert sync type to async one
string.async();
});
});
if you do not want import the entire library, you can find single validators in
import { object } from 'flow-validator/sync/object';
or
import { asyncArrayOf } from 'flow-validator/async/asyncArrayOf';
Type | Flow syntax | Runtime type |
---|---|---|
string | string | string |
number | number | number |
boolean | boolean | boolean |
generic object | Object | objectType |
generic function | Function | Function |
instance of C | C | instanceOf(C) |
class of C | Class<C> | classOf(C) |
array | Array<A> | arrayOf(A) |
intersection | A & B | intersection(A, B) |
union | `A | B` |
literal | 's' | literal('s') |
optional | ?A | optional(A) |
map | { [key: A]: B } | mapping(A, B) |
refinement | ✘ | number.refine(n => { if (n > 10) return n; throw new Error(); }) |
object | { name: string } | object({ name: string }) |
exact object | `{ | name: string |
null | null | isNull |
undefined | void | isUndefined |
not checked | any | isAny |
all types | mixed | isMixed |
function | (a: A) => B | takes(A)(returns(B)(...)) |
Type | Refinements | Transformations |
---|---|---|
string | .isEmail() .isValidDate() .minLength() .maxLength() .regexp() | .toDate() |
for older versions:
git clone https://github.com/freddi301/flow-validator.git
cd flow-validator
yarn
npm run doc:serve
(open issue, include examples or links)
flow-io (checkout io-ts too for typescript)
FAQs
object validation with flow types and more
We found that flow-validator demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Vite releases Rolldown-Vite, a Rust-based bundler preview offering faster builds and lower memory usage as a drop-in replacement for Vite.
Research
Security News
A malicious npm typosquat uses remote commands to silently delete entire project directories after a single mistyped install.
Research
Security News
Malicious PyPI package semantic-types steals Solana private keys via transitive dependency installs using monkey patching and blockchain exfiltration.