ianstormtaylor / superstruct Goto Github PK
View Code? Open in Web Editor NEWA simple and composable way to validate data in JavaScript (and TypeScript).
Home Page: https://docs.superstructjs.org
License: MIT License
A simple and composable way to validate data in JavaScript (and TypeScript).
Home Page: https://docs.superstructjs.org
License: MIT License
Where the keys are pre-determined, but the values are validated.
when setting 'string?' to nullable string field it throws error as;
TypeError: Expected a value of type
string | undefined
for field
Hi Ian, thanks for your work, Superstruct works great!
For the past days I was working with a library called Bumpover that deals data migration, whose data validation API relies on Superstruct. This library is usable for now, so how about adding its link to a "Showcase" or "Related" field in README? The more scenarios using Superstuct, the more popularized it is.
Similar to other interface implementations, and unlike the existing struct
, where it doesn't validate the entire shape of an object, but just ensures that certain properties are available.
To parallel, the default object
struct, only verifying existing properties, and not throwing for unknown properties passed in.
I think this needs to be separate from interface
, because interface
doesn't perform other checks.
It seems like now is impossible to declare custom error messages for user types
What if in this example I want to provide 2 different error messages, one for first check The provided {value} is not email
and other for length check Email can't be longer than 256 smbs
const struct = superstruct({
types: {
email: value => isEmail(value) && value.length < 256,
}
})
May you allow to provide a message in validate function via throw
or as a result? Or I just not found a solution.
Hi Ian, good to see you here, this library hits a pain point!
Previously I've involved in a JS library tracking user behaviour. For each site using it, site admins can configure tracking rules, which results in a dynamic schema to persist in DB. We picked JSON schema for that case, which works but looks verbose. So here comes the point: for dynamic schemas, can we serialize the struct
to an exchangeable format, them parsing them at runtime? As a side effect supporting this feature, even importing JSON schema as struct
seems possible.
Hope for your thoughts on this idea, thanks.
This is the opposite of coercion, and instead acts on the value after it has been normalized. This can also be useful in cases where you need data in a canonical representation, but you want to allow a few different ones. Although, this might be solved with coercion already
This line
Line 12 in 9dca528
Cannot convert object to primitive value
.
Modern js frameworks like to implement objects without prototype like:
const a = Object.create(null);
a.x = 1;
// The line below will fail with "Cannot convert object to primitive value"
const www = `jhjh ${a}`;
So every time I met an error in such object instead of superstruct error I get Cannot convert object to primitive value
.
I'll try to provide a fix
To get rid of the potential confusion between struct('object')
and struct.object
. The same way that struct('array')
and struct.list
are separated. Open to ideas for better names that shape
.
Edit: Actually record
may be a better name than shape.
Hello, I want to get your thoughts on potentially supporting async validation?
My use case: validating an object by querying a service that some key actually exists in backend.
const Config = struct.async({
name: val => val === 'a' || val === 'b',
key: k => axios.get(`/query-service/${k}`),
// ^ assume this Promise resolves 'abc' or rejects 'not found'
});
try {
const config = await Config({ name : 'a', key: 'some-existing-key' }) // {name: 'a', key: 'abc'}
} catch (err) {
console.log(err) // 'not found'
}
For requiring a value to be an instance of a particular class.
Hey @ianstormtaylor ๐
Thanks for your work on this!
Are you familiar with tcomb
? If so, would you mind raising any distinctions between superstruct
and tcomb
. ๐
I really like your library because I have used ajv and joi as well and I was frustrated from these libraries.
I would like to use your library with abstraction layer because I do not want to write types as string Because I will write typos like 'string' 'String' and others variants :)
I saw very nice abstraction on the top of ajv.
https://github.com/RomAnoX/ajv-schema-builder
What do you think about this idea?
Thank you
I wasn't able to find in the doc a clear reference example.
Like the jsonschema
feature: $ref: '#ext' // references another schema
What's the equivalent in superstruct?
Hello,
Is there a plan to add typescript/flow type definitions?
Thank you!
HATEOS should be HATEOAS
Hello, if I want to make the author field optional, what do I have to do with this basic piece of code ?
superstruct/examples/composing-structs.js
Line 17 in 07caeb2
const Article = struct({
id: 'number',
title: 'string',
created_at: 'date',
published_at: 'date?',
author: User,
})
What I would like to do is just add the question mark sign.
Thanks.
Following error is encountered when installing superstruct from ground.
Environment: macOS 10.13 / Node V8.3.0
โ superstruct git:(master) npm i
โ Installed 29 packages
โ Linked 441 latest versions
[fsevents] Success: "/Users/ewind/code/playground/superstruct/node_modules/[email protected]@fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile
โ Run 1 scripts
yarn run v1.0.2
$ yarn run build:es && yarn run build:cjs && yarn run build:max && yarn run build:min
./src/index.js โ ./lib/index.es.js...
created ./lib/index.es.js in 694ms
./src/index.js โ ./lib/index.js...
created ./lib/index.js in 1.2s
./src/index.js โ ./umd/superstruct.js...
created ./umd/superstruct.js in 821ms
/bin/sh: uglifyjs: command not found
./src/index.js โ stdout...
created stdout in 1.1s
Error: write EPIPE
at _errnoException (util.js:1022:11)
at WriteWrap.afterWrite (net.js:862:14)
error Command failed with exit code 127.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
โ Install fail! Error: Run "sh -c yarn run build" error, exit code 1
Error: Run "sh -c yarn run build" error, exit code 1
at ChildProcess.proc.on.code (/Users/ewind/.nvm/versions/node/v8.3.0/lib/node_modules/cnpm/node_modules/runscript/index.js:74:21)
at emitTwo (events.js:125:13)
at ChildProcess.emit (events.js:213:7)
at maybeClose (internal/child_process.js:927:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
This error message can be tracked to the build:min
script in package.json:
"build:min": "NODE_ENV=production rollup --config ./config/rollup-umd-min.js | uglifyjs > ./umd/superstruct.min.js",
This also results in error running yarn run build
:
โ superstruct git:(fix-build) yarn run build
yarn run v1.0.2
$ yarn run build:es && yarn run build:cjs && yarn run build:max && yarn run build:min
./src/index.js โ ./lib/index.es.js...
created ./lib/index.es.js in 637ms
./src/index.js โ ./lib/index.js...
created ./lib/index.js in 613ms
./src/index.js โ ./umd/superstruct.js...
created ./umd/superstruct.js in 582ms
/bin/sh: uglifyify: command not found
./src/index.js โ stdout...
created stdout in 619ms
Error: write EPIPE
at _errnoException (util.js:1022:11)
at WriteWrap.afterWrite (net.js:862:14)
error Command failed with exit code 127.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The uglifyify
dependency is missing bin
entry, leading error for npm scripts. I've raised an issue about this, while I suggest a minify config with rollup plugin can work better with less verbose config. I'm going to PR for it ๐
Which versions of node are supported? Currently due to dependencies only node 8+ is supported, is that intended?
error [email protected]: The engine "node" is incompatible with this module. Expected version ">=8".
This seems a lot like this library https://github.com/icebob/fastest-validator.
How would you compare superstruct's performance vs fastest-validator?
The examples show passing a function to defaults, however when I try to do so I receive the following:
TypeError: Expected a value of type `date` for `created_at` but received `() => new Date()`.
Is there any way to validate a property by cross-referencing other data values? i.e.
const schema = struct({
foo: 'string',
bah: (value, data) => !!(data.foo || value),
});
Hello, this is not an issue, but a question to discuss a little bit.
Have you met tcomb from Giulio Canti?
I wonder if it doesn't addresses all your concerns from this project README or if you considered it but noticed another short-coming or anything that made you start your own project.
Hello, I have a following script to showcase something I observed. If I have a list of union in my struct, and if one the of members didn't match a union, the path
/ value
points to the actual mismatching property that caused the union to break, but the type
only stops at the union level.
I'm not sure if this is intended behavior. In my real use case I have slightly more complex data structure, and the mismatch made it a little harder for me to figure out where the issue is. Can you advise?
const {struct} = require('superstruct');
const Cat = struct({
name: 'string',
meow: 'string',
});
const Dog = struct({
name: 'string',
bark: 'string'
});
const Pet = struct.union([Cat, Dog]);
const Home = struct({
pets: [Pet]
});
const homeData = {
pets: [
{ name: 'pluto', bark: 'woof' },
{ name: 'hello', meow: 'kitty' },
{ name: 'vlad', flap: 'bat flapping' },
]
};
try {
Home.assert(homeData);
} catch (err) {
console.error('message =', err.message);
console.error('type =', err.type);
console.error('path =', err.path);
console.error('value =', err.value);
console.error('errors =', err.errors);
}
This prints out
message = Expected a value of type `{name,meow} | {name,bark}` for `pets.2.flap` but received `bat flapping`.
# points to the union struct
type = {name,meow} | {name,bark}
# points to the prop that broke the union struct
path = [ 'pets', 2, 'flap' ]
# points to the prop that broke the union struct
value = bat flapping
errors = [ { data: { pets: [Array] },
path: [ 'pets', 2, 'flap' ],
value: 'bat flapping',
errors: [Circular],
type: '{name,meow} | {name,bark}' } ]
Thank you for publishing superstruct - amazing clarity.
I am defining schemas in YAML and using superstruct to validate. If I want to do bounds checking for integers, for example, I have to resort to using struct.function(). I can't use types for this scenario because only the value is passed in (edit) - and not the key of the validated data property. If the key were passed to the type validation function, I could bind to that function to look up the additional schema parameters I need.
Please consider if it would be a good idea or a bad idea to pass along additional parameters to the type validation function.
And let people destructure to check if there was an error. This way there's not an awkward need to check the return value's type to see if it was valid or not.
First off, props for the awesome library! Loving it so far ๐
Only hiccup I've had is there doesn't seem to be a way to tell if a value is a struct or not. There is the one method - but it's private: https://github.com/ianstormtaylor/superstruct/blob/eca567de5ac47debe0a9229d0f75c60afea3c8a4/src/is-struct.js
Is this something you'd be okay with exporting publicly?
It's pretty common to need a list of enums (eg. categories
) and the current syntax is:
struct([struct.enum([...])])
struct.list([struct.enum([...])])
I think it would be nice to have:
struct.enums([...])
Right now list structs are required to have a single element definition:
struct(['string'])
But there is a use case for tuples, where the element count is fixed. You wouldn't use this for single-element arrays, so we can make multi-element arrays the syntax for tuples. For example:
struct(['string', 'number'])
Would then require data that looks like:
['a', 1]
['b', 2]
...
This would make the case of validating arguments pretty simple too, for example:
const s = struct(['string', 'number', 'object'])
function myFunction(prefix, amount, options = {}) {
s.assert(arguments)
...
}
Hi, I'm wondering if superstruct can support recursive schema? For example
const BinaryTree = struct({
value: 'any',
left: struct.optional(BinaryTree),
right: struct.optional(BinaryTree),
});
Intuitively I feel this should be supported already, but I don't know of a way to implement, can you advise? Thanks!
For when you need a value to be an exact constant.
const User = struct({
id: 'number',
object: struct.constant('user'),
name: 'string',
email: 'string',
})
ฮป yarn run build
yarn run v1.3.2
$ yarn run build:lib && yarn run build:max && yarn run build:min
$ babel ./src --out-dir ./lib
src\default-types.js -> lib\default-types.js
src\index.js -> lib\index.js
src\struct-error.js -> lib\struct-error.js
src\superstruct.js -> lib\superstruct.js
$ mkdir -p ./dist && browserify ./src/index.js --transform babelify --standalone Superstruct > ./dist/superstruct.js
The syntax of the command is incorrect.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I'll try to work on this.
Hey
I checked the docs, but didn't find any info if this library is supposed to be used only to validate types of data or it can be used for other validations.
For example, I can check if value is a number. Is it possible and how to check, if this value is less than 100 or more than 6?
Using the string & number
syntax.
Hey, I have a question. Let's say I have this payload that I want to validate:
[
{ id: '1', name: 'John', age: 43 },
{ id: '2', name: 'Miranda' }
]
Then I would create a struct for each item:
const User = struct({
id: 'string',
name: 'string',
age: 'number?'
})
But since it's a list of users, how would I go about validating that? Is there a way to create a type that is a list of struct?
Hi,
I need help :(
I any option to validate full structute and return all errors?
My current solution show first found error in structure
Unexpected token: name (StructError) [./node_modules/superstruct/lib/index.es.js:7,0][index.ef29450fbb2e4dc5d2e2.js:147554,6]
This can sometimes be useful, for example when you require numbers, but a string of a number was passed in. If there was a coercion step before validation it would account for that.
First off awesome library. You have saved me from the muck of json schema!
I find myself having to call superstruct a lot to add date and email validation. I was wondering if it is possible, or could be possible, to extend the core struct instance to have additonal types defined for all structs.
I was doing a special exported struct that I consumed but having to know and manage the require path is getting a tiny bit hairy. Would love your thoughts on this?
When the data passed in has multiple validation errors, superstruct will throw upon the first error. I think it would be very much desirable to collect all errors and return them. That would make it much more useful, specially for large complex types with many fields.
When trying to nest TreeNode
structs like below I came up with error:
const Node = struct({
id: 'number',
children: [Node]
})
Maybe I'm missing something, so how can we support such kind of validation? I can such feature pretty handy in slate's schema, is slate going to has this library as dependency?
Me again ๐
When using a struct as the type for a property, it throws an error even if a default value is specified.
See it in action: https://runkit.com/embed/z10qks2qv2v1
const User = superstruct.struct({
id: 'number',
name: 'string',
})
const Article = superstruct.struct({
id: 'number',
title: 'string',
author: User,
}, {
author: {
id: 1000,
name: 'Owner',
},
})
// Passes as expected
Article({
id: 1,
title: 'This works as expected',
author: {
id: 2,
name: 'Contributor',
},
})
// Fails :(
Article({
id: 1,
title: 'This does not work!',
})
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.