2 Commits

Author SHA1 Message Date
Sven Slootweg 91714b7dda WIP 2 months ago
Sven Slootweg c345fdd74d WIP 2 months ago
  1. 410
      lib/Connection.js
  2. 7
      lib/util/ensure-array.js
  3. 7
      lib/util/ensure-object.js
  4. 8
      lib/util/named-tree-builder.js
  5. 5
      package.json
  6. 236
      yarn.lock

410
lib/Connection.js

@ -6,10 +6,17 @@ const asExpression = require("as-expression");
const matchValue = require("match-value");
const unreachable = require("@joepie91/unreachable");
const { validateArguments } = require("@validatem/core");
const required = require("@validatem/required");
const anyProperty = require("@validatem/any-property");
const isString = require("@validatem/is-string");
const isFunction = require("@validatem/is-function");
const { command, unsafeRaw, already7Bit } = require("./util/command");
const pInterval = require("./util/p-interval");
const createFetchTaskTracker = require("./util/fetch-task");
const createBoxTreeBuilder = require("./util/box-tree-builder");
const ensureArray = require("./util/ensure-array");
var tls = require('tls'),
Socket = require('net').Socket,
@ -1238,56 +1245,196 @@ Object.defineProperty(Connection.prototype, 'seq', { get: function() {
};
}});
function createCommandHandlers(rules) {
function parseTypes(typeString) {
if (typeString === NoRequest || typeString === AnyRequest) {
return [ typeString ];
} else {
return typeString
.split(/\s*,\s*/)
.map((type) => type.toUpperCase());
}
}
function createCommandHandlers(_rules) {
let [ rules ] = validateArguments(arguments, {
rules: anyProperty({
key: [ required ],
value: [ required, {
untagged: anyProperty({
key: [ isString ],
value: [ required, isFunction ]
}),
tagged: [ isFunction ]
}]
})
});
let untaggedHandlers = new Map();
let taggedHandlers = new Map();
for (let [ types, options ] of Object.entries(rules)) {
let parsedTypes = types
.split(/\s*\s*/)
.map((type) => type.toUpperCase());
function setUntaggedHandler(requestType, responseType, handler) {
if (!untaggedHandlers.has(requestType)) {
untaggedHandlers.set(requestType, new Map());
}
let handlers = untaggedHandlers.get(requestType);
if (!handlers.has(responseType)) {
handlers.set(responseType, handler);
} else {
throw new Error(`Duplicate handler definition for untagged type '${requestType}' -> '${responseType}'`);
}
}
for (let type of parsedTypes) {
function setTaggedHandler(requestType, handler) {
if (!taggedHandlers.has(requestType)) {
taggedHandlers.set(requestType, handler);
} else {
throw new Error(`Duplicate handler definition for tagged type`);
}
}
function getRequestType(request) {
return (request != null)
? request.type.toUpperCase()
: NoRequest;
}
function getTaggedHandler(request) {
return taggedHandlers.get(getRequestType(request));
}
function getUntaggedHandler(request, responseType) {
let typeHandlers = untaggedHandlers.get(getRequestType(request));
let anyRequestHandlers = untaggedHandlers.get(AnyRequest);
// console.log({
// requestType: getRequestType(request),
// responseType: responseType,
// anyHandler: anyRequestHandlers.get(responseType)
// });
if (typeHandlers != null && typeHandlers.has(responseType)) {
return typeHandlers.get(responseType);
} else if (anyRequestHandlers != null && anyRequestHandlers.has(responseType)) {
return anyRequestHandlers.get(responseType);
}
}
for (let [ typeString, options ] of allEntries(rules)) {
for (let type of parseTypes(typeString)) {
if (options.untagged != null) {
untaggedHandlers.set(type, options.untagged);
for (let [ responseTypeString, handler ] of allEntries(options.untagged)) {
for (let responseType of parseTypes(responseTypeString)) {
setUntaggedHandler(type, responseType, handler);
}
}
}
if (options.tagged != null) {
taggedHandlers.set(type, options.tagged);
setTaggedHandler(type, options.tagged);
}
}
}
// REFACTOR: Eventually remove `.call(this` hackery
// REFACTOR: Remove all the toUpperCase stuff and normalize this in the core instead, so that we can just *assume* it to be upper-case here
return {
canHandleUntagged: function (request) {
return untaggedHandlers.has(request.type.toUpperCase());
canHandleUntagged: function (request, data) {
return (getUntaggedHandler(request, data.type.toUpperCase()) != null);
},
canHandleTagged: function (request) {
return taggedHandlers.has(request.type.toUpperCase());
canHandleTagged: function (request, _data) {
return (getTaggedHandler(request) != null);
},
handleUntagged: function (request, data) {
let handler = untaggedHandlers.get(request.type.toUpperCase());
let handler = getUntaggedHandler(request, data.type.toUpperCase());
return handler.call(this, request, data);
},
handleTagged: function (request, data) {
let handler = taggedHandlers.get(request.type.toUpperCase());
let handler = getTaggedHandler(request);
return handler.call(this, request, data);
}
};
}
function allEntries(object) {
// The equivalent of Object.entries but also including Symbol keys
return Reflect.ownKeys(object).map((key) => {
return [ key, object[key] ];
});
}
let NoRequest = Symbol("NoRequest");
let AnyRequest = Symbol("AnyRequest");
// FIXME: Strip "UID" prefix from command names before matching, as these only affect the output format, but not the type of response
// Exception: EXPUNGE is allowed during UID commands, but not during their non-UID equivalents: https://datatracker.ietf.org/doc/html/rfc3501#page-73
let commandHandlers = createCommandHandlers({
[AnyRequest]: {
untagged: {
"BYE": function (_request, _) {
this._sock.end();
},
"CAPABILITY": function (_request, { payload }) {
this._caps = payload.map((v) => v.toUpperCase());
},
"NAMESPACE": function (_request, { payload }) {
this.namespaces = payload;
},
"PREAUTH": function (_request, _) {
this.state = 'authenticated';
},
"EXPUNGE": function (_request, { sequenceNumber }) {
if (this._box != null) {
if (this._box.messages.total > 0) {
this._box.messages.total -= 1;
}
this.emit('expunge', sequenceNumber);
}
},
}
},
"STATUS": {
untagged: {
"STATUS": function (request, { payload }) {
// REFACTOR: Improve this?
let attrs = defaultValue(payload.attrs, {});
let box = {
name: payload.name,
uidnext: defaultValue(attrs.uidnext, 0),
uidvalidity: defaultValue(attrs.uidvalidity, 0),
messages: {
total: defaultValue(attrs.messages, 0),
new: defaultValue(attrs.recent, 0),
unseen: defaultValue(attrs.unseen, 0)
},
// CONDSTORE
highestmodseq: (attrs.highestmodseq != null)
? String(attrs.highestmodseq)
: undefined
};
request.legacyArgs.push(box);
Object.assign(request.responseData, box);
}
}
},
"LIST, XLIST, LSUB": {
untagged: function (request, { payload }) {
if (request.delimiter === undefined) {
request.delimiter = payload.delimiter;
} else {
if (request.boxBuilder == null) {
request.boxBuilder = createBoxTreeBuilder();
untagged: {
"LIST, XLIST, LSUB": function (request, { payload }) {
if (request.delimiter === undefined) {
request.delimiter = payload.delimiter;
} else {
if (request.boxBuilder == null) {
request.boxBuilder = createBoxTreeBuilder();
}
request.boxBuilder.add(payload);
}
request._curReq.boxBuilder.add(payload);
}
},
tagged: function (request, _) {
@ -1301,16 +1448,114 @@ let commandHandlers = createCommandHandlers({
}
},
"ID": {
untagged: function (request, { payload }) {
// https://datatracker.ietf.org/doc/html/rfc2971
// Used for communicating server/client name, version, etc.
request.responseData.serverVersion = payload;
request.legacyArgs.push(payload);
// https://datatracker.ietf.org/doc/html/rfc2971
// Used for communicating server/client name, version, etc.
untagged: {
"ID": function (request, { payload }) {
request.responseData.serverVersion = payload;
request.legacyArgs.push(payload);
}
}
}
},
"ESEARCH": {
// https://datatracker.ietf.org/doc/html/rfc4731 / https://datatracker.ietf.org/doc/html/rfc7377
untagged: {
"ESEARCH": function (request, { payload }) {
Object.assign(request.responseData, payload); // Protocol-defined attributes. TODO: Improve the key names for this? Or is there extensibility?
request.legacyArgs.push(payload);
}
}
},
"SORT": {
// https://datatracker.ietf.org/doc/html/rfc5256
untagged: {
"SORT": function (request, { payload }) {
request.responseData.UIDs = payload;
request.legacyArgs.push(payload);
}
}
},
"THREAD": {
// https://datatracker.ietf.org/doc/html/rfc5256
untagged: {
"THREAD": function (request, { payload }) {
request.responseData.threads = payload; // FIXME: Work out the exact format
request.legacyArgs.push(payload);
}
}
},
"SEARCH": {
untagged: {
"SEARCH": function (request, { payload }) {
if (payload.results !== undefined) {
// CONDSTORE-modified search results
request.legacyArgs.push(payload.results);
request.legacyArgs.push(payload.modseq);
} else {
request.legacyArgs.push(payload);
}
}
}
},
"GETQUOTA, GETQUOTAROOT": {
// https://datatracker.ietf.org/doc/html/rfc2087
untagged: {
"QUOTA": function (request, { payload }) {
ensureArray(request.responseData, "quota");
request.responseData.quota.push(payload);
ensureArray(request.legacyArgs, 0);
request.legacyArgs[0].push(payload);
},
"QUOTAROOT": function (_request, _) {
throw new Error(`Not implemented`);
}
}
},
"SELECT, EXAMINE": {
untagged: {
"RECENT": function (_request, { sequenceNumber }) {
this._ensureBox();
// FIXME: This conditional is always true?
if (this._box) {
this._box.messages.new = sequenceNumber;
}
},
"FLAGS": function (_request, { payload }) {
this._ensureBox();
// FIXME: This conditional is always true?
if (this._box) {
this._box.flags = payload;
}
},
"EXISTS": function (_request, { sequenceNumber }) {
this._ensureBox();
// FIXME: This conditional is always true?
if (this._box) {
var prev = this._box.messages.total, now = sequenceNumber;
this._box.messages.total = now;
if (now > prev && this.state === 'authenticated') {
this._box.messages.new = now - prev;
this.emit('mail', this._box.messages.new);
}
}
},
}
},
});
Connection.prototype._ensureBox = function () {
if (!this._box) {
if (RE_OPENBOX.test(this._curReq.type)) {
this._resetCurrentBox();
} else {
throw new Error(`Received a box-related response while not processing a box-related request`);
}
}
};
@ -1324,25 +1569,11 @@ Connection.prototype._resUntagged = function({ type, num: sequenceNumber, textCo
// console.log("resUntagged", { type, num: sequenceNumber, payload, textCode: responseData });
var i, len, box, destinationKey;
if (this._curReq != null && commandHandlers.canHandleUntagged(this._curReq)) {
// FIXME: Include other fields
commandHandlers.handleUntagged.call(this, this._curReq, { sequenceNumber, payload });
} else if (type === 'bye') {
this._sock.end();
} else if (type === 'namespace') {
this.namespaces = payload;
} else if (type === 'capability') {
this._caps = payload.map((v) => v.toUpperCase());
} else if (type === 'preauth') {
this.state = 'authenticated';
} else if (type === 'expunge') {
if (this._box) {
if (this._box.messages.total > 0) {
this._box.messages.total -= 1;
}
let response = { type, sequenceNumber, payload };
this.emit('expunge', sequenceNumber);
}
if (commandHandlers.canHandleUntagged(this._curReq, response)) {
// FIXME: Include other fields
commandHandlers.handleUntagged.call(this, this._curReq, response);
} else if (type === 'ok') {
if (this.state === 'connected' && !this._curReq) {
this._login();
@ -1387,50 +1618,6 @@ Connection.prototype._resUntagged = function({ type, num: sequenceNumber, textCo
} else if (typeof responseData === 'string' && responseData.toUpperCase() === 'UIDVALIDITY') {
this.emit('uidvalidity', payload);
}
} else if (type === "esearch") {
// https://datatracker.ietf.org/doc/html/rfc4731 / https://datatracker.ietf.org/doc/html/rfc7377
Object.assign(this._curReq.responseData, payload); // Protocol-defined attributes. TODO: Improve the key names for this? Or is there extensibility?
this._curReq.cbargs.push(payload);
} else if (type === "sort") {
// https://datatracker.ietf.org/doc/html/rfc5256
this._curReq.responseData.UIDs = payload;
this._curReq.cbargs.push(payload);
} else if (type === 'thread') {
// https://datatracker.ietf.org/doc/html/rfc5256
this._curReq.responseData.threads = payload; // FIXME: Work out the exact format
this._curReq.cbargs.push(payload);
} else if (type === 'search') {
if (payload.results !== undefined) {
// CONDSTORE-modified search results
this._curReq.cbargs.push(payload.results);
this._curReq.cbargs.push(payload.modseq);
} else {
this._curReq.cbargs.push(payload);
}
} else if (type === 'quota') {
let responseData = this._curReq.responseData;
if (responseData.quota == null) { responseData.quota = []; };
responseData.quota.push(payload);
let cbargs = this._curReq.cbargs;
if (cbargs.length === 0) { cbargs.push([]); }
cbargs[0].push(payload);
} else if (type === 'recent') {
if (!this._box && RE_OPENBOX.test(this._curReq.type)) {
this._resetCurrentBox();
}
if (this._box) {
this._box.messages.new = sequenceNumber;
}
} else if (type === 'flags') {
if (!this._box && RE_OPENBOX.test(this._curReq.type)) {
this._resetCurrentBox();
}
if (this._box) {
this._box.flags = payload;
}
} else if (type === 'bad' || type === 'no') {
if (this.state === 'connected' && !this._curReq) {
clearTimeout(this._connectionTimeout);
@ -1440,39 +1627,6 @@ Connection.prototype._resUntagged = function({ type, num: sequenceNumber, textCo
this.emit('error', err);
this._sock.end();
}
} else if (type === 'exists') {
if (!this._box && RE_OPENBOX.test(this._curReq.type)) {
this._resetCurrentBox();
}
if (this._box) {
var prev = this._box.messages.total, now = sequenceNumber;
this._box.messages.total = now;
if (now > prev && this.state === 'authenticated') {
this._box.messages.new = now - prev;
this.emit('mail', this._box.messages.new);
}
}
} else if (type === 'status') {
let attrs = defaultValue(payload.attrs, {});
box = {
name: payload.name,
uidnext: defaultValue(attrs.uidnext, 0),
uidvalidity: defaultValue(attrs.uidvalidity, 0),
messages: {
total: defaultValue(attrs.messages, 0),
new: defaultValue(attrs.recent, 0),
unseen: defaultValue(attrs.unseen, 0)
},
// CONDSTORE
highestmodseq: (attrs.highestmodseq != null)
? String(attrs.highestmodseq)
: undefined
};
// FIXME
this._curReq.cbargs.push(box);
} else if (type === 'fetch') {
if (/^(?:UID )?FETCH/.test(this._curReq.fullcmd)) {
// FETCH response sent as result of FETCH request
@ -1565,9 +1719,11 @@ Connection.prototype._resTagged = function({ type, tagnum, text: payload, textCo
});
}
if (commandHandlers.canHandleTagged(request)) {
let response = { type, payload };
if (commandHandlers.canHandleTagged(request, response)) {
// FIXME: Add other fields with a sensible name
commandHandlers.handleTagged.call(this, request, { payload });
commandHandlers.handleTagged.call(this, request, response);
}
// console.dir({ done: request.cbargs }, { depth: null, colors: true });

7
lib/util/ensure-array.js

@ -0,0 +1,7 @@
"use strict";
module.exports = function ensureArrau(object, property) {
if (object[property] == null) {
object[property] = [];
}
};

7
lib/util/ensure-object.js

@ -0,0 +1,7 @@
"use strict";
module.exports = function ensureObject(object, property) {
if (object[property] == null) {
object[property] = {};
}
};

8
lib/util/named-tree-builder.js

@ -3,13 +3,9 @@
const defaultValue = require("default-value");
const asExpression = require("as-expression");
// FIXME: Move to stand-alone package, clearly document that it is not order-sensitive
const ensureObject = require("./ensure-object");
function ensureObject(object, property) {
if (object[property] == null) {
object[property] = {};
}
}
// FIXME: Move to stand-alone package, clearly document that it is not order-sensitive
module.exports = function createNamedTreeBuilder(options = {}) {
let parentKey = options.parentKey;

5
package.json

@ -6,6 +6,11 @@
"main": "./lib/Connection",
"dependencies": {
"@joepie91/unreachable": "^1.0.0",
"@validatem/any-property": "^0.1.3",
"@validatem/core": "^0.3.15",
"@validatem/is-function": "^0.1.0",
"@validatem/is-string": "^1.0.0",
"@validatem/required": "^0.1.1",
"as-expression": "^1.0.0",
"bluebird": "^3.7.2",
"default-value": "^1.0.0",

236
yarn.lock

@ -350,6 +350,152 @@
resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a"
integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==
"@validatem/annotate-errors@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@validatem/annotate-errors/-/annotate-errors-0.1.2.tgz#fa9152bb30f4f42b69496b527e38f0c31ff605a9"
integrity sha512-EuX7pzdYI/YpTmZcgdPG481Oi3elAg8JWh/LYXuE1h6MaZk3A8eP5DD33/l7EoKzrysn6y8nCsqNa1ngei562w==
dependencies:
"@validatem/match-validation-error" "^0.1.0"
"@validatem/any-property@^0.1.0", "@validatem/any-property@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@validatem/any-property/-/any-property-0.1.3.tgz#fc7768c1922a8bacff9369ae48913672e5350f52"
integrity sha512-jYWxif5ff9pccu7566LIQ/4+snlApXEJUimBywzAriBgS3r4eDBbz3oZFHuiPmhxNK/NNof5YUS+L6Sk3zaMfg==
dependencies:
"@validatem/annotate-errors" "^0.1.2"
"@validatem/combinator" "^0.1.0"
"@validatem/error" "^1.0.0"
"@validatem/validation-result" "^0.1.1"
"@validatem/virtual-property" "^0.1.0"
default-value "^1.0.0"
"@validatem/combinator@^0.1.0":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@validatem/combinator/-/combinator-0.1.2.tgz#eab893d55f1643b9c6857eaf6ff7ed2a728e89ff"
integrity sha512-vE8t1tNXknmN62FlN6LxQmA2c6TwVKZ+fl/Wit3H2unFdOhu7SZj2kRPGjAXdK/ARh/3svYfUBeD75pea0j1Sw==
"@validatem/core@^0.3.15":
version "0.3.15"
resolved "https://registry.yarnpkg.com/@validatem/core/-/core-0.3.15.tgz#645a0734dbc6efa3a5c39c62c5f2d8fa773f89f3"
integrity sha512-4nBLGzgpPrPsZ5DDXDXwL5p+GUEvpAFt6I3/YUHoah+ckYmKNh9qwmWKkFZHxJVdRrTewGFRj0FPw5fqje1yxA==
dependencies:
"@validatem/annotate-errors" "^0.1.2"
"@validatem/any-property" "^0.1.0"
"@validatem/error" "^1.0.0"
"@validatem/match-validation-error" "^0.1.0"
"@validatem/match-versioned-special" "^0.1.0"
"@validatem/match-virtual-property" "^0.1.0"
"@validatem/normalize-rules" "^0.1.0"
"@validatem/required" "^0.1.0"
"@validatem/validation-result" "^0.1.1"
"@validatem/virtual-property" "^0.1.0"
as-expression "^1.0.0"
assure-array "^1.0.0"
create-error "^0.3.1"
default-value "^1.0.0"
execall "^2.0.0"
flatten "^1.0.3"
indent-string "^4.0.0"
is-arguments "^1.0.4"
supports-color "^7.1.0"
syncpipe "^1.0.0"
"@validatem/error@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@validatem/error/-/error-1.1.0.tgz#bef46e7066c39761b494ebe3eec2ecdc7348f4ed"
integrity sha512-gZJEoZq1COi/8/5v0fVKQ9uX54x5lb5HbV7mzIOhY6dqjmLNfxdQmpECZPQrCAOpcRkRMJ7zaFhq4UTslpY9yA==
"@validatem/has-shape@^0.1.0":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@validatem/has-shape/-/has-shape-0.1.8.tgz#dff0f0449c12b96d150091b7a980154d810ae63d"
integrity sha512-x2i8toW1uraFF2Vl6WBl4CScbBeg5alrtoCKMyXbJkHf2B5QxL/ftUh2RQRcBzx6U0i7KUb8vdShcWAa+fehRQ==
dependencies:
"@validatem/annotate-errors" "^0.1.2"
"@validatem/combinator" "^0.1.0"
"@validatem/error" "^1.0.0"
"@validatem/validation-result" "^0.1.1"
array-union "^2.1.0"
as-expression "^1.0.0"
assure-array "^1.0.0"
default-value "^1.0.0"
flatten "^1.0.3"
"@validatem/is-function@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/is-function/-/is-function-0.1.0.tgz#15a2e95259dc5e32256e8c21872455661437d069"
integrity sha512-UtVrwTGhaIdIJ0mPG5XkAmYZUeWgRoMP1G9ZEHbKvAZJ4+SXf/prC0jPgE0pw+sPjdQG4hblsXSfo/9Bf3PGdQ==
dependencies:
"@validatem/error" "^1.0.0"
is-callable "^1.1.5"
"@validatem/is-plain-object@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@validatem/is-plain-object/-/is-plain-object-0.1.1.tgz#b7a3ef8ef960882c7c41e84ed709fa0bfb932e93"
integrity sha512-aNGbNIbKRpYI0lRBczlTBbiA+nqN52ADAASdySKg2/QeSCVtYS4uOIeCNIJRAgXe/5sUnLTuL4pgq628uAl7Kw==
dependencies:
"@validatem/error" "^1.0.0"
is-plain-obj "^2.1.0"
"@validatem/is-string@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@validatem/is-string/-/is-string-1.0.0.tgz#cc4a464f3bbc797aa7c7e124d11e5959b67636fd"
integrity sha512-j6fXuTgOrq94RbjSWeOzeKEcZ2ftnrG2ZHU16cGwC+gYn/st8JECXEpxSeZG8PJpn7V+PFaZeCKW9sJhonE1pA==
dependencies:
"@validatem/error" "^1.0.0"
is-string "^1.0.5"
"@validatem/match-special@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/match-special/-/match-special-0.1.0.tgz#4e0c28f1aee5bf53c1ef30bbf8c755d4946ae0ff"
integrity sha512-TFiq9Wk/1Hoja4PK85WwNYnwBXk3+Lgoj59ZIMxm2an1qmNYp8j+BnSvkKBflba451yIn6V1laU9NJf+/NYZgw==
"@validatem/match-validation-error@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/match-validation-error/-/match-validation-error-0.1.0.tgz#fa87f5f1836e7c1d9bf6b75b2addf0a5b21e4c1e"
integrity sha512-6akGTk7DdulOreyqDiGdikwRSixQz/AlvARSX18dcWaTFc79KxCLouL2hyoFcor9IIUhu5RTY4/i756y4T1yxA==
dependencies:
"@validatem/match-versioned-special" "^0.1.0"
"@validatem/match-versioned-special@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/match-versioned-special/-/match-versioned-special-0.1.0.tgz#2eacc48debecdbbe7e3d02f0c0a665afaea9bedf"
integrity sha512-xoOTY0bdA2ELj+ntcDVJ8YyMEFIJpjZ4HNPL9lGcbnRFwJBhQcHUAhUpZwkMxu02zH9wkNM1FvYGHxPz40745Q==
"@validatem/match-virtual-property@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/match-virtual-property/-/match-virtual-property-0.1.0.tgz#4de2de1075987b5f3b356d3f2bcf6c0be5b5fb83"
integrity sha512-ssd3coFgwbLuqvZftLZTy3eHN0TFST8oTS2XTViQdXJPXVoJmwEKBpFhXgwnb5Ly1CE037R/KWpjhd1TP/56kQ==
"@validatem/normalize-rules@^0.1.0":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@validatem/normalize-rules/-/normalize-rules-0.1.3.tgz#59fd6193b1091ff97b5c723b32c9bb1fe2a9dc9c"
integrity sha512-HHPceAP2ce9NWymIZrgLCTzpdwXNRBCCB5H6ZPc5ggOrbmh4STpT83fLazleHtvYNlqgXZ4GjQOvCwrjaM+qEA==
dependencies:
"@validatem/has-shape" "^0.1.0"
"@validatem/is-plain-object" "^0.1.0"
"@validatem/match-special" "^0.1.0"
assure-array "^1.0.0"
default-value "^1.0.0"
flatten "^1.0.3"
is-plain-obj "^2.1.0"
"@validatem/required@^0.1.0", "@validatem/required@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@validatem/required/-/required-0.1.1.tgz#64f4a87333fc5955511634036b7f8948ed269170"
integrity sha512-vI4NzLfay4RFAzp7xyU34PHb8sAo6w/3frrNh1EY9Xjnw2zxjY5oaxwmbFP1jVevBE6QQEnKogtzUHz/Zuvh6g==
"@validatem/validation-result@^0.1.1":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@validatem/validation-result/-/validation-result-0.1.2.tgz#4e75cfd87305fc78f8d05ac84921a2c99a0348e0"
integrity sha512-okmP8JarIwIgfpaVcvZGuQ1yOsLKT3Egt49Ynz6h1MAeGsP/bGHXkkXtbiWOVsk5Tzku5vDVFSrFnF+5IEHKxw==
dependencies:
default-value "^1.0.0"
"@validatem/virtual-property@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/virtual-property/-/virtual-property-0.1.0.tgz#880540dfd149f98ecf1095d93912e34443381fe4"
integrity sha512-JUUvWtdqoSkOwlsl20oB3qFHYIL05a/TAfdY4AJcs55QeVTiX5iI1b8IoQW644sIWWooBuLv+XwoxjRsQFczlQ==
acorn-jsx@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
@ -471,6 +617,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
arrify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
@ -623,6 +774,14 @@ caching-transform@^4.0.0:
package-hash "^4.0.0"
write-file-atomic "^3.0.0"
call-bind@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
dependencies:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
caller-callsite@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
@ -768,6 +927,13 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
clone-regexp@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
integrity sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==
dependencies:
is-regexp "^2.0.0"
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
@ -847,6 +1013,11 @@ coveralls@^3.0.11:
minimist "^1.2.5"
request "^2.88.2"
create-error@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23"
integrity sha1-aYECRaYp5lRDK/BDdzYAA6U1GiM=
cross-spawn@^7.0.0, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@ -1094,6 +1265,13 @@ events-to-array@^1.0.1:
resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6"
integrity sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=
execall@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45"
integrity sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==
dependencies:
clone-regexp "^2.1.0"
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
@ -1173,6 +1351,11 @@ flatted@^3.1.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
flatten@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
foreground-child@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53"
@ -1215,6 +1398,11 @@ fsevents@~2.3.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function-loop@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/function-loop/-/function-loop-2.0.1.tgz#799c56ced01698cf12a1b80e4802e9dafc2ebada"
@ -1235,6 +1423,15 @@ get-caller-file@^2.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.1"
get-package-type@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
@ -1325,6 +1522,18 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
hasha@^5.0.0:
version "5.2.2"
resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1"
@ -1427,6 +1636,13 @@ ink@^2.6.0, ink@^2.7.1:
wrap-ansi "^6.2.0"
yoga-layout-prebuilt "^1.9.3"
is-arguments@^1.0.4:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9"
integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==
dependencies:
call-bind "^1.0.0"
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
@ -1434,6 +1650,11 @@ is-binary-path@~2.1.0:
dependencies:
binary-extensions "^2.0.0"
is-callable@^1.1.5:
version "1.2.3"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
is-ci@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
@ -1475,11 +1696,26 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-plain-obj@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-regexp@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d"
integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==
is-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
is-string@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f"
integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==
is-typedarray@^1.0.0, is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"

Loading…
Cancel
Save