From a94bb4a78983c1abfca4dd577129b645aee55edd Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Fri, 15 May 2020 22:37:10 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 5 +++++ example.js | 23 +++++++++++++++++++++++ index.js | 30 ++++++++++++++++++++++++++++++ package.json | 12 ++++++++++++ yarn.lock | 8 ++++++++ 6 files changed, 79 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 example.js create mode 100644 index.js create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..80e8252 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# @validatem/match-versioned-special + +Documentation for this module has not been written yet. By the time it reaches 1.0.0, it will have full documentation. + +In the meantime, check out the `example.js` file in the repository for a usage demonstration. diff --git a/example.js b/example.js new file mode 100644 index 0000000..7d32275 --- /dev/null +++ b/example.js @@ -0,0 +1,23 @@ +"use strict"; + +const matchVersionedSpecial = require("./"); +const virtualProperty = require("@validatem/virtual-property"); + +let matchVirtualProperty = matchVersionedSpecial({ + markerProperty: "___validatem_isVirtualProperty", + versionProperty: "___validatem_virtualPropertyVersion", + friendlyName: "a virtual property", + expectedVersions: [ 1 ] +}); + +let propertyA = "foo"; +let propertyB = virtualProperty("bar"); + +// This one is a version we don't recognize +let propertyC = virtualProperty("baz"); +propertyC.___validatem_virtualPropertyVersion = -2; + +console.log(matchVirtualProperty(propertyA)); // false +console.log(matchVirtualProperty(propertyB)); // true +console.log(matchVirtualProperty(propertyC)); // Produces version mismatch error + diff --git a/index.js b/index.js new file mode 100644 index 0000000..19db76d --- /dev/null +++ b/index.js @@ -0,0 +1,30 @@ +"use strict"; + +/* +Validatem has a separate package for each sort of (public) special value/marker, rather than just stuffing them all into @validatem/core. This is for three reasons: +1) To reduce module duplication. If for some reason two validators depend on slightly different versions of Validatem plumbing, it's much better if that plumbing is *just* an object factory, and not the entirety of @validatem/core. +2) To make versioning easier. Special values/types can now be independently versioned, so even if the @validatem/core API changes in a breaking manner, validators do not need to be updated to use a newer @validatem/core; because they don't depend on it *at all*, and instead depend on these individual plumbing modules, which will probably *never* have a breaking change. +3) Even *if* one of the plumbing modules gets a breaking release, it's easy to write @validatem/core and other plumbing modules such that they can deal with multiple different versions of plumbing objects, without requiring validators to update their dependency to remain compatible. + +To accomplish these goals, all these plumbing modules produce objects with some metadata that identifies a) it being a special object, b) the type of special object, and c) the version of that object's API, which will match the semver-major version of the module that it originates from. This function is used to check for the various different kinds of special objects, and ensure that they are of a supported version (eg. older @validatem/core modules cannot deal with newer versions of plumbing objects). + +If breaking releases occur for plumbing modules in the future, this logic can also check for *multiple* acceptable versions, and the *handling* logic for those special plumbing objects will be updated so that it is capable of handling both older and newer versions. + +This is a generalized solution to the problem of modular plumbing, and should also be useful for other modular toolkits. Time will tell whether this model actually ends up working as well in practice as it does on paper. +*/ + +// TODO: Add a module copy mismatch check here that is based on __modulePath, to detect redundant copies? Similar to how validation-error.js used to do an instance check + +module.exports = function createVersionedSpecialMatcher({ markerProperty, versionProperty, friendlyName, expectedVersions }) { + return function isSpecial(value) { + if (value[markerProperty]) { + if (expectedVersions.includes(value[versionProperty])) { + return true; + } else { + throw new Error(`Encountered ${friendlyName} with version ${value[versionProperty]}, but we were expecting one of versions [ ${expectedVersions.join(", ")} ]; this probably means you tried to use a validator that is incompatible with your version of @validatem/core, or with some other Validatem utility. Look at the stacktrace to determine where the mismatch is happening.`); + } + } else { + return false; + } + }; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..8587916 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "@validatem/match-versioned-special", + "description": "Utility for checking whether something is a special (plumbing) object with a particular version", + "version": "0.1.0", + "main": "index.js", + "repository": "http://git.cryto.net/validatem/match-versioned-special.git", + "author": "Sven Slootweg ", + "license": "WTFPL OR CC0-1.0", + "devDependencies": { + "@validatem/virtual-property": "^0.1.0" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..eaf9d31 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@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==