Skip to content

Commit

Permalink
Rules
Browse files Browse the repository at this point in the history
  • Loading branch information
shuritch committed Oct 18, 2023
1 parent d8c1b3f commit cc3fa99
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- DOCS & Typings & JSDoc [issue](https://github.com/astrohelm/astroplan/issues/11)
- Custom checks (rules) [issue](https://github.com/astrohelm/astroplan/issues/7)
- FS utilities [issue](https://github.com/astrohelm/astroplan/issues/9)
- Allow custom types, schemas and rules to return value of string, boolean and SchemaError types;

## [0.1.0][] - 2023-10-16

Expand Down
30 changes: 29 additions & 1 deletion lib/proto/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
'use strict';

const defaultTest = () => [];
const INVALID = 'Invalid prototype, missing construct method';

const parse = (res, options, cause) => {
const { sample, path, plan, tools } = options;
if (typeof res === 'object' && Array.isArray(res)) {
if (!res.length || res[0] instanceof tools.Error) return res;
return res.map(v => parse(v, options)).flat(2);
}
if (typeof res === 'boolean' && !res) return [new tools.Error({ sample, path, plan, cause })];
if (typeof res === 'string') return [new tools.Error({ sample, path, plan, cause: res })];
if (res instanceof tools.Error) return [res];
return [];
};

const createType = (proto, defaultMeta) => {
if (!proto?.construct || typeof proto.construct !== 'function') throw new Error(INVALID);
const meta = {};
Expand All @@ -11,7 +25,21 @@ const createType = (proto, defaultMeta) => {
Object.assign(this, meta);
if (plan.meta) Object.assign(this, plan.meta);
if (!this.type) this.type = 'unknown';
if (!this.test) this.test = () => [];
const test = this.test ?? defaultTest;
const rules = plan.rules ?? [];
this.test = (sample, path = 'root') => {
const options = { sample, path, tools, plan };
const errors = parse(test(sample, path), options, `Didn't pass test`);
if (rules.length === 0) return errors;
for (let i = 0; i < rules.length; ++i) {
const result = parse(rules[i](sample), options, `Didn't pass rule[${i}]`);
if (result.length > 0) {
const err = result.map(cause => new tools.Error({ sample, path, cause, plan }));
errors.push(...err);
}
}
return errors;
};
return Object.freeze(this);
}
return Object.assign(Type, meta);
Expand Down
2 changes: 1 addition & 1 deletion lib/schema/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = (options = {}) => {
const { pattern = '[P] => C' } = options;
const format = dict => pattern.toLowerCase().replace(/[scp]/g, char => dict[MAP[char]]);

return function Error({ path, sample, plan, cause, sampleType }) {
return function SchemaError({ path, sample, plan, cause, sampleType }) {
[this.count, this.path, this.cause] = [0, path, ''];
if (sample) [this.sample, this.sampleType] = [sample, sampleType ?? typeof sample];
if (cause) [this.cause, this.count] = [cause, this.count + 1];
Expand Down
3 changes: 0 additions & 3 deletions lib/schema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ module.exports = function Schema(schema, params = {}) {

this.warnings = [];
Object.freeze(tools);

Object.assign(this, tools.build(schema));
const { test } = this;
this.test = (sample, path = 'root') => test(sample, path);
return Object.freeze(this);
};
// this.update = schema => new Schema(schema,)
16 changes: 16 additions & 0 deletions tests/rules.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const [test, assert] = [require('node:test'), require('node:assert')];
const Schema = require('..');

test('Rules', () => {
const rule1 = sample => sample?.length > 5;
const rule2 = sample => sample?.length < 100;
const plan = { type: 'string', rules: [rule1, rule2] };
const schema = new Schema(plan);
assert.strictEqual(schema.warnings.length, 0);
assert.strictEqual(schema.test().length, 3); //? Required + two rules
assert.strictEqual(schema.test('Test').length, 1); //? One rule
console.log(schema.test('Hello world'));
assert.strictEqual(schema.test('Hello world').length, 0);
});
11 changes: 5 additions & 6 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//TODO: #1 Rules & Tests
//TODO: #2 Parser for samples
//TODO: #3 Typescript code generation
//TODO: #4 FS UTilities
//TODO: #5 Types
//TODO: #6 README
//TODO: #1 Parser for samples
//TODO: #2 Typescript code generation
//TODO: #3 FS UTilities
//TODO: #4 Types
//TODO: #5 README

type Condition = 'allof' | 'anyof' | 'oneof';
type TypeField = { type: Type | Type[]; condition?: Condition };
Expand Down

0 comments on commit cc3fa99

Please sign in to comment.