Skip to content

Commit

Permalink
Merge pull request #2 from Bxnq/refactor/advanced-functions
Browse files Browse the repository at this point in the history
feat: added min, max, match, optional. optional, or, and, updated docs
  • Loading branch information
Bxnq authored Jan 4, 2024
2 parents b3cc61b + a77973b commit 2330010
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 18 deletions.
73 changes: 62 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Balid is a light weight schema validator.
- [ ] **Advanced Types**
- [x] Objects
- [ ] Arrays
- [ ] **Utility Functions (e.g: max, min)**
- [x] **Utility Functions (e.g: max, min)**

- [ ] min
- [ ] max
- [x] min
- [x] max

- [ ] Github Actions
- [ ] publish version when `main` branch changes
Expand All @@ -44,6 +44,9 @@ yarn install balid
- [String](#string)
- [Number](#number)
- [Object](#object)
- [And](#and)
- [Or](#or)
- [Optional](#optional)

### Any

Expand All @@ -52,8 +55,8 @@ import { b } from "balid";

const schema = b.any();

schema.validate(200); // returns true
schema.validate({ foo: "bar" }); // returns true
schema.validate(200); // returns { valid: true }
schema.validate({ foo: "bar" }); // returns { valid: true }
```

### Boolean:
Expand All @@ -63,8 +66,8 @@ import { b } from "balid";

const schema = b.boolean();

schema.validate(false); // returns true
schema.validate("false"); // returns false
schema.validate(false); // returns { valid: true }
schema.validate("false"); // returns { valid: false }
```

### String:
Expand All @@ -74,7 +77,17 @@ import { b } from "balid";

const schema = b.string();

schema.validate("Hello World"); // returns true
schema.validate("Hello World"); // returns { valid: true }

const minMaxSchema = b.string({ min: 2, max: 10 });

schema.validate("a"); // returns { valid: false }
schema.validate("hello"); // returns { valid: true }

const matchSchema = b.string({ match: /hello/ });

matchSchema.validate("hello"); // returns { valid: true }
matchSchema.validate("world"); // returns { valid: false }
```

### Number:
Expand All @@ -84,8 +97,14 @@ import { b } from "balid";

const schema = b.number();

schema.validate(123); // returns true
schema.validate("123"); // returns false
schema.validate(123); // returns { valid: true }
schema.validate("123"); // returns { valid: false }

const minMaxSchema = b.number({ min: 10, max: 20 });

schema.validate(1); // returns { valid: false }
schema.validate(25); // returns { valid: false }
schema.validate(15); // returns { valid: true }
```

### Object:
Expand All @@ -97,5 +116,37 @@ const schema = b.object({
name: b.string(),
});

schema.validate({ name: "John Doe" }); // returns true
schema.validate({ name: "John Doe" }); // returns { valid: true }
```

### And

```typescript
import { b } from "balid";

const schema = b.and(b.any(), b.boolean());

schema.validate(true); // returns { valid: true }
```

### Or

```typescript
import { b } from "balid";

const schema = b.or(b.string(), b.boolean());

schema.validate("hello world"); // returns { valid: true }
schema.validate(true); // returns { valid: true }
```

### Optional

```typescript
import { b } from "balid";

const schema = b.optional(b.string());

schema.validate("hello world"); // returns { valid: true }
schema.validate(); // returns { valid: true }
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "balid",
"version": "0.1.0",
"version": "0.2.0",
"description": "A simple schema validator.",
"type": "module",
"author": "Bxnq",
Expand Down
9 changes: 8 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
export * from "./validators";
import { types, util } from "./validators";

const b = {
...types,
...util,
};

export { b };
87 changes: 83 additions & 4 deletions src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export type SchemaType = {
validate: (input: any) => Valid;
};

export type TypeParams = ((schema?: SchemaType) => SchemaType) | ((...schemas: SchemaType[]) => SchemaType);

export type Valid = {
valid: boolean;
errors: string[];
Expand All @@ -22,7 +24,7 @@ const check = (valid: Valid, check: boolean) => {
return;
};

export const b: Record<string, (schema?) => SchemaType> = {
export const types = {
any: () => {
return {
validate(input) {
Expand All @@ -41,29 +43,56 @@ export const b: Record<string, (schema?) => SchemaType> = {
},
};
},
number: () => {
number: (options?: { min?: number; max?: number }) => {
let min = options?.min ?? undefined;
let max = options?.max ?? undefined;

return {
validate(input: any) {
const valid = handle();

check(valid, typeof input === "number");

if (min != undefined) {
check(valid, input >= min);
}

if (max != undefined) {
check(valid, input <= max);
}

return valid;
},
};
},
string: () => {
string: (options?: { min?: number; max?: number; match?: RegExp }) => {
let min = options?.min ?? undefined;
let max = options?.max ?? undefined;
let match = options?.match ?? undefined;

return {
validate(input: any) {
const valid = handle();

check(valid, typeof input === "string");

if (min != undefined) {
check(valid, String(input).length >= min);
}

if (max != undefined) {
check(valid, String(input).length <= max);
}

if (match != undefined) {
check(valid, match.test(input));
}

return valid;
},
};
},
object: (schema?: Record<string, SchemaType>) => {
object: (schema?: object) => {
return {
validate(input: any) {
let valid = handle();
Expand All @@ -81,3 +110,53 @@ export const b: Record<string, (schema?) => SchemaType> = {
};
},
};

export const util = {
optional: (schema?: SchemaType) => {
return {
validate(input?: any) {
let valid = handle();

check(valid, input == undefined || schema.validate(input).valid);

return valid;
},
};
},
or: (...schemas: SchemaType[]) => {
return {
validate(input) {
let valid = handle();

for (const schema of schemas) {
if (schema.validate(input).valid) {
return {
valid: true,
errors: [],
};
}
}

return { valid: false, errors: [] };
},
};
},
and: (...schemas: SchemaType[]) => {
return {
validate(input) {
let valid = handle();

for (const schema of schemas) {
if (!schema.validate(input).valid) {
return {
valid: false,
errors: [],
};
}
}

return valid;
},
};
},
};
56 changes: 55 additions & 1 deletion tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ describe("basic", () => {
expect(schema.validate(true).valid).toBe(false);
expect(schema.validate(2).valid).toBe(false);
expect(schema.validate({ test: "string" }).valid).toBe(false);

const minSchema = b.string({ min: 5 });

expect(minSchema.validate("hello world").valid).toBe(true);
expect(minSchema.validate("abc").valid).toBe(false);

const maxSchema = b.string({ max: 5 });

expect(maxSchema.validate("hello world").valid).toBe(false);
expect(maxSchema.validate("test").valid).toBe(true);

const matchSchema = b.string({ match: /hello/ });

expect(matchSchema.validate("hello").valid).toBe(true);
expect(matchSchema.validate("world").valid).toBe(false);
});

test("number", () => {
Expand All @@ -39,21 +54,60 @@ describe("basic", () => {
expect(schema.validate(true).valid).toBe(false);
expect(schema.validate("hello world").valid).toBe(false);
expect(schema.validate({ foo: "bar" }).valid).toBe(false);

const minSchema = b.number({ min: 5 });

expect(minSchema.validate(2).valid).toBe(false);
expect(minSchema.validate(8).valid).toBe(true);

const maxSchema = b.number({ max: 5 });

expect(maxSchema.validate(2).valid).toBe(true);
expect(maxSchema.validate(8).valid).toBe(false);
});
});

describe("advanced", () => {
test("object", () => {
const schema = b.object({
name: b.string(),
age: b.number(),
age: b.optional(b.number()),
});

expect(schema.validate(2).valid).toBe(false);
expect(schema.validate(true).valid).toBe(false);
expect(schema.validate("hello world").valid).toBe(false);

expect(schema.validate({ name: "test", age: 2 }).valid).toBe(true);
expect(schema.validate({ name: "hello world" }).valid).toBe(true);
expect(schema.validate({ age: 2 }).valid).toBe(false);
expect(schema.validate({ name: 2, age: "hello world" }).valid).toBe(false);
});
});

describe("util", () => {
test("optional", () => {
const schema = b.optional(b.string());

expect(schema.validate("test").valid).toBe(true);
expect(schema.validate().valid).toBe(true);
});
test("or", () => {
const schema = b.or(b.string(), b.number());

expect(schema.validate("test").valid).toBe(true);
expect(schema.validate(2).valid).toBe(true);

expect(schema.validate(true).valid).toBe(false);
expect(schema.validate({ foo: "bar" }).valid).toBe(false);
});
test("and", () => {
const schema = b.and(b.any(), b.boolean());

expect(schema.validate(true).valid).toBe(true);

expect(schema.validate(2).valid).toBe(false);
expect(schema.validate("test").valid).toBe(false);
expect(schema.validate({ foo: "bar" }).valid).toBe(false);
});
});

0 comments on commit 2330010

Please sign in to comment.