Skip to content

BREAKING: Remove event emitter #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,20 +204,12 @@ proxy objects that validate reading, assigning and deleting properties:
- `error_code`: The `code` property to define on errors. Defaults to
`E_SCHEMA`.
- `writer = mySchema.write([data[, options]])`: Creates a writer with optional
initial data and an event emitter. If the given data does not match the
schema, an exception is thrown. The returned writer throws on undefined
property modification, if an assigned value is invalid, or on an attempt to
read an undefined property. These options are supported:
initial data. If the given data does not match the schema, an exception is
thrown. The returned writer throws on undefined property modification, if an
assigned value is invalid, or on an attempt to read an undefined property.
These options are supported:
- `error_code`: The `code` property to define on errors. Defaults to
`E_SCHEMA`.
- `emitter`: If specified, these events will be emitted:
- `set` when a property is assigned a new value
- `delete` when a property is deleted
- `push` when `push` is called on an array
- `pop` when `pop` is called on an array
- `unshift` when `unshift` is called on an array
- `shift` when `shift` is called on an array
- `splice` when `splice` is called on an array
- `data = mySchema.verify(writer)`: Checks if any properties are missing in the
given writer and returns the unwrapped data. Throws if the given object is
not a schema writer.
Expand Down
12 changes: 2 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ module.exports.validator = validator;

module.exports.E_SCHEMA = E_SCHEMA;

/**
* @typedef {Object} Emitter
* @property {function(string, *): boolean | void} emit
*/
/**
* @template {Value} V
* @typedef WithToJSON
Expand All @@ -88,15 +84,11 @@ module.exports.E_SCHEMA = E_SCHEMA;
* @template {Value} V
* @typedef {V & WithToJSON<V>} SchemaWriter
*/
/**
* @template {Value} V
* @typedef WriterOptions
* @property {Emitter} [emitter]
*/
/**
* @template {Value} V
* @callback SchemaRead
* @param {V} value
* @param {SchemaOptions} [options]
* @returns {SchemaReader<V>}
*/
/* eslint-disable jsdoc/valid-types */
Expand All @@ -109,7 +101,7 @@ module.exports.E_SCHEMA = E_SCHEMA;
* @template {Value} V
* @callback SchemaWrite
* @param {RecursivePartial<V>} value
* @param {WriterOptions<V>} [options]
* @param {SchemaOptions} [options]
* @returns {SchemaWriter<V>}
*/

Expand Down
117 changes: 0 additions & 117 deletions lib/array-verifyer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const {
unwrap,
assertType,
lazy,
stringify,
failSet,
failDelete,
failSchemaValidation
Expand Down Expand Up @@ -72,10 +71,6 @@ function createArrayItemReader(itemTest, verify) {
function createArrayItemWriter(itemTest) {
return (array, options = {}, base = undefined) => {
array = unwrap(array);
const { emitter } = options;
if (emitter) {
emitArrayEvents(array, emitter, base, itemTest);
}
return new Proxy(array, {
get: createItemGetter(itemTest, options, base, 'write', arrayPath),
set(target, key, value) {
Expand All @@ -84,31 +79,10 @@ function createArrayItemWriter(itemTest) {
const index = getArrayIndex(key, base);
const path = arrayPath(base, index);
itemTest.verify(value, {}, path);
if (emitter) {
emitter.emit('set', {
type: 'array',
array: target,
base,
index,
path,
value
});
}
}
return Reflect.set(target, key, value);
},
deleteProperty(target, key) {
if (emitter) {
const index = getArrayIndex(/** @type {string} */ (key), base);
const path = arrayPath(base, index);
emitter.emit('delete', {
type: 'array',
array: target,
base,
index,
path
});
}
return Reflect.deleteProperty(target, key);
}
});
Expand All @@ -131,94 +105,3 @@ function getArrayIndex(key, base) {
}
return index;
}

/**
* @template {Value} V
* @param {Array<V>} array
* @param {Object} emitter
* @param {string | undefined} base
* @param {Validator<V>} itemTest
*/
function emitArrayEvents(array, emitter, base, itemTest) {
const proto = Object.create(Array.prototype);
/**
* @param {V[]} values
* @returns {number}
*/
proto.push = (...values) => {
const unwrapped = values.map(unwrap);
verifyArrayMethodValues(base, 'push', 0, unwrapped, itemTest);
emitter.emit('push', { array, base, values: unwrapped });
return Array.prototype.push.call(array, ...unwrapped);
};
/**
* @returns {V}
*/
proto.pop = () => {
emitter.emit('pop', { array, base });
return Array.prototype.pop.call(array);
};
/**
* @returns {V}
*/
proto.shift = () => {
emitter.emit('shift', { array, base });
return Array.prototype.shift.call(array);
};
/**
* @param {V[]} values
* @returns {number}
*/
proto.unshift = (...values) => {
const unwrapped = values.map(unwrap);
verifyArrayMethodValues(base, 'unshift', 0, unwrapped, itemTest);
emitter.emit('unshift', { array, base, values: unwrapped });
return Array.prototype.unshift.call(array, ...unwrapped);
};
/**
* @param {number} start
* @param {number} delete_count
* @param {V[]} values
* @returns {V[]}
*/
proto.splice = (start, delete_count, ...values) => {
const unwrapped = values.map(unwrap);
verifyArrayMethodValues(base, 'splice', 2, unwrapped, itemTest);
emitter.emit('splice', {
array,
base,
start,
delete_count,
values: unwrapped
});
return Array.prototype.splice.call(
array,
start,
delete_count,
...unwrapped
);
};
Object.setPrototypeOf(array, proto);
}

/**
* @template {Value} V
* @param {string | undefined} base
* @param {string} method
* @param {number} offset
* @param {Array<V>} values
* @param {Validator<V>} itemTest
*/
function verifyArrayMethodValues(base, method, offset, values, itemTest) {
values.forEach((value, i) => {
if (itemTest(value) === false) {
failSchemaValidation(
new TypeError(
`Expected argument ${
i + offset + 1
} of ${base}.${method} to be ${itemTest} but got ${stringify(value)}`
)
);
}
});
}
20 changes: 0 additions & 20 deletions lib/map-verifyer.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,6 @@ function createMapValueWriter(valueTest) {
get: createItemGetter(valueTest, options, base, 'write', objectPath),
set: createItemSetter(valueTest, options, base),
deleteProperty(target, key) {
if (options && options.emitter && typeof key === 'string') {
const path = objectPath(base, key);
options.emitter.emit('delete', {
type: 'object',
object: target,
key,
base,
path
});
}
return Reflect.deleteProperty(target, key);
}
});
Expand All @@ -99,16 +89,6 @@ function createItemSetter(valueTest, options, base) {
value = unwrap(value);
const path = objectPath(base, key);
valueTest.verify(value, options, path);
if (options && options.emitter) {
options.emitter.emit('set', {
type: 'object',
object: target,
key,
value,
base,
path
});
}
}
return Reflect.set(target, key, value);
};
Expand Down
20 changes: 0 additions & 20 deletions lib/object-verifyer.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,6 @@ function createWriter(tests, spec_options) {
options.error_code
);
}
if (options.emitter && typeof key === 'string') {
const path = objectPath(base, key);
options.emitter.emit('delete', {
type: 'object',
object: target,
key,
base,
path
});
}
return Reflect.deleteProperty(target, key);
}
});
Expand Down Expand Up @@ -137,16 +127,6 @@ function createPropertySetter(tests, options, base) {
const path = objectPath(base, key);
const test = getTest(tests, key, base, options);
test.verify(value, options, path, false);
if (options.emitter) {
options.emitter.emit('set', {
type: 'object',
object: target,
key,
value,
base,
path
});
}
}
return Reflect.set(target, key, value);
};
Expand Down
Loading