Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gubu

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gubu - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

13

gubu.d.ts

@@ -68,6 +68,6 @@ declare const GUBU: {

declare const Optional: Builder;
declare const Empty: Builder;
declare const Any: Builder;
declare const None: Builder;
declare const One: Builder;
declare const Some: Builder;
declare const All: Builder;

@@ -81,5 +81,6 @@ declare const Before: Builder;

declare function buildize(invs?: any): ValSpec;
declare function gubuError(val: any, state: State, text?: string, why?: string): ErrDesc;
declare function makeErr(val: any, state: State, text?: string, why?: string): ErrDesc;
declare type GubuShape = (<T>(inroot?: T, inctx?: any) => T) & {
spec: () => any;
gubu: typeof GUBU;
};

@@ -94,2 +95,3 @@ declare type Gubu = typeof make & {

Define: typeof Define;
Empty: typeof Empty;
None: typeof None;

@@ -101,6 +103,5 @@ One: typeof One;

Required: typeof Required;
Some: typeof Some;
};
declare const G$: (spec: any) => ValSpec;
declare const gubu: Gubu;
declare const Gubu: Gubu;
declare const GAfter: Builder;

@@ -112,2 +113,3 @@ declare const GAll: Builder;

declare const GDefine: Builder;
declare const GEmpty: Builder;
declare const GNone: Builder;

@@ -119,4 +121,3 @@ declare const GOne: Builder;

declare const GRequired: Builder;
declare const GSome: Builder;
export type { Validate, Update, Context, Builder, ValSpec, State, };
export { gubu, G$, norm, buildize, gubuError, After, All, Any, Before, Closed, Define, None, One, Optional, Refer, Rename, Required, Some, GAfter, GAll, GAny, GBefore, GClosed, GDefine, GNone, GOne, GOptional, GRefer, GRename, GRequired, GSome, };
export { Gubu, G$, norm, buildize, makeErr, After, All, Any, Before, Closed, Define, Empty, None, One, Optional, Refer, Rename, Required, GAfter, GAll, GAny, GBefore, GClosed, GDefine, GEmpty, GNone, GOne, GOptional, GRefer, GRename, GRequired, };
"use strict";
/* Copyright (c) 2021 Richard Rodger, MIT License */
/* Copyright (c) 2021 Richard Rodger and other contributors, MIT License */
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -7,8 +7,10 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
exports.GSome = exports.GRequired = exports.GRename = exports.GRefer = exports.GOptional = exports.GOne = exports.GNone = exports.GDefine = exports.GClosed = exports.GBefore = exports.GAny = exports.GAll = exports.GAfter = exports.Some = exports.Required = exports.Rename = exports.Refer = exports.Optional = exports.One = exports.None = exports.Define = exports.Closed = exports.Before = exports.Any = exports.All = exports.After = exports.gubuError = exports.buildize = exports.norm = exports.G$ = exports.gubu = void 0;
exports.GRequired = exports.GRename = exports.GRefer = exports.GOptional = exports.GOne = exports.GNone = exports.GEmpty = exports.GDefine = exports.GClosed = exports.GBefore = exports.GAny = exports.GAll = exports.GAfter = exports.Required = exports.Rename = exports.Refer = exports.Optional = exports.One = exports.None = exports.Empty = exports.Define = exports.Closed = exports.Before = exports.Any = exports.All = exports.After = exports.makeErr = exports.buildize = exports.norm = exports.G$ = exports.Gubu = void 0;
/*
* NOTE: `undefined` is not considered a value or type, and thus means 'any'.
*/
// TODO: custom undefined handling?
// TODO: closed on array
// TODO: composable?
// TODO: function deref?
// TODO: test Some, or drop?
// TODO: BigInt spec roundtrip test

@@ -62,3 +64,3 @@ // TODO: Only - builder, exact values

function norm(spec) {
var _a, _b, _c, _d, _e, _f;
var _a, _b, _c, _d, _e, _f, _g;
// Is this a (possibly incomplete) ValSpec?

@@ -117,4 +119,11 @@ if (null != spec && ((_a = spec.$) === null || _a === void 0 ? void 0 : _a.gubu$)) {

}
else if (spec.gubu === GUBU || true === ((_d = spec.$) === null || _d === void 0 ? void 0 : _d.gubu)) {
let gs = (spec === null || spec === void 0 ? void 0 : spec.spec) ? spec.spec() : spec;
t = gs.t;
v = gs.v;
r = gs.r;
u = gs.u;
}
else if ((undefined === spec.prototype && Function === spec.constructor) ||
Function === ((_d = spec.prototype) === null || _d === void 0 ? void 0 : _d.constructor)) {
Function === ((_e = spec.prototype) === null || _e === void 0 ? void 0 : _e.constructor)) {
t = 'custom';

@@ -126,3 +135,3 @@ b = v;

r = true;
u.n = (_f = (_e = v.prototype) === null || _e === void 0 ? void 0 : _e.constructor) === null || _f === void 0 ? void 0 : _f.name;
u.n = (_g = (_f = v.prototype) === null || _f === void 0 ? void 0 : _f.constructor) === null || _g === void 0 ? void 0 : _g.name;
u.i = v;

@@ -306,3 +315,3 @@ }

if ('none' === t) {
terr.push(makeErr('none', sval, path, dI, vs, 1070));
terr.push(makeErrImpl('none', sval, path, dI, vs, 1070));
}

@@ -313,3 +322,3 @@ else if ('object' === t) {

if (vs.r && undefined === sval) {
terr.push(makeErr('required', sval, path, dI, vs, 1010));
terr.push(makeErrImpl('required', sval, path, dI, vs, 1010));
}

@@ -322,3 +331,3 @@ else if (

// console.log('SVAL Q')
terr.push(makeErr('type', sval, path, dI, vs, 1020));
terr.push(makeErrImpl('type', sval, path, dI, vs, 1020));
}

@@ -335,7 +344,7 @@ else {

if (vs.r && undefined === sval) {
terr.push(makeErr('required', sval, path, dI, vs, 1030));
terr.push(makeErrImpl('required', sval, path, dI, vs, 1030));
}
// else if (null != sval && !Array.isArray(sval)) {
else if (undefined !== sval && !Array.isArray(sval)) {
terr.push(makeErr('type', sval, path, dI, vs, 1040));
terr.push(makeErrImpl('type', sval, path, dI, vs, 1040));
}

@@ -365,3 +374,3 @@ else {

{
terr.push(makeErr('type', sval, path, dI, vs, 1050));
terr.push(makeErrImpl('type', sval, path, dI, vs, 1050));
pass = false;

@@ -372,3 +381,3 @@ }

if (vs.r) {
terr.push(makeErr('required', sval, path, dI, vs, 1060));
terr.push(makeErrImpl('required', sval, path, dI, vs, 1060));
pass = false;

@@ -381,2 +390,12 @@ }

}
// Empty strings fail if string is required. Use Empty to allow.
else if ('string' === t && '' === sval) {
if (vs.r && !vs.u.empty) {
terr.push(makeErrImpl('required', sval, path, dI, vs, 1080));
}
// Optional empty strings take the default, unless Empty allows.
else if (!vs.u.empty) {
src[key] = vs.v;
}
}
}

@@ -457,2 +476,3 @@ if (vs.a) {

};
gubuShape.gubu = GUBU;
return gubuShape;

@@ -479,3 +499,3 @@ }

else {
state.terr.push(makeErr(w, sval, state.path, state.dI, state.node, 1040));
state.terr.push(makeErrImpl(w, sval, state.path, state.dI, state.node, 1040));
}

@@ -503,2 +523,8 @@ update.pass = false;

exports.Optional = Optional;
const Empty = function (spec) {
let vs = buildize(this || spec);
vs.u.empty = true;
return vs;
};
exports.Empty = Empty;
// Optional value provides default.

@@ -537,5 +563,2 @@ const Any = function (spec) {

exports.One = One;
// Pass if some match, but always check each one - does *not* short circuit.
const Some = makeListBuilder('some');
exports.Some = Some;
// Pass only if all match. Short circuits.

@@ -581,3 +604,3 @@ const All = makeListBuilder('all');

update.err =
makeErr('closed', val, state.path, state.dI, vs, 3010, '', { k });
makeErrImpl('closed', val, state.path, state.dI, vs, 3010, '', { k });
return false;

@@ -653,16 +676,25 @@ }

return Object.assign(vs, {
Required,
Optional,
After,
All,
Any,
Before,
Closed,
Before,
After,
Define,
Empty,
None,
One,
Optional,
Refer,
Rename,
Required,
});
}
exports.buildize = buildize;
function gubuError(val, state, text, why) {
return makeErr(why || 'custom', val, state.path, state.dI, state.node, 4000, text);
// External utility to make ErrDesc objects.
function makeErr(val, state, text, why) {
return makeErrImpl(why || 'custom', val, state.path, state.dI, state.node, 4000, text);
}
exports.gubuError = gubuError;
function makeErr(why, sval, path, dI, node, mark, text, user, fname) {
exports.makeErr = makeErr;
// Internal utility to make ErrDesc objects.
function makeErrImpl(why, sval, path, dI, node, mark, text, user, fname) {
let err = {

@@ -723,8 +755,9 @@ n: node,

Define,
Empty,
None,
One,
Optional,
Refer,
Rename,
Required,
Some,
});

@@ -734,4 +767,4 @@ Object.defineProperty(make, 'name', { value: 'gubu' });

exports.G$ = G$;
const gubu = make;
exports.gubu = gubu;
const Gubu = make;
exports.Gubu = Gubu;
const GAfter = After;

@@ -749,2 +782,4 @@ exports.GAfter = GAfter;

exports.GDefine = GDefine;
const GEmpty = Empty;
exports.GEmpty = GEmpty;
const GNone = None;

@@ -762,4 +797,2 @@ exports.GNone = GNone;

exports.GRequired = GRequired;
const GSome = Some;
exports.GSome = GSome;
//# sourceMappingURL=gubu.js.map

@@ -1,2 +0,2 @@

/* Copyright (c) 2021 Richard Rodger, MIT License */
/* Copyright (c) 2021 Richard Rodger and other contributors, MIT License */

@@ -7,4 +7,7 @@ /*

// TODO: custom undefined handling?
// TODO: closed on array
// TODO: composable?
// TODO: function deref?
// TODO: test Some, or drop?
// TODO: BigInt spec roundtrip test

@@ -235,2 +238,9 @@ // TODO: Only - builder, exact values

}
else if (spec.gubu === GUBU || true === spec.$?.gubu) {
let gs = spec?.spec ? spec.spec() : spec
t = (gs as ValSpec).t
v = gs.v
r = gs.r
u = gs.u
}
else if (

@@ -466,3 +476,3 @@ (undefined === spec.prototype && Function === spec.constructor) ||

if ('none' === t) {
terr.push(makeErr('none', sval, path, dI, vs, 1070))
terr.push(makeErrImpl('none', sval, path, dI, vs, 1070))
}

@@ -474,3 +484,3 @@ else if ('object' === t) {

if (vs.r && undefined === sval) {
terr.push(makeErr('required', sval, path, dI, vs, 1010))
terr.push(makeErrImpl('required', sval, path, dI, vs, 1010))
}

@@ -487,3 +497,3 @@ else if (

// console.log('SVAL Q')
terr.push(makeErr('type', sval, path, dI, vs, 1020))
terr.push(makeErrImpl('type', sval, path, dI, vs, 1020))
}

@@ -501,7 +511,7 @@ else {

if (vs.r && undefined === sval) {
terr.push(makeErr('required', sval, path, dI, vs, 1030))
terr.push(makeErrImpl('required', sval, path, dI, vs, 1030))
}
// else if (null != sval && !Array.isArray(sval)) {
else if (undefined !== sval && !Array.isArray(sval)) {
terr.push(makeErr('type', sval, path, dI, vs, 1040))
terr.push(makeErrImpl('type', sval, path, dI, vs, 1040))
}

@@ -535,3 +545,3 @@ else {

{
terr.push(makeErr('type', sval, path, dI, vs, 1050))
terr.push(makeErrImpl('type', sval, path, dI, vs, 1050))
pass = false

@@ -543,3 +553,3 @@ }

if (vs.r) {
terr.push(makeErr('required', sval, path, dI, vs, 1060))
terr.push(makeErrImpl('required', sval, path, dI, vs, 1060))
pass = false

@@ -552,2 +562,13 @@ }

}
// Empty strings fail if string is required. Use Empty to allow.
else if ('string' === t && '' === sval) {
if (vs.r && !vs.u.empty) {
terr.push(makeErrImpl('required', sval, path, dI, vs, 1080))
}
// Optional empty strings take the default, unless Empty allows.
else if (!vs.u.empty) {
src[key] = vs.v
}
}
}

@@ -641,2 +662,5 @@

gubuShape.gubu = GUBU
return gubuShape

@@ -668,3 +692,3 @@ }

else {
state.terr.push(makeErr(
state.terr.push(makeErrImpl(
w, sval, state.path, state.dI, state.node, 1040))

@@ -698,3 +722,10 @@ }

const Empty: Builder = function(this: ValSpec, spec?: any) {
let vs = buildize(this || spec)
vs.u.empty = true
return vs
}
// Optional value provides default.

@@ -739,5 +770,2 @@ const Any: Builder = function(this: ValSpec, spec?: any) {

// Pass if some match, but always check each one - does *not* short circuit.
const Some: Builder = makeListBuilder('some')
// Pass only if all match. Short circuits.

@@ -792,3 +820,3 @@ const All: Builder = makeListBuilder('all')

update.err =
makeErr('closed', val, state.path, state.dI, vs, 3010, '', { k })
makeErrImpl('closed', val, state.path, state.dI, vs, 3010, '', { k })
return false

@@ -890,8 +918,15 @@ }

return Object.assign(vs, {
Required,
Optional,
After,
All,
Any,
Before,
Closed,
Before,
After,
Define,
Empty,
None,
One,
Optional,
Refer,
Rename,
Required,
})

@@ -901,4 +936,5 @@ }

function gubuError(val: any, state: State, text?: string, why?: string) {
return makeErr(
// External utility to make ErrDesc objects.
function makeErr(val: any, state: State, text?: string, why?: string) {
return makeErrImpl(
why || 'custom',

@@ -914,3 +950,5 @@ val,

function makeErr(
// Internal utility to make ErrDesc objects.
function makeErrImpl(
why: string,

@@ -987,3 +1025,6 @@ sval: any,

(<T>(inroot?: T, inctx?: any) => T) &
{ spec: () => any }
{
spec: () => any,
gubu: typeof GUBU
}

@@ -998,8 +1039,9 @@

Define,
Empty,
None,
One,
Optional,
Refer,
Rename,
Required,
Some,
})

@@ -1017,2 +1059,3 @@

Define: typeof Define
Empty: typeof Empty
None: typeof None

@@ -1024,3 +1067,2 @@ One: typeof One

Required: typeof Required
Some: typeof Some
}

@@ -1034,3 +1076,3 @@

const gubu: Gubu = (make as Gubu)
const Gubu: Gubu = (make as Gubu)

@@ -1044,2 +1086,3 @@

const GDefine = Define
const GEmpty = Empty
const GNone = None

@@ -1051,6 +1094,4 @@ const GOne = One

const GRequired = Required
const GSome = Some
export type {

@@ -1066,7 +1107,7 @@ Validate,

export {
gubu,
Gubu,
G$,
norm,
buildize,
gubuError,
makeErr,

@@ -1079,2 +1120,3 @@ After,

Define,
Empty,
None,

@@ -1086,3 +1128,2 @@ One,

Required,
Some,

@@ -1095,2 +1136,3 @@ GAfter,

GDefine,
GEmpty,
GNone,

@@ -1102,6 +1144,4 @@ GOne,

GRequired,
GSome,
}
{
"name": "gubu",
"version": "0.0.2",
"description": "gubu",
"version": "0.0.3",
"description": "An object shape validation utility.",
"main": "gubu.js",

@@ -38,8 +38,7 @@ "type": "commonjs",

"@types/jest": "^27.0.3",
"jest": "^27.4.3",
"jest": "^27.4.5",
"ts-jest": "^27.1.1",
"typescript": "^4.5.2",
"jsonic": "github:jsonicjs/jsonic#nextgen"
"typescript": "^4.5.4"
},
"dependencies": {}
}

@@ -1,2 +0,229 @@

# gubu
gubu
# Gubu: An object shape validation utility.
NOTE: WORK IN PROGRESS
This is a schema validator in the tradition of [Joi](https://joi.dev) or any JSON-Schema validator, with the key features:
* Schemas are WYSIWYG - you define a schema with a template matching your object strucure;
* Covers the most useful cases in a natural way - in particular, defaults are specified directly and the type is inferred from the default;
* Very light and easily extensible.
Why write yet another validator? I've used `Joi` for a long time, but
always found its schema definition a little verbose at the syntax
level. I've never liked JSON-Schema - it's just too noisy to
eyeball. What I do like is [Vue.js property
validation](https://vuejs.org/v2/guide/components-props.html#Prop-Validation),
but that only works at the top level.
I needed this validator for two cases: adding message validation to
the [Seneca microservices framework](https://senecajs.org), and
providing deep defaults for complex custom Vue.js components.
[![npm version](https://img.shields.io/npm/v/gubu.svg)](https://npmjs.com/package/gubu)
[![build](https://github.com/rjrodger/gubu/actions/workflows/build.yml/badge.svg)](https://github.com/rjrodger/gubu/actions/workflows/build.yml)
[![Coverage Status](https://coveralls.io/repos/github/rjrodger/gubu/badge.svg?branch=main)](https://coveralls.io/github/rjrodger/gubu?branch=main)
[![Known Vulnerabilities](https://snyk.io/test/github/rjrodger/gubu/badge.svg)](https://snyk.io/test/github/rjrodger/gubu)
[![DeepScan grade](https://deepscan.io/api/teams/5016/projects/19459/branches/505694/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=5016&pid=19459&bid=505694)
[![Maintainability](https://api.codeclimate.com/v1/badges/ee603417bbb953d35ebe/maintainability)](https://codeclimate.com/github/rjrodger/gubu/maintainability)
| ![Voxgig](https://www.voxgig.com/res/img/vgt01r.png) | This open source module is sponsored and supported by [Voxgig](https://www.voxgig.com). |
|---|---|
## Quick Example
```js
const { Gubu } = require('gubu')
// Property a is optional, must be a Number, and defaults to 1.
// Property b is required, and must be a String.
const shape = Gubu({ a: 1, b: String })
// Object shape is good! Prints `{ a: 99, b: 'foo' }`
console.log( shape({ a: 99, b: 'foo' }) )
// Object shape is also good. Prints `{ a: 1, b: 'foo' }`
console.log( shape({ b: 'foo' }) )
// Object shape is bad. Throws an exception:
// "TODO: msg"
console.log( shape({ a: 'BAD' }) )
```
Use the exported `Gubu` function to create a validation function that
checks the first argument for validity - does it match the schema shape?
## Install
```sh
$ npm install gubu
```
## Usage
The *Gubu* module has no dependencies. A single function named `Gubu` is exported.
### TypeScript
*Gubu* is written in TypeScript, and can be imported naturally:
```
import { Gubu } from 'gubu'
```
### Browser
TODO
### Shape Rules
The general principle is that the schema shape should match valid
object as closely as possible.
For scalar values you can provide a native type object to make the value required:
* `Gubu(String)` matches strings: `'foo'`
* `Gubu(Number)` matches numbers: `123`
* `Gubu(Boolean)` matches booleans: `true`
Empty strings are not considered to be valid if a string is required
(this is usually what you want). To allow empty string, use
`Gubu(Empty(String))` (where `Empty` is exported by the `Gubu` module).
Or defaults to make the value optional:
* `Gubu('bar')` matches strings: `'foo'`, and `undefined` (becoming `'bar'`), but not `null`
* `Gubu(0)` matches numbers: `123`, and `undefined` (becoming `0`), but not `null`
* `Gubu(false)` matches booleans: `true`, and `undefined` (becoming `false`), but not `null`
The values `null` and `NaN` must match exactly. The value `undefined`
is special - it literally means no value.
For objects, write them as you want them:
```
let shape = Gubu({
foo: {
bar: {
zed: String,
qaz: Number,
}
}
})
```
For arrays, the first elements is treated as the shape that all elements must match:
* `Gubu([String])` matches `['a', 'b', 'c']`
* `Gubu([{x:1}])` matches `[{x: 11}, {x: 22}, {x: 33}]`
Elements after the first are treated a special cases, defined specific
shapes for each element (offset by 1):
* `Gubu([String,Number])` matches `[1, 'b', 'c']` - the first element is a `Number`, the rest `Strings`.
You can specify custom validation using functions:
* `Gubu({a: (v) => 10<v })`: matches `{a: 11}` as `10 < 11`
And you can manipulate the value if you need to:
* `Gubu({a: (v,u) => 10<v ? (u.val=2*v, true) : false })`: matches `{a: 11}` as `10 < 11` and returns `{a: 22}`.
You can also compose validations together:
```
const shape = Gubu({ a: Gubu({ x: Number }) })
// Matches { a: { x: 1 } } as expected
shape({ a: { x: 1 } })
```
*Gubu* exports shape "builder" utility functions that let you further
refine the shape (You've already seen the `Empty` builder above that
allows strings to be empty). Wrap your value with the function
in-place in the shape.
The `Required` builder makes a value required:
```
const { Gubu, Required } = require(`gubu`)
const shape = Gubu({
a: Required({x: 1}) // Property `a` is required and must match `{x: 1}`.
})
```
The `Closed` builder prohibits an object from having additional unspecified properties:
```
const { Gubu, Closed } = require(`gubu`)
// Only properties `a` and `b` are allowed.
const shape = Gubu(Closed({
a: 1,
b: true
}))
```
You can access builders as properties of the main `Gubu` function to
keep them namespaced. You can also chain most builders. Thus a
required, closed object can be specificied with:
```
const { Gubu } = require(`gubu`)
const shape = Gubu({
a: Gubu.Closed({ x: 1 }).Required(),
b: Gubu.Required({ x: 1 }).Closed(), // Also works.
})
```
You can also write your own builders - see the [API Builders](#builders) section.
In addition to this README, the [unit tests](lib/gubu.test.ts) are
comprehensive and provide many usage examples.
## API
### Builders
## Credits
## GUBU
The name comes from a sort of in-joke in Irish politics. It is
[grotesque, unbelievable, bizarre and
unprecedented](https://en.wikipedia.org/wiki/GUBU), that anyone would
write yet another validation library for JavaSCript, let alone a
second one (The first one I wrote is
[parambulator](https://github.com/rjrodger/parambulator)).
Also I like short names.
## License
Copyright (c) 2021, Richard Rodger and other contributors.
Licensed under [MIT][].
[MIT]: ./LICENSE

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc