├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENCE ├── README.md ├── _config.yml ├── codecov.yml ├── common ├── config │ └── rush │ │ ├── .npmrc │ │ ├── command-line.json │ │ ├── common-versions.json │ │ ├── npm-shrinkwrap.json │ │ └── version-policies.json └── scripts │ ├── install-run-rush.js │ └── install-run.js ├── package-lock.json ├── packages ├── rawmodel-core │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── builder.ts │ │ │ ├── handler.ts │ │ │ ├── models.ts │ │ │ ├── parser.ts │ │ │ ├── props.ts │ │ │ ├── types.ts │ │ │ └── validator.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── core │ │ │ ├── builder │ │ │ │ └── create-model-class-method.test.ts │ │ │ ├── handler │ │ │ │ └── handler-method.test.ts │ │ │ ├── models │ │ │ │ ├── apply-errors-instance-method.test.ts │ │ │ │ ├── clone-instance-method.test.ts │ │ │ │ ├── collect-errors-instance-method.test.ts │ │ │ │ ├── commit-instance-method.test.ts │ │ │ │ ├── empty-instance-method.test.ts │ │ │ │ ├── fake-instance-method.test.ts │ │ │ │ ├── flatten-instance-method.test.ts │ │ │ │ ├── freeze-instance-method.test.ts │ │ │ │ ├── get-ancestors-instance-method.test.ts │ │ │ │ ├── get-context-instance-method.test.ts │ │ │ │ ├── get-parent-instance-method.test.ts │ │ │ │ ├── get-prop-instance-method.test.ts │ │ │ │ ├── handle-instance-method.test.ts │ │ │ │ ├── has-prop-instance-method.test.ts │ │ │ │ ├── invalidate-instance-method.test.ts │ │ │ │ ├── is-changed-instance-method.test.ts │ │ │ │ ├── is-equal-instance-method.test.ts │ │ │ │ ├── is-valid-instance-method.test.ts │ │ │ │ ├── populate-instance-method.test.ts │ │ │ │ ├── prop-decorator.test.ts │ │ │ │ ├── reset-instance-method.test.ts │ │ │ │ ├── rollback-instance-method.test.ts │ │ │ │ ├── serialize-instance-method.test.ts │ │ │ │ ├── speed.test.ts │ │ │ │ └── validate-instance-method.test.ts │ │ │ ├── parser │ │ │ │ └── parse-method.test.ts │ │ │ ├── props │ │ │ │ ├── class-config.test.ts │ │ │ │ ├── commit-instance-method.test.ts │ │ │ │ ├── empty-instance-method.test.ts │ │ │ │ ├── fake-instance-method.test.ts │ │ │ │ ├── freeze-instance-method.test.ts │ │ │ │ ├── get-error-code-instance-method.test.ts │ │ │ │ ├── get-initial-value-instance-method.test.ts │ │ │ │ ├── get-raw-value-instance-method.test.ts │ │ │ │ ├── get-value-instance-method.test.ts │ │ │ │ ├── handle-instance-method.test.ts │ │ │ │ ├── invalidate-instance-method.test.ts │ │ │ │ ├── is-changed-instance-method.test.ts │ │ │ │ ├── is-empty-instance-method.test.ts │ │ │ │ ├── is-equal-instance-method.test.ts │ │ │ │ ├── is-populatable-instance-method.test.ts │ │ │ │ ├── is-serializable-instance-method.test.ts │ │ │ │ ├── is-valid-instance-method.test.ts │ │ │ │ ├── reset-instance-method.test.ts │ │ │ │ ├── rollback-instance-method.test.ts │ │ │ │ ├── set-error-code-instance-method.test.ts │ │ │ │ ├── set-value-instance-method.test.ts │ │ │ │ └── validate-instance-method.test.ts │ │ │ └── validator │ │ │ │ └── validate-method.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── rawmodel-handlers │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── handlers │ │ │ └── mongo-uniqueness.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── handlers │ │ │ └── mongo-uniqueness.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── rawmodel-parsers │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── parsers │ │ │ ├── array.ts │ │ │ ├── boolean.ts │ │ │ ├── bson-object-id-string.ts │ │ │ ├── date.ts │ │ │ ├── float.ts │ │ │ ├── integer.ts │ │ │ └── string.ts │ │ └── tests │ │ │ ├── index.test.ts │ │ │ └── parsers │ │ │ ├── array.test.ts │ │ │ ├── boolean.test.ts │ │ │ ├── bson-object-id-string.test.ts │ │ │ ├── date.test.ts │ │ │ ├── float.test.ts │ │ │ ├── integer.test.ts │ │ │ └── string.test.ts │ ├── tsconfig.json │ └── tslint.json ├── rawmodel-schema │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── builder.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── core │ │ │ └── builder │ │ │ │ └── create-model-method.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── rawmodel-utils │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── helpers │ │ │ ├── is-array.ts │ │ │ ├── is-boolean.ts │ │ │ ├── is-class-of.ts │ │ │ ├── is-date.ts │ │ │ ├── is-deep-equal.ts │ │ │ ├── is-float.ts │ │ │ ├── is-function.ts │ │ │ ├── is-hex.ts │ │ │ ├── is-infinite.ts │ │ │ ├── is-instance-of.ts │ │ │ ├── is-integer.ts │ │ │ ├── is-null.ts │ │ │ ├── is-number.ts │ │ │ ├── is-object.ts │ │ │ ├── is-present.ts │ │ │ ├── is-string.ts │ │ │ ├── is-undefined.ts │ │ │ ├── is-value.ts │ │ │ ├── normalize.ts │ │ │ ├── realize.ts │ │ │ ├── to-array.ts │ │ │ ├── to-boolean.ts │ │ │ ├── to-date.ts │ │ │ ├── to-float.ts │ │ │ ├── to-integer.ts │ │ │ ├── to-number.ts │ │ │ └── to-string.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── helpers │ │ │ ├── is-array.test.ts │ │ │ ├── is-boolean.test.ts │ │ │ ├── is-class-of.test.ts │ │ │ ├── is-date.test.ts │ │ │ ├── is-deep-equal.test.ts │ │ │ ├── is-float.test.ts │ │ │ ├── is-function.test.ts │ │ │ ├── is-hex.test.ts │ │ │ ├── is-infinite.test.ts │ │ │ ├── is-instance-of.test.ts │ │ │ ├── is-integer.test.ts │ │ │ ├── is-null.test.ts │ │ │ ├── is-number.test.ts │ │ │ ├── is-object.test.ts │ │ │ ├── is-present.test.ts │ │ │ ├── is-string.test.ts │ │ │ ├── is-undefined.test.ts │ │ │ ├── is-value.test.ts │ │ │ ├── normalize.test.ts │ │ │ ├── realize.test.ts │ │ │ ├── to-array.test.ts │ │ │ ├── to-boolean.test.ts │ │ │ ├── to-date.test.ts │ │ │ ├── to-float.test.ts │ │ │ ├── to-integer.test.ts │ │ │ ├── to-number.test.ts │ │ │ └── to-string.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json └── rawmodel-validators │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ ├── index.ts │ ├── tests │ │ ├── index.test.ts │ │ └── validators │ │ │ ├── absence.test.ts │ │ │ ├── array-exclusion.test.ts │ │ │ ├── array-inclusion.test.ts │ │ │ ├── array-length.test.ts │ │ │ ├── base64.test.ts │ │ │ ├── bson-object-id.test.ts │ │ │ ├── date.test.ts │ │ │ ├── downcase-string.test.ts │ │ │ ├── email.test.ts │ │ │ ├── eth-address.test.ts │ │ │ ├── exclusion.test.ts │ │ │ ├── fqdn.test.ts │ │ │ ├── hex-color.test.ts │ │ │ ├── hex.test.ts │ │ │ ├── inclusion.test.ts │ │ │ ├── json-string.test.ts │ │ │ ├── match.test.ts │ │ │ ├── number-size.test.ts │ │ │ ├── presence.test.ts │ │ │ ├── string-exclusion.test.ts │ │ │ ├── string-inclusion.test.ts │ │ │ ├── string-length.test.ts │ │ │ ├── upcase-string.test.ts │ │ │ └── uuid.test.ts │ └── validators │ │ ├── absence.ts │ │ ├── array-exclusion.ts │ │ ├── array-inclusion.ts │ │ ├── array-length.ts │ │ ├── base64.ts │ │ ├── bson-object-id.ts │ │ ├── date.ts │ │ ├── downcase-string.ts │ │ ├── email.ts │ │ ├── eth-address.ts │ │ ├── exclusion.ts │ │ ├── fqdn.ts │ │ ├── hex-color.ts │ │ ├── hex.ts │ │ ├── inclusion.ts │ │ ├── json-string.ts │ │ ├── match.ts │ │ ├── number-size.ts │ │ ├── presence.ts │ │ ├── string-exclusion.ts │ │ ├── string-inclusion.ts │ │ ├── string-length.ts │ │ ├── upcase-string.ts │ │ └── uuid.ts │ └── tsconfig.json └── rush.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Don't allow people to merge changes to these generated files, because the result 2 | # may be invalid. You need to run "rush update" again. 3 | shrinkwrap.yaml merge=binary 4 | npm-shrinkwrap.json merge=binary 5 | yarn.lock merge=binary 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: xpepermint # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Runtime data 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # Bower dependency directory (https://bower.io/) 25 | bower_components 26 | 27 | # node-waf configuration 28 | .lock-wscript 29 | 30 | # Compiled binary addons (https://nodejs.org/api/addons.html) 31 | build/Release 32 | 33 | # Dependency directories 34 | node_modules/ 35 | jspm_packages/ 36 | 37 | # Optional npm cache directory 38 | .npm 39 | 40 | # Optional eslint cache 41 | .eslintcache 42 | 43 | # Optional REPL history 44 | .node_repl_history 45 | 46 | # Output of 'npm pack' 47 | *.tgz 48 | 49 | # Yarn Integrity file 50 | .yarn-integrity 51 | 52 | # dotenv environment variables file 53 | .env 54 | 55 | # next.js build output 56 | .next 57 | 58 | # Common toolchain intermediate files 59 | temp 60 | 61 | # Rush files 62 | common/temp/** 63 | package-deps.json 64 | 65 | # OSx environment 66 | .DS_Store 67 | 68 | # Compiled data 69 | dist 70 | build 71 | _site 72 | GemFile 73 | GemFile.lock 74 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - 12 5 | - 11 6 | script: 7 | # use latest npm to work on node9 8 | - npm install -g npm 9 | # install required global npm packages 10 | - npm install -g codecov 11 | - npm install -g @microsoft/rush 12 | # testing 13 | - rush update --full 14 | - rush rebuild 15 | - rush test 16 | after_success: 17 | # code coverage & codecov upload 18 | - rm -Rf .nyc_output && mkdir -p .nyc_output 19 | - find packages/**/.nyc_output -type f -name '*.json' -not -path 'packages/**/.nyc_output/processinfo/*' -exec cp '{}' .nyc_output \; 20 | - npx nyc report --extension=.ts --reporter=text-lcov > .nyc_output/coverage.lcov 21 | - codecov 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Development 4 | 5 | We use [RushJS](https://rushjs.io) to manage this repository. Some quick notes on how to manage the repository are documented [here](https://gist.github.com/xpepermint/eecfc6ad6cd7c9f5dcda381aa255738d). 6 | 7 | **Install dependencies** -- You only need to run this once. 8 | 9 | ```sh 10 | npm install -g @microsoft/rush 11 | ``` 12 | 13 | **Update packages** -- Run this if you add/remove packages from this repository. 14 | 15 | ```sh 16 | rush update --full 17 | ``` 18 | 19 | **Rebuild and test** -- Do this each time you make changes to the code 20 | 21 | ```sh 22 | rush rebuild --verbose 23 | rush test --verbose 24 | ``` 25 | 26 | The above notes will help you decide which commands to run during development on your own machine. But for any commits and pull requests in this repository, the entire test suite will be run using continuous integration. 27 | 28 | ## Issues 29 | 30 | We use GitHub issues to track bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. 31 | 32 | ## Pull requests 33 | 34 | Always fork the repo and create your branch from master. If you've added code that should be tested, add tests. Alsp ensure the test suite passes before submitting the PR. 35 | 36 | ## Coding style 37 | 38 | Please follow the [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines). 39 | 40 | You should prefix private and protected class variables with `_`. Public class variables should start with a letter. Public class variables which hold read-only configuration information should be prefixed with `__`. 41 | 42 | ## Release process 43 | 44 | The release manager will publish packages to NPM using these commands. 45 | 46 | ``` 47 | $ rush version --bump --override-bump minor 48 | $ rush update --full 49 | $ rush rebuild 50 | $ rush test 51 | $ rush publish --publish --include-all 52 | ``` 53 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2016-2018 Xpepermint. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: rawmodel 2 | heading: Strongly-typed JavaScript object with support for validation and error handling. 3 | logo: /assets/images/rawmodel.svg 4 | email: info@rawmodel.org 5 | google_analytics: 6 | 7 | menu: 8 | - url: '#introduction' 9 | title: What is rawmodel 10 | - url: '#installation' 11 | title: Getting started 12 | - url: '#usage' 13 | title: Usage 14 | 15 | remote_theme: rawmodel/gp-theme 16 | plugins: 17 | - jekyll-remote-theme 18 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | fixes: 2 | - "rawmodel/framework::/" # travis path to match github repo paths 3 | comment: 4 | layout: "reach, diff, flags, files" 5 | behavior: default 6 | require_changes: false # if true: only post the comment if coverage changes 7 | require_base: no # [yes :: must have a base report to post] 8 | require_head: yes # [yes :: must have a head report to post] 9 | branches: null 10 | coverage: 11 | status: 12 | project: 13 | default: 14 | # basic 15 | target: auto 16 | threshold: null 17 | base: auto 18 | # advanced 19 | branches: null 20 | if_no_uploads: error 21 | if_not_found: success 22 | if_ci_failed: error 23 | only_pulls: false 24 | flags: null 25 | paths: null 26 | -------------------------------------------------------------------------------- /common/config/rush/.npmrc: -------------------------------------------------------------------------------- 1 | # Rush uses this file to configure the package registry, regardless of whether the 2 | # package manager is PNPM, NPM, or Yarn. Prior to invoking the package manager, 3 | # Rush will always copy this file to the folder where installation is performed. 4 | # When NPM is the package manager, Rush works around NPM's processing of 5 | # undefined environment variables by deleting any lines that reference undefined 6 | # environment variables. 7 | # 8 | # DO NOT SPECIFY AUTHENTICATION CREDENTIALS IN THIS FILE. It should only be used 9 | # to configure registry sources. 10 | 11 | registry=https://registry.npmjs.org/ 12 | always-auth=false 13 | -------------------------------------------------------------------------------- /common/config/rush/command-line.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", 3 | "commands": [ 4 | { 5 | "commandKind": "bulk", 6 | "name": "test", 7 | "summary": "Test packages.", 8 | "description": "Executes automated tests.", 9 | "enableParallelism": true 10 | } 11 | ], 12 | "parameters": [] 13 | } 14 | -------------------------------------------------------------------------------- /common/config/rush/common-versions.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This configuration file specifies NPM dependency version selections that affect all projects 3 | * in a Rush repo. For full documentation, please see https://rushjs.io 4 | */ 5 | { 6 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json", 7 | 8 | /** 9 | * A table that specifies a "preferred version" for a dependency package. The "preferred version" 10 | * is typically used to hold an indirect dependency back to a specific version, however generally 11 | * it can be any SemVer range specifier (e.g. "~1.2.3"), and it will narrow any (compatible) 12 | * SemVer range specifier. See the Rush documentation for details about this feature. 13 | */ 14 | "preferredVersions": { 15 | 16 | /** 17 | * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo, 18 | * instead of the latest version. 19 | */ 20 | // "some-library": "1.2.3" 21 | }, 22 | 23 | /** 24 | * The "rush check" command can be used to enforce that every project in the repo must specify 25 | * the same SemVer range for a given dependency. However, sometimes exceptions are needed. 26 | * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be 27 | * accepted by "rush check" for a given dependency. 28 | * 29 | * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE 30 | * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO). 31 | * This design avoids unnecessary churn in this file. 32 | */ 33 | "allowedAlternativeVersions": { 34 | 35 | /** 36 | * For example, allow some projects to use an older TypeScript compiler 37 | * (in addition to whatever "usual" version is being used by other projects in the repo): 38 | */ 39 | // "typescript": [ 40 | // "~2.4.0" 41 | // ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/config/rush/version-policies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "policyName": "patchAll", 4 | "definitionName": "lockStepVersion", 5 | "version": "3.3.3", 6 | "nextBump": "patch" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /packages/rawmodel-core/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-core/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-core/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/core", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/core_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/core_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/core_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/core_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/core_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/core_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/core_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "3.0.0", 48 | "tag": "@rawmodel/core_v2.4.0", 49 | "date": "Fri, 12 Jul 2019 17:57:56 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "2.3.0", 54 | "tag": "@rawmodel/core_v2.3.0", 55 | "date": "Thu, 11 Apr 2019 11:45:39 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "2.2.1", 60 | "tag": "@rawmodel/core_v2.2.1", 61 | "date": "Wed, 10 Apr 2019 17:10:31 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "2.2.0", 66 | "tag": "@rawmodel/core_v2.2.0", 67 | "date": "Wed, 10 Apr 2019 07:55:41 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "2.1.5", 72 | "tag": "@rawmodel/core_v2.1.5", 73 | "date": "Tue, 11 Dec 2018 10:35:14 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "2.1.4", 78 | "tag": "@rawmodel/core_v2.1.4", 79 | "date": "Tue, 11 Dec 2018 09:55:28 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "2.1.3", 84 | "tag": "@rawmodel/core_v2.1.3", 85 | "date": "Mon, 10 Dec 2018 22:15:09 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "2.1.2", 90 | "tag": "@rawmodel/core_v2.1.2", 91 | "date": "Sat, 10 Nov 2018 11:14:49 GMT", 92 | "comments": {} 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /packages/rawmodel-core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/core 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Version update only* 39 | 40 | ## 3.0.0 41 | Fri, 12 Jul 2019 17:57:56 GMT 42 | 43 | *Version update only* 44 | 45 | ## 2.3.0 46 | Thu, 11 Apr 2019 11:45:39 GMT 47 | 48 | *Version update only* 49 | 50 | ## 2.2.1 51 | Wed, 10 Apr 2019 17:10:31 GMT 52 | 53 | *Version update only* 54 | 55 | ## 2.2.0 56 | Wed, 10 Apr 2019 07:55:41 GMT 57 | 58 | *Version update only* 59 | 60 | ## 2.1.5 61 | Tue, 11 Dec 2018 10:35:14 GMT 62 | 63 | *Version update only* 64 | 65 | ## 2.1.4 66 | Tue, 11 Dec 2018 09:55:28 GMT 67 | 68 | *Version update only* 69 | 70 | ## 2.1.3 71 | Mon, 10 Dec 2018 22:15:09 GMT 72 | 73 | *Version update only* 74 | 75 | ## 2.1.2 76 | Sat, 10 Nov 2018 11:14:49 GMT 77 | 78 | *Initial release* 79 | 80 | -------------------------------------------------------------------------------- /packages/rawmodel-core/README.md: -------------------------------------------------------------------------------- 1 | > [Rawmodel](https://github.com/rawmodel/framework) core package. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-core/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/core", 3 | "version": "3.3.3", 4 | "description": "Strongly-typed JavaScript object with support for validation and error handling.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "@rawmodel/parsers": "3.3.3", 88 | "nyc": "^15.0.1", 89 | "ts-node": "^8.10.1", 90 | "@typescript-eslint/eslint-plugin": "2.34.0", 91 | "@typescript-eslint/parser": "2.34.0", 92 | "eslint-config-prettier": "6.11.0", 93 | "eslint-plugin-import": "2.20.2", 94 | "eslint-plugin-jsdoc": "25.4.2", 95 | "eslint-plugin-unicorn": "20.0.0", 96 | "eslint": "7.0.0", 97 | "typescript": "^3.8.3" 98 | }, 99 | "dependencies": { 100 | "@rawmodel/utils": "3.3.3" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/core/builder.ts: -------------------------------------------------------------------------------- 1 | import { Model } from './models'; 2 | import { PropDefinition } from './types'; 3 | 4 | /** 5 | * Returns a Model class generated from the provided properties. 6 | * @param recipe Model schema recipe. 7 | */ 8 | export function createModelClass(props: PropDefinition[]): typeof Model { 9 | const Klass = class GenericModel extends Model {}; 10 | 11 | Object.defineProperty(Klass, '__props', { 12 | value: {}, 13 | enumerable: false, 14 | configurable: true, 15 | }); 16 | 17 | props.forEach((prop) => { 18 | Klass.__props[prop.name] = { ...prop }; 19 | }); 20 | 21 | return Klass; 22 | } 23 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/core/handler.ts: -------------------------------------------------------------------------------- 1 | import { realize } from '@rawmodel/utils'; 2 | import { HandlerConfig, HandlerRecipe } from './types'; 3 | 4 | /** 5 | * Handles `error` based on the provided `recipes`. 6 | * @param value Arbitrary error. 7 | * @param recipe Handler recipes. 8 | * @param config Handler configuration. 9 | */ 10 | export async function handle(error: any, recipes: HandlerRecipe[] = [], config: HandlerConfig = {}): Promise { 11 | 12 | for (const recipe of recipes) { 13 | 14 | const context = realize(config.context); 15 | const isMatch = await Promise.resolve().then(() => { 16 | return recipe.resolver.call(context, error); 17 | }).then((r) => { 18 | return r === true; 19 | }); 20 | 21 | if (isMatch) { 22 | return recipe.code; 23 | } 24 | } 25 | 26 | return null; 27 | } 28 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/core/parser.ts: -------------------------------------------------------------------------------- 1 | import { isNull, isUndefined, toArray } from '@rawmodel/utils'; 2 | import { ParserConfig, ParserRecipe } from './types'; 3 | 4 | /** 5 | * Parses the provided `value` based on the provided `recipe`. 6 | * @param value Arbitrary value. 7 | * @param recipe Parser recipe. 8 | * @param config Parser configuration. 9 | */ 10 | export function parse(value: any, recipe?: ParserRecipe, config?: ParserConfig) { 11 | recipe = !recipe ? {} : recipe; 12 | config = !config ? {} : config; 13 | 14 | const perform = (value: any) => { 15 | if (isUndefined(value) || isNull(value)) { 16 | return value; 17 | } 18 | return recipe.resolver 19 | ? recipe.resolver.call(config.context, value) 20 | : value; 21 | }; 22 | 23 | if (isUndefined(value) || isNull(value)) { 24 | return value; 25 | } else if (recipe.array) { 26 | return toArray(value).map((v) => perform(v)); 27 | } else { 28 | return perform(value); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/core/types.ts: -------------------------------------------------------------------------------- 1 | import { Prop } from './props'; 2 | import { Model } from './models'; 3 | 4 | /** 5 | * Model configuration interface. 6 | */ 7 | export interface ModelConfig { 8 | context?: Context | (() => Context); 9 | parent?: Model; 10 | } 11 | 12 | /** 13 | * Property path. 14 | */ 15 | export type PropPath = (string | number)[]; 16 | 17 | /** 18 | * Property error interface. 19 | */ 20 | export interface PropError { 21 | path: PropPath; 22 | code: number; 23 | } 24 | 25 | /** 26 | * Model property class configuration object. 27 | */ 28 | export interface PropItem { 29 | path: PropPath; 30 | prop: Prop; 31 | value: any; 32 | } 33 | 34 | /** 35 | * Model property class configuration object. 36 | */ 37 | export interface PropConfig { 38 | getter?: SimpleResolver; 39 | setter?: SimpleResolver; 40 | parser?: ParserRecipe; 41 | defaultValue?: any | SimpleResolver; 42 | fakeValue?: any | SimpleResolver; 43 | emptyValue?: any | SimpleResolver; 44 | validators?: ValidatorRecipe[]; 45 | handlers?: HandlerRecipe[]; 46 | populatable?: string[]; 47 | serializable?: string[]; 48 | enumerable?: boolean; 49 | model?: Model; 50 | } 51 | 52 | /** 53 | * Model property class configuration object. 54 | */ 55 | export interface PropDefinition extends PropConfig { 56 | name: string; 57 | } 58 | 59 | /** 60 | * Parser recipe interface. 61 | */ 62 | export interface ParserRecipe { 63 | array?: boolean; 64 | resolver?: ParserResolver; 65 | } 66 | 67 | /** 68 | * Simple data resolver. 69 | */ 70 | export type SimpleResolver = (v?: any) => any; 71 | 72 | /** 73 | * Parser resolver definition. 74 | */ 75 | export type ParserResolver = SimpleResolver | any; 76 | 77 | /** 78 | * Parser configuration interface. 79 | */ 80 | export interface ParserConfig { 81 | context?: any | SimpleResolver; 82 | } 83 | 84 | /** 85 | * Validation recipe interface. 86 | */ 87 | export interface ValidatorRecipe { 88 | code: number; 89 | resolver: ValidatorResolver; 90 | } 91 | 92 | /** 93 | * Validator handler definition. 94 | */ 95 | export type ValidatorResolver = (v?: any) => (boolean | Promise); 96 | 97 | /** 98 | * Validator configuration interface. 99 | */ 100 | export interface ValidatorConfig { 101 | context?: any | SimpleResolver; 102 | } 103 | 104 | /** 105 | * Error handler recipe interface. 106 | */ 107 | export interface HandlerRecipe { 108 | code: number; 109 | resolver: HandlerResolver; 110 | } 111 | 112 | /** 113 | * Handler handler definition. 114 | */ 115 | export type HandlerResolver = (v?: any) => (boolean | Promise); 116 | 117 | /** 118 | * Error handler configuration interface. 119 | */ 120 | export interface HandlerConfig { 121 | context?: any | SimpleResolver; 122 | } 123 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/core/validator.ts: -------------------------------------------------------------------------------- 1 | import { realize } from '@rawmodel/utils'; 2 | import { ValidatorConfig, ValidatorRecipe } from './types'; 3 | 4 | /** 5 | * Validates `value` based on the provided `recipes`. 6 | * @param value Arbitrary error. 7 | * @param recipe Handler recipes. 8 | * @param config Handler configuration. 9 | */ 10 | export async function validate(value: any, recipes: ValidatorRecipe[] = [], config: ValidatorConfig = {}): Promise { 11 | 12 | for (const recipe of recipes) { 13 | 14 | const context = realize(config.context); 15 | const isValid = await Promise.resolve().then(() => { 16 | return recipe.resolver.call(context, value); 17 | }).then((r) => { 18 | return r === true; 19 | }); 20 | 21 | if (!isValid) { 22 | return recipe.code; 23 | } 24 | } 25 | 26 | return null; 27 | } 28 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/types'; 2 | export * from './core/parser'; 3 | export * from './core/validator'; 4 | export * from './core/handler'; 5 | export * from './core/parser'; 6 | export * from './core/props'; 7 | export * from './core/models'; 8 | export * from './core/builder'; 9 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/builder/create-model-class-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { createModelClass, Model } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('generates empty model class', (ctx) => { 7 | const Klass = createModelClass([]); 8 | ctx.true(new Klass() instanceof Model); 9 | }); 10 | 11 | spec.test('generates model with properties', (ctx) => { 12 | const Klass = createModelClass([ 13 | { 14 | name: 'name', 15 | }, 16 | { 17 | name: 'book', 18 | parser: { 19 | resolver: createModelClass([ 20 | { 21 | name: 'title', 22 | }, 23 | ]), 24 | }, 25 | }, 26 | ]); 27 | const data = { 28 | name: 'foo', 29 | book: { title: 'bar' }, 30 | }; 31 | const model = new Klass(data); 32 | ctx.deepEqual(model.serialize(), data); 33 | }); 34 | 35 | export default spec; 36 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/handler/handler-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { handle } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('handles an error and returns error codes', async (ctx) => { 7 | const recipes = [ 8 | { code: 200, resolver(e) { 9 | return e.message === 'foo'; 10 | } }, 11 | { code: 201, resolver(e) { 12 | return e.message === 'bar'; 13 | } }, 14 | ]; 15 | const error = new Error('foo'); 16 | const code = await handle(error, recipes); 17 | ctx.deepEqual(code, 200); 18 | }); 19 | 20 | spec.test('passes context to each resolver', async (ctx) => { 21 | const config = { 22 | context: { foo: 'foo' }, 23 | }; 24 | const recipes = [ 25 | { code: 100, resolver(v) { 26 | return v === this.foo; 27 | } }, 28 | ]; 29 | const code = await handle('foo', recipes, config); 30 | ctx.deepEqual(code, 100); 31 | }); 32 | 33 | export default spec; 34 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/apply-errors-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('sets properties errors', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | book: {}, 25 | books: [null, {}], 26 | }); 27 | user.applyErrors([ 28 | { path: ['name'], code: 100 }, 29 | { path: ['book', 'title'], code: 200 }, 30 | { path: ['books', 1, 'title'], code: 400 }, 31 | ]); 32 | ctx.deepEqual(user.getProp('name').getErrorCode(), 100); 33 | ctx.deepEqual(user.getProp('book', 'title').getErrorCode(), 200); 34 | ctx.deepEqual(user.getProp('books', 1, 'title').getErrorCode(), 400); 35 | }); 36 | 37 | export default spec; 38 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/clone-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns an exact copy of the original', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const parent = new Book(); 24 | const user = new User({ 25 | parent, // fake parent 26 | name: 'foo', 27 | book: { 28 | title: 'bar', 29 | }, 30 | books: [ 31 | null, 32 | { 33 | title: 'baz', 34 | }, 35 | ], 36 | }); 37 | const clone0 = user.clone(); 38 | const clone1 = user.clone({book: { title: 'foo' }}); 39 | ctx.true(clone0 !== user); 40 | ctx.true(clone0.isEqual(user)); 41 | ctx.deepEqual(clone0.getAncestors(), []); 42 | ctx.deepEqual(clone0.book.getAncestors(), [clone0]); 43 | ctx.is(clone1.book.title, 'foo'); 44 | }); 45 | 46 | export default spec; 47 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/collect-errors-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns an array of errors', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | book: {}, 25 | books: [{}], 26 | }); 27 | user.getProp('name').setErrorCode(100); 28 | user.getProp('book', 'title').setErrorCode(200); 29 | user.getProp('books', 0, 'title').setErrorCode(400); 30 | ctx.deepEqual(user.collectErrors(), [ 31 | { path: ['name'], code: 100 }, 32 | { path: ['book', 'title'], code: 200 }, 33 | { path: ['books', 0, 'title'], code: 400 }, 34 | ]); 35 | }); 36 | 37 | spec.test('supports JSON types', (ctx) => { 38 | class User extends Model { 39 | @prop() 40 | public name: string; 41 | @prop() 42 | public json0: any; 43 | @prop() 44 | public json1: any; 45 | @prop() 46 | public json2: any; 47 | } 48 | const user = new User({ 49 | name: 'foo', 50 | json0: { foo: 'foo' }, 51 | json1: {}, 52 | }); 53 | user.getProp('name').setErrorCode(100); 54 | user.getProp('json0').setErrorCode(200); 55 | 56 | ctx.deepEqual(user.collectErrors(), [ 57 | { path: ['name'], code: 100 }, 58 | { path: ['json0'], code: 200 }, 59 | ]); 60 | }); 61 | 62 | export default spec; 63 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/commit-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('manage committed states', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | { 30 | title: 'baz', 31 | }, 32 | ], 33 | }); 34 | user.commit(); 35 | ctx.is(user.getProp('name').getInitialValue(), 'foo'); 36 | ctx.is(user.getProp('book', 'title').getInitialValue(), 'bar'); 37 | ctx.is(user.getProp('books', 0, 'title').getInitialValue(), 'baz'); 38 | }); 39 | 40 | export default spec; 41 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/empty-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('sets properties to `null`', (ctx) => { 7 | class Book extends Model { 8 | @prop({ 9 | defaultValue: 'foo', 10 | }) 11 | public title: string; 12 | } 13 | class User extends Model { 14 | @prop({ 15 | defaultValue: 'bar', 16 | }) 17 | public name: string; 18 | @prop({ 19 | emptyValue: 'null', 20 | }) 21 | public description: string; 22 | @prop({ 23 | parser: { resolver: Book }, 24 | defaultValue: {}, 25 | }) 26 | public book: Book; 27 | @prop({ 28 | parser: { array: true, resolver: Book }, 29 | defaultValue: [null, {}], 30 | }) 31 | public books: Book[]; 32 | } 33 | const user = new User({ 34 | name: 'fake', 35 | description: 'fake', 36 | book: { 37 | title: 'fake', 38 | }, 39 | books: [ 40 | { 41 | title: 'fake', 42 | }, 43 | ], 44 | }); 45 | user.empty(); 46 | ctx.deepEqual(user.serialize(), { 47 | name: null, 48 | description: 'null', 49 | book: null, 50 | books: null, 51 | }); 52 | }); 53 | 54 | export default spec; 55 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/fake-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('sets properties to their fake values', (ctx) => { 7 | class Book extends Model { 8 | @prop({ 9 | fakeValue: 'foo', 10 | }) 11 | public title: string; 12 | } 13 | class User extends Model { 14 | @prop({ 15 | fakeValue: 'bar', 16 | }) 17 | public name: string; 18 | @prop({ 19 | parser: { resolver: Book }, 20 | fakeValue: 'bar', 21 | }) 22 | public book: Book; 23 | @prop({ 24 | parser: { array: true, resolver: Book }, 25 | fakeValue: [null, {}], 26 | }) 27 | public books: Book[]; 28 | } 29 | const user = new User(); 30 | user.fake(); 31 | ctx.deepEqual(user.serialize(), { 32 | name: 'bar', 33 | book: { 34 | title: 'foo', 35 | }, 36 | books: [ 37 | null, 38 | { 39 | title: 'foo', 40 | }, 41 | ], 42 | }); 43 | }); 44 | 45 | export default spec; 46 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/flatten-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns an array of props', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | undefined, 30 | { 31 | title: 'baz', 32 | }, 33 | ], 34 | }); 35 | const items = user.flatten(); 36 | ctx.deepEqual(items.map((f) => f.path), [ 37 | ['name'], 38 | ['book'], 39 | ['book', 'title'], 40 | ['books'], 41 | ['books', 0], 42 | ['books', 1], 43 | ['books', 1, 'title'], 44 | ]); 45 | ctx.is(items[2].prop, user.getProp(['book', 'title'])); // ref to prop 46 | ctx.is(items[5].prop, user.getProp(['books'])); // array values ref to parent prop 47 | ctx.is(items[0].value, 'foo'); 48 | ctx.is(items[4].value, undefined); 49 | ctx.is(items[6].value, 'baz'); 50 | }); 51 | 52 | spec.test('supports serialization strategies', (ctx) => { 53 | class User extends Model { 54 | @prop() 55 | public name: string; 56 | @prop({ 57 | serializable: ['input'], 58 | }) 59 | public email: string; 60 | } 61 | const user = new User({ 62 | name: 'foo', 63 | email: 'baz', 64 | }); 65 | const items = user.flatten('input'); 66 | ctx.is(items.length, 1); 67 | }); 68 | 69 | spec.test('supports JSON types', (ctx) => { 70 | class User extends Model { 71 | @prop() 72 | public name: string; 73 | @prop() 74 | public json: any; 75 | } 76 | const user = new User({ 77 | name: 'foo', 78 | json: { foo: 'foo' }, 79 | }); 80 | const items = user.flatten().map(({ path, prop }) => { 81 | return { path, prop: !!prop }; 82 | }); 83 | 84 | ctx.deepEqual(items, [ 85 | { path: ['name'], prop: true }, 86 | { path: ['json'], prop: true }, 87 | { path: ['json', 'foo'], prop: false }, 88 | ]); 89 | }); 90 | 91 | export default spec; 92 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/freeze-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('makes property not settable', async (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | { 30 | title: 'baz', 31 | }, 32 | ], 33 | }); 34 | user.freeze(); 35 | ctx.throws(() => user.name = null); 36 | ctx.throws(() => user.book = null); 37 | ctx.throws(() => user.book.title = null); 38 | ctx.throws(() => user.books = null); 39 | ctx.throws(() => user.books[0].title = null); 40 | }); 41 | 42 | export default spec; 43 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/get-ancestors-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns the first model in a tree of nested models', (ctx) => { 7 | class Author extends Model { 8 | @prop() 9 | public name: string; 10 | } 11 | class Book extends Model { 12 | @prop() 13 | public title: string; 14 | @prop({ 15 | parser: { resolver: Author }, 16 | }) 17 | public author: Author; 18 | } 19 | class User extends Model { 20 | @prop({ 21 | parser: { resolver: Book }, 22 | }) 23 | public book: Book; 24 | } 25 | const user = new User({ 26 | book: { 27 | title: 200, 28 | author: { name: 'John' }, 29 | }, 30 | }); 31 | ctx.deepEqual(user.getAncestors(), []); 32 | ctx.deepEqual(user.book.getAncestors(), [user]); 33 | ctx.deepEqual(user.book.author.getAncestors(), [user, user.book]); 34 | }); 35 | 36 | export default spec; 37 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/get-context-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns configuration context', (ctx) => { 7 | interface Context { 8 | foo: string; 9 | bar: number; 10 | } 11 | class User extends Model {} 12 | const context = { foo: 'foo', bar: 1 }; 13 | const user = new User(null, { context }); 14 | ctx.is(user.getContext().foo, 'foo'); 15 | ctx.is(user.getContext().bar, 1); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/get-parent-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns an instance of the parent model', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | book: { 25 | title: 200, 26 | }, 27 | books: [ 28 | undefined, 29 | { 30 | title: 300, 31 | }, 32 | ], 33 | }); 34 | ctx.is(user.getParent(), null); 35 | ctx.is(user.book.getParent(), user); 36 | ctx.is(user.books[1].getParent(), user); 37 | }); 38 | 39 | export default spec; 40 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/get-prop-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns an instance of a prop at path', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | undefined, 30 | { 31 | title: 'baz', 32 | }, 33 | ], 34 | }); 35 | ctx.is(user.getProp(['name']).getValue(), 'foo'); 36 | ctx.is(user.getProp('name').getValue(), 'foo'); 37 | ctx.is(user.getProp(['book', 'title']).getValue(), 'bar'); 38 | ctx.is(user.getProp('book', 'title').getValue(), 'bar'); 39 | ctx.is(user.getProp(['books', 1]), user.getProp(['books'])); // array items refer to parent prop 40 | ctx.is(user.getProp(['books', 1, 'title']).getValue(), 'baz'); 41 | ctx.is(user.getProp('books', 1, 'title').getValue(), 'baz'); 42 | ctx.is(user.getProp(['fake']), undefined); 43 | ctx.is(user.getProp(['fake', 10, 'title']), undefined); 44 | ctx.is(user.getProp(), undefined); 45 | }); 46 | 47 | export default spec; 48 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/handle-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('handles property errors', async (ctx) => { 7 | const handlers = [{ 8 | resolver: (e) => e.message === 'foo', 9 | code: 100, 10 | }]; 11 | class Book extends Model { 12 | @prop({ 13 | handlers, 14 | }) 15 | public title: string; 16 | } 17 | class Country extends Model { 18 | @prop() 19 | public code: string; 20 | } 21 | class User extends Model { 22 | @prop({ 23 | handlers, 24 | }) 25 | public name: string; 26 | @prop({ 27 | handlers, 28 | parser: { resolver: Book }, 29 | }) 30 | public book0: Book; 31 | @prop({ 32 | handlers, 33 | parser: { array: true, resolver: Book }, 34 | }) 35 | public books0: Book[]; 36 | @prop({ 37 | parser: { resolver: Book }, 38 | }) 39 | public book1: Book; 40 | @prop({ 41 | parser: { array: true, resolver: Book }, 42 | }) 43 | public books1: Book[]; 44 | @prop({ 45 | parser: { resolver: Country }, 46 | }) 47 | public country: Country; 48 | } 49 | const user = new User({ 50 | book1: {}, 51 | books1: [{}], 52 | country: {}, 53 | }); 54 | const problem0 = new Error(); 55 | const problem1 = new Error('foo'); 56 | const code = 100; 57 | await user.handle(problem0); 58 | ctx.true(user.isValid()); 59 | await user.handle(problem1); 60 | ctx.false(user.isValid()); 61 | ctx.throws(() => user.handle(problem0, { quiet: false })); 62 | ctx.throws(() => user.handle(problem1, { quiet: false })); 63 | ctx.deepEqual(user.collectErrors(), [ 64 | { path: ['name'], code }, 65 | { path: ['book0'], code }, 66 | { path: ['books0'], code }, 67 | { path: ['book1', 'title'], code }, 68 | { path: ['books1', 0, 'title'], code }, 69 | ]); 70 | }); 71 | 72 | export default spec; 73 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/has-prop-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns `true` if the prop exists', (ctx) => { 7 | class User extends Model { 8 | @prop() 9 | public name: string; 10 | } 11 | const user = new User(); 12 | ctx.is(user.hasProp(['name']), true); 13 | ctx.is(user.hasProp(['book', 'title']), false); 14 | }); 15 | 16 | export default spec; 17 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/invalidate-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('clears property errors', async (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | book: {}, 25 | books: [null, {}], 26 | }); 27 | user.applyErrors([ 28 | { path: ['name'], code: 100 }, 29 | { path: ['book', 'title'], code: 200 }, 30 | { path: ['books', 1, 'title'], code: 300 }, 31 | ]); 32 | user.invalidate(); 33 | ctx.deepEqual(user.getProp('name').getErrorCode(), null); 34 | ctx.deepEqual(user.getProp('book', 'title').getErrorCode(), null); 35 | ctx.deepEqual(user.getProp('books', 1, 'title').getErrorCode(), null); 36 | }); 37 | 38 | export default spec; 39 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/is-changed-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns `true` if at least one prop has been changed', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const data = { 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | null, 30 | { 31 | title: 'baz', 32 | }, 33 | ], 34 | }; 35 | const user0 = new User(data); 36 | const user1 = new User(data); 37 | const user2 = new User(data); 38 | const user3 = new User(data); 39 | const user4 = new User(); 40 | ctx.true(user0.isChanged()); 41 | user0.name = 'foo-new'; 42 | ctx.true(user0.isChanged()); 43 | user1.book.title = 'bar-new'; 44 | ctx.true(user1.isChanged()); 45 | user2.books[0] = { title: 'baz-new' } as Book; // model instances in array 46 | ctx.true(user2.isChanged()); 47 | user3.books[1].title = 'baz-new'; 48 | ctx.true(user3.isChanged()); 49 | ctx.false(user4.isChanged()); // no data, no change 50 | }); 51 | 52 | export default spec; 53 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/is-equal-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns `true` when the passing object looks the same', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const data = { 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | null, 30 | { 31 | title: 'baz', 32 | }, 33 | ], 34 | }; 35 | ctx.true(new User(data).isEqual(new User(data))); 36 | }); 37 | 38 | export default spec; 39 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/is-valid-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('tell if model has no errors', async (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user0 = new User({ 24 | book: {}, 25 | books: [null, {}], 26 | }); 27 | const user1 = new User(); 28 | ctx.true(user0.isValid()); 29 | ctx.true(user1.isValid()); 30 | user0.applyErrors([ 31 | { path: ['books', 1, 'title'], code: 100}, 32 | ]); 33 | ctx.false(user0.isValid()); 34 | }); 35 | 36 | export default spec; 37 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/reset-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('sets properties to their default values', (ctx) => { 7 | class Book extends Model { 8 | @prop({ 9 | defaultValue: 'foo', 10 | }) 11 | public title: string; 12 | } 13 | class User extends Model { 14 | @prop({ 15 | defaultValue: 'bar', 16 | }) 17 | public name: string; 18 | @prop({ 19 | parser: { resolver: Book }, 20 | defaultValue: {}, 21 | }) 22 | public book: Book; 23 | @prop({ 24 | parser: { array: true, resolver: Book }, 25 | defaultValue: [null, {}], 26 | }) 27 | public books: Book[]; 28 | } 29 | const user = new User({ 30 | name: 'fake', 31 | book: { 32 | title: 'fake', 33 | }, 34 | books: [ 35 | { 36 | title: 'fake', 37 | }, 38 | ], 39 | }); 40 | user.reset(); 41 | ctx.deepEqual(user.serialize(), { 42 | name: 'bar', 43 | book: { 44 | title: 'foo', 45 | }, 46 | books: [ 47 | null, 48 | { 49 | title: 'foo', 50 | }, 51 | ], 52 | }); 53 | }); 54 | 55 | export default spec; 56 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/rollback-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('manage committed states', (ctx) => { 7 | class Book extends Model { 8 | @prop() 9 | public title: string; 10 | } 11 | class User extends Model { 12 | @prop() 13 | public name: string; 14 | @prop({ 15 | parser: { resolver: Book }, 16 | }) 17 | public book: Book; 18 | @prop({ 19 | parser: { array: true, resolver: Book }, 20 | }) 21 | public books: Book[]; 22 | } 23 | const user = new User({ 24 | name: 'foo', 25 | book: { 26 | title: 'bar', 27 | }, 28 | books: [ 29 | { 30 | title: 'baz', 31 | }, 32 | ], 33 | }); 34 | user.commit(); 35 | ctx.is(user.getProp('name').getInitialValue(), 'foo'); 36 | ctx.is(user.getProp('book', 'title').getInitialValue(), 'bar'); 37 | ctx.is(user.getProp('books', 0, 'title').getInitialValue(), 'baz'); 38 | user.populate({ 39 | name: 'foo-new', 40 | book: { 41 | title: 'bar-new', 42 | }, 43 | books: [ 44 | { 45 | title: 'baz-new', 46 | }, 47 | ], 48 | }); 49 | user.rollback(); 50 | ctx.is(user.getProp('name').getValue(), 'foo'); 51 | ctx.is(user.getProp('book', 'title').getValue(), 'bar'); 52 | ctx.is(user.getProp('books', 0, 'title').getValue(), 'baz'); 53 | }); 54 | 55 | export default spec; 56 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/models/validate-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('validates properties or throws on error', async (ctx) => { 7 | const validators = [ 8 | { resolver: (v) => true, code: 100 }, 9 | { resolver: (v) => !!v, code: 200 }, 10 | ]; 11 | class Book extends Model { 12 | @prop({ 13 | validators, 14 | }) 15 | public title: string; 16 | } 17 | class User extends Model { 18 | @prop({ 19 | validators, 20 | }) 21 | public name: string; 22 | @prop({ 23 | parser: { resolver: Book }, 24 | validators, 25 | }) 26 | public book0: Book; 27 | @prop({ 28 | parser: { array: true, resolver: Book }, 29 | validators, 30 | }) 31 | public books0: Book[]; 32 | @prop({ 33 | parser: { resolver: Book }, 34 | validators, 35 | }) 36 | public book1: Book; 37 | @prop({ 38 | parser: { array: true, resolver: Book }, 39 | validators, 40 | }) 41 | public books1: Book[]; 42 | } 43 | const user = new User({ 44 | book1: {}, 45 | books1: [{}], 46 | }); 47 | const code = 200; 48 | await user.validate({ quiet: true }); 49 | ctx.is(await user.validate().catch(() => false), false); 50 | ctx.deepEqual(user.collectErrors(), [ 51 | { path: ['name'], code }, 52 | { path: ['book0'], code }, 53 | { path: ['books0'], code }, 54 | { path: ['book1', 'title'], code }, 55 | { path: ['books1', 0, 'title'], code }, 56 | ]); 57 | }); 58 | 59 | spec.test('validates polymorphic arrays', async (ctx) => { 60 | const validators = [ 61 | { resolver: (v) => !!v, code: 100 }, 62 | ]; 63 | const parser = (v) => { 64 | if (v && v.kind === 'Book') { 65 | return new Book(v); 66 | } else { 67 | return v; 68 | } 69 | }; 70 | class Book extends Model { 71 | @prop({ 72 | validators, 73 | }) 74 | public title: string; 75 | } 76 | class User extends Model { 77 | @prop({ 78 | parser: { array: true, resolver: parser }, 79 | validators, 80 | }) 81 | public books: Book[]; 82 | } 83 | const user = new User({ 84 | books: ['foo', { kind: 'Book' }], 85 | }); 86 | ctx.is(await user.validate().catch(() => false), false); 87 | ctx.deepEqual(user.collectErrors(), [ 88 | { path: ['books', 1, 'title'], code: 100 }, 89 | ]); 90 | }); 91 | 92 | export default spec; 93 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/parser/parse-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { parse } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes through', (ctx) => { 7 | ctx.is(parse(100, null), 100); 8 | ctx.is(parse('100', undefined), '100'); 9 | ctx.deepEqual(parse([1]), [1]); 10 | ctx.deepEqual(parse({ a: 2 }), { a: 2 }); 11 | }); 12 | 13 | spec.test('converts to arrays', (ctx) => { 14 | ctx.deepEqual(parse(100, { array: true }), [100]); 15 | }); 16 | 17 | spec.test('converts to custom type', (ctx) => { 18 | ctx.deepEqual(parse(100, { resolver(v) { 19 | return 'foo'; 20 | } }), 'foo'); 21 | ctx.deepEqual(parse(100, { array: true, resolver(v) { 22 | return 'foo'; 23 | } }), ['foo']); 24 | }); 25 | 26 | export default spec; 27 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/class-config.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('supports default value', (ctx) => { 7 | const prop0 = new Prop({ 8 | defaultValue: 0, 9 | }); 10 | const prop1 = new Prop({ 11 | defaultValue: [], // empty value 12 | }); 13 | const prop2 = new Prop({ 14 | defaultValue: () => 'bar', 15 | }); 16 | ctx.is(prop0.getValue(), 0); 17 | ctx.deepEqual(prop1.getValue(), []); 18 | ctx.is(prop2.getValue(), 'bar'); 19 | }); 20 | 21 | spec.test('supports empty value', (ctx) => { 22 | const prop0 = new Prop({ 23 | emptyValue: 'foo', 24 | }); 25 | const prop1 = new Prop({ 26 | defaultValue: () => 'foo', 27 | }); 28 | ctx.is(prop0.getValue(), 'foo'); 29 | ctx.is(prop1.getValue(), 'foo'); 30 | }); 31 | 32 | spec.test('supports custom getter', (ctx) => { 33 | const prop = new Prop({ 34 | getter: (v) => `foo-${v}`, 35 | }); 36 | ctx.is(prop.getValue(), 'foo-null'); 37 | prop.setValue('bar'); 38 | ctx.is(prop.getValue(), 'foo-bar'); 39 | }); 40 | 41 | spec.test('supports custom setter', (ctx) => { 42 | const prop = new Prop({ 43 | setter: (v) => `foo-${v}`, 44 | }); 45 | ctx.is(prop.getValue(), null); 46 | prop.setValue('bar'); 47 | ctx.is(prop.getValue(), 'foo-bar'); 48 | }); 49 | 50 | export default spec; 51 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/commit-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('copies property data to initial value', (ctx) => { 7 | const prop = new Prop(); 8 | prop.setValue('foo'); 9 | prop.commit(); 10 | prop.setValue('baz'); 11 | ctx.is(prop.getInitialValue(), 'foo'); 12 | }); 13 | 14 | export default spec; 15 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/empty-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('clears property value', (ctx) => { 7 | const prop = new Prop({ 8 | emptyValue: null, 9 | }); 10 | prop.setValue('bar'); 11 | prop.empty(); 12 | ctx.is(prop.getValue(), null); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/fake-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('populates property with fake value', (ctx) => { 7 | const prop = new Prop({ 8 | fakeValue: 'baz', 9 | }); 10 | prop.setValue('bar'); 11 | prop.fake(); 12 | ctx.is(prop.getValue(), 'baz'); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/freeze-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('makes property not settable', async (ctx) => { 7 | const prop = new Prop(); 8 | prop.freeze(); 9 | ctx.throws(() => prop.setValue('foo')); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/get-error-code-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('gets property error code', (ctx) => { 7 | const prop = new Prop(); 8 | ctx.deepEqual(prop.getErrorCode(), null); 9 | prop.setErrorCode(200); 10 | ctx.deepEqual(prop.getErrorCode(), 200); 11 | }); 12 | 13 | export default spec; 14 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/get-initial-value-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns property value on last commit', (ctx) => { 7 | const prop = new Prop(); 8 | prop.setValue('foo'); 9 | prop.commit(); 10 | prop.setValue('bar'); 11 | ctx.is(prop.getInitialValue(), 'foo'); 12 | prop.setValue(false); 13 | prop.commit(); 14 | prop.setValue(true); 15 | ctx.is(prop.getInitialValue(), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/get-raw-value-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns raw property value', (ctx) => { 7 | const prop = new Prop(); 8 | const value = () => true; 9 | prop.setValue(value); 10 | ctx.is(value, value); 11 | }); 12 | 13 | export default spec; 14 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/get-value-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('gets property value', (ctx) => { 7 | const prop = new Prop(); 8 | ctx.is(prop.getValue(), null); 9 | prop.setValue('foo'); 10 | ctx.is(prop.getValue(), 'foo'); 11 | prop.setValue('bar'); 12 | ctx.is(prop.getValue(), 'bar'); 13 | prop.setValue(() => 'zak'); 14 | ctx.is(prop.getValue(), 'zak'); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/handle-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('handles property errors and populates error codes', async (ctx) => { 7 | const prop = new Prop({ 8 | handlers: [ 9 | { code: 400, resolver: (e) => e === 'foo' }, 10 | { code: 401, resolver: (e) => e === 'foo' }, 11 | ], 12 | }); 13 | await prop.handle('foo'); 14 | ctx.deepEqual(prop.getErrorCode(), 400); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/invalidate-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('clears property errors', (ctx) => { 7 | const prop = new Prop(); 8 | prop.setErrorCode(100); 9 | prop.invalidate(); 10 | ctx.deepEqual(prop.getErrorCode(), null); 11 | }); 12 | 13 | export default spec; 14 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-changed-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, Prop, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property value has been changed', (ctx) => { 7 | class User extends Model { 8 | @prop() 9 | public name: string; 10 | } 11 | const user = new User(); 12 | const prop0 = new Prop(); 13 | ctx.false(prop0.isChanged()); 14 | prop0.setValue(null); 15 | ctx.false(prop0.isChanged()); 16 | prop0.setValue('foo'); 17 | prop0.commit(); 18 | ctx.false(prop0.isChanged()); 19 | prop0.setValue(user); 20 | user.name = 'foo'; 21 | ctx.true(prop0.isChanged()); 22 | }); 23 | 24 | export default spec; 25 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-empty-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property value is empty', (ctx) => { 7 | const prop = new Prop(); 8 | ctx.true(prop.isEmpty()); 9 | prop.setValue(null); 10 | ctx.true(prop.isEmpty()); 11 | prop.setValue(''); 12 | ctx.true(prop.isEmpty()); 13 | prop.setValue('foo'); 14 | ctx.false(prop.isEmpty()); 15 | prop.setValue([]); 16 | ctx.true(prop.isEmpty()); 17 | prop.setValue([null]); 18 | ctx.false(prop.isEmpty()); 19 | }); 20 | 21 | export default spec; 22 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-equal-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property value equals to the provided one', (ctx) => { 7 | const prop = new Prop(); 8 | const fn = () => true; 9 | ctx.true(prop.isEqual(null)); 10 | prop.setValue('foo'); 11 | ctx.true(prop.isEqual('foo')); 12 | prop.setValue(fn); 13 | ctx.true(prop.isEqual(fn)); 14 | }); 15 | 16 | export default spec; 17 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-populatable-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property value can be set using strategy', (ctx) => { 7 | const prop = new Prop({ 8 | populatable: ['foo'], 9 | }); 10 | ctx.true(prop.isPopulatable()); 11 | ctx.true(prop.isPopulatable('foo')); 12 | ctx.false(prop.isPopulatable('bar')); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-serializable-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property value can be read using strategy', (ctx) => { 7 | const prop = new Prop({ 8 | serializable: ['foo'], 9 | }); 10 | ctx.true(prop.isSerializable()); 11 | ctx.true(prop.isSerializable('foo')); 12 | ctx.false(prop.isSerializable('bar')); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/is-valid-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Model, Prop, prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('returns true if the property has no errors', (ctx) => { 7 | class User extends Model { 8 | @prop() 9 | public name: string; 10 | } 11 | const user = new User(); 12 | const prop0 = new Prop(); 13 | ctx.true(prop0.isValid()); 14 | prop0.setErrorCode(100); 15 | ctx.false(prop0.isValid()); 16 | prop0.setErrorCode(null); 17 | prop0.setValue(user); 18 | ctx.true(prop0.isValid()); 19 | prop0.__config.parser = { resolver: User }; // nested model type 20 | user.getProp('name').setErrorCode(200); // nested model error 21 | ctx.false(prop0.isValid()); 22 | }); 23 | 24 | export default spec; 25 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/reset-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('resets property to default value', (ctx) => { 7 | const prop = new Prop({ 8 | defaultValue: 'foo', 9 | }); 10 | prop.setValue('bar'); 11 | prop.commit(); 12 | prop.setValue('baz'); 13 | prop.reset(); 14 | ctx.is(prop.getValue(), 'foo'); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/rollback-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('reverts property to the last commited value', (ctx) => { 7 | const prop = new Prop(); 8 | prop.setValue('foo'); 9 | prop.commit(); 10 | prop.setValue('baz'); 11 | prop.rollback(); 12 | ctx.is(prop.getValue(), 'foo'); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/set-error-code-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('sets property error codes', (ctx) => { 7 | const prop = new Prop(); 8 | ctx.deepEqual(prop.getErrorCode(), null); 9 | prop.setErrorCode(200); 10 | ctx.deepEqual(prop.getErrorCode(), 200); 11 | }); 12 | 13 | export default spec; 14 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/set-value-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { integerParser } from '@rawmodel/parsers'; 3 | import { Prop } from '../../..'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('sets property value', (ctx) => { 8 | const prop = new Prop(); 9 | ctx.is(prop.getValue(), null); 10 | prop.setValue('foo'); 11 | ctx.is(prop.getValue(), 'foo'); 12 | prop.setValue('bar'); 13 | ctx.is(prop.getValue(), 'bar'); 14 | prop.setValue(() => 'zak'); 15 | ctx.is(prop.getValue(), 'zak'); 16 | }); 17 | 18 | spec.test('parses input data', (ctx) => { 19 | const prop = new Prop({ 20 | parser: { resolver: integerParser() }, 21 | }); 22 | prop.setValue('100'); 23 | ctx.is(prop.getValue(), 100); 24 | prop.setValue(() => '200'); 25 | ctx.is(prop.getValue(), 200); 26 | }); 27 | 28 | spec.test('support strategies', (ctx) => { 29 | const prop = new Prop({ 30 | populatable: ['foo'], 31 | }); 32 | ctx.is(prop.getValue(), null); 33 | prop.setValue('100', 'bar'); 34 | ctx.is(prop.getValue(), null); 35 | prop.setValue('200', 'foo'); 36 | ctx.is(prop.getValue(), '200'); 37 | }); 38 | 39 | export default spec; 40 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/props/validate-instance-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { Prop } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('validates property and populates error codes', async (ctx) => { 7 | const prop = new Prop({ 8 | validators: [ 9 | { code: 400, resolver: (v) => true }, 10 | { code: 401, resolver: (v) => false }, 11 | ], 12 | }); 13 | await prop.validate(); 14 | ctx.deepEqual(prop.getErrorCode(), 401); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/core/validator/validate-method.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { validate } from '../../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('validates a value and returns error codes', async (ctx) => { 7 | const recipes = [ 8 | { code: 200, resolver: (v) => v === 'foo' }, 9 | { code: 201, resolver: (v) => v === 'foo' }, 10 | { code: 400, resolver: (v) => v === 'bar' }, 11 | { code: 401, resolver: (v) => v === 'bar' }, 12 | ]; 13 | const code = await validate('foo', recipes); 14 | ctx.deepEqual(code, 400); 15 | }); 16 | 17 | spec.test('passes context to each resolver', async (ctx) => { 18 | const config = { 19 | context: { foo: 'foo' }, 20 | }; 21 | const recipes = [ 22 | { code: 100, resolver(v) { 23 | return v === this.foo; 24 | } }, 25 | ]; 26 | const code = await validate('foo', recipes, config); 27 | ctx.deepEqual(code, null); 28 | }); 29 | 30 | export default spec; 31 | -------------------------------------------------------------------------------- /packages/rawmodel-core/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as rawmodel from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!rawmodel.Model); 8 | ctx.true(!!rawmodel.Prop); 9 | ctx.true(!!rawmodel.parse); 10 | ctx.true(!!rawmodel.validate); 11 | ctx.true(!!rawmodel.handle); 12 | }); 13 | 14 | export default spec; 15 | -------------------------------------------------------------------------------- /packages/rawmodel-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/handlers", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/handlers_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/handlers_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/handlers_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/handlers_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/handlers_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/handlers_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/handlers_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "3.0.0", 48 | "tag": "@rawmodel/handlers_v2.4.0", 49 | "date": "Fri, 12 Jul 2019 17:57:56 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "2.3.0", 54 | "tag": "@rawmodel/handlers_v2.3.0", 55 | "date": "Thu, 11 Apr 2019 11:45:39 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "2.2.1", 60 | "tag": "@rawmodel/handlers_v2.2.1", 61 | "date": "Wed, 10 Apr 2019 17:10:31 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "2.2.0", 66 | "tag": "@rawmodel/handlers_v2.2.0", 67 | "date": "Wed, 10 Apr 2019 07:55:41 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "2.1.5", 72 | "tag": "@rawmodel/handlers_v2.1.5", 73 | "date": "Tue, 11 Dec 2018 10:35:14 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "2.1.4", 78 | "tag": "@rawmodel/handlers_v2.1.4", 79 | "date": "Tue, 11 Dec 2018 09:55:28 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "2.1.3", 84 | "tag": "@rawmodel/handlers_v2.1.3", 85 | "date": "Mon, 10 Dec 2018 22:15:09 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "2.1.2", 90 | "tag": "@rawmodel/handlers_v2.1.2", 91 | "date": "Sat, 10 Nov 2018 11:14:49 GMT", 92 | "comments": {} 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/handlers 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Version update only* 39 | 40 | ## 3.0.0 41 | Fri, 12 Jul 2019 17:57:56 GMT 42 | 43 | *Version update only* 44 | 45 | ## 2.3.0 46 | Thu, 11 Apr 2019 11:45:39 GMT 47 | 48 | *Version update only* 49 | 50 | ## 2.2.1 51 | Wed, 10 Apr 2019 17:10:31 GMT 52 | 53 | *Version update only* 54 | 55 | ## 2.2.0 56 | Wed, 10 Apr 2019 07:55:41 GMT 57 | 58 | *Version update only* 59 | 60 | ## 2.1.5 61 | Tue, 11 Dec 2018 10:35:14 GMT 62 | 63 | *Version update only* 64 | 65 | ## 2.1.4 66 | Tue, 11 Dec 2018 09:55:28 GMT 67 | 68 | *Version update only* 69 | 70 | ## 2.1.3 71 | Mon, 10 Dec 2018 22:15:09 GMT 72 | 73 | *Version update only* 74 | 75 | ## 2.1.2 76 | Sat, 10 Nov 2018 11:14:49 GMT 77 | 78 | *Initial release* 79 | 80 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/README.md: -------------------------------------------------------------------------------- 1 | > Collection of error handlers for [Rawmodel](https://github.com/rawmodel/. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/handlers", 3 | "version": "3.3.3", 4 | "description": "Collection of error handlers for RawModel.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "nyc": "^15.0.1", 88 | "ts-node": "^8.10.1", 89 | "@typescript-eslint/eslint-plugin": "2.34.0", 90 | "@typescript-eslint/parser": "2.34.0", 91 | "eslint-config-prettier": "6.11.0", 92 | "eslint-plugin-import": "2.20.2", 93 | "eslint-plugin-jsdoc": "25.4.2", 94 | "eslint-plugin-unicorn": "20.0.0", 95 | "eslint": "7.0.0", 96 | "typescript": "^3.8.3" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/src/handlers/mongo-uniqueness.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a function for detecting MongoDB uniqueness error. 3 | * @param options Handler configuration. 4 | */ 5 | export function mongoUniquenessHandler(options?: { 6 | indexName?: string; 7 | }) { 8 | return (error: any) => { 9 | if (!error || !options) { 10 | return false; 11 | } 12 | 13 | const matches = ( 14 | !!error 15 | && !!error.message 16 | && error.message.indexOf('E11000 duplicate') === 0 17 | && ( 18 | typeof error.code === 'undefined' 19 | || error.code === 11000 20 | ) 21 | ); 22 | 23 | if (matches) { 24 | const regex = /index\:\ (?:.*\.)?\$?(?:([_a-z0-9]*)(?:_\d*)|([_a-z0-9]*))\s*dup key/i; 25 | const match = error.message.match(regex); 26 | return options.indexName === (match[1] || match[2]); 27 | } else { 28 | return false; 29 | } 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './handlers/mongo-uniqueness'; 2 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/src/tests/handlers/mongo-uniqueness.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { mongoUniquenessHandler } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not matching error', (ctx) => { 7 | const error = new Error(); 8 | ctx.false(mongoUniquenessHandler()('text')); 9 | ctx.false(mongoUniquenessHandler()(error)); 10 | }); 11 | 12 | spec.test('succeeds when matching error', (ctx) => { 13 | const error0 = { message: 'E11000 duplicate key error index: test.users.$uniqueEmail dup key: { : \"me@domain.com\" }' }; 14 | const error1 = { message: 'E11000 duplicate key error collection: db.users index: name_1 dup key: { : "Kate" }' }; 15 | const error2 = { message: 'E11000 duplicate key error index: myDb.myCollection.$id dup key: { : ObjectId(\'57226808ec55240c00000272\') }' }; 16 | const error3 = { message: 'E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }' }; 17 | const error4 = { message: 'E11000 duplicate key error collection: upsert_bug.col index: _id_ dup key: { : 3.0 }' }; 18 | ctx.true(mongoUniquenessHandler({ indexName: 'uniqueEmail' })(error0)); 19 | ctx.true(mongoUniquenessHandler({ indexName: 'name' })(error1)); 20 | ctx.true(mongoUniquenessHandler({ indexName: 'id' })(error2)); 21 | ctx.true(mongoUniquenessHandler({ indexName: 'b' })(error3)); 22 | ctx.true(mongoUniquenessHandler({ indexName: '_id' })(error4)); 23 | }); 24 | 25 | export default spec; 26 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as handlers from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!handlers.mongoUniquenessHandler); 8 | }); 9 | 10 | export default spec; 11 | -------------------------------------------------------------------------------- /packages/rawmodel-handlers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/parsers", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/parsers_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/parsers_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/parsers_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/parsers_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/parsers_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/parsers_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/parsers_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "3.0.0", 48 | "tag": "@rawmodel/handlers_v2.4.0", 49 | "date": "Fri, 12 Jul 2019 17:57:56 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "2.3.0", 54 | "tag": "@rawmodel/handlers_v2.3.0", 55 | "date": "Thu, 11 Apr 2019 11:45:39 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "2.2.1", 60 | "tag": "@rawmodel/handlers_v2.2.1", 61 | "date": "Wed, 10 Apr 2019 17:10:31 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "2.2.0", 66 | "tag": "@rawmodel/handlers_v2.2.0", 67 | "date": "Wed, 10 Apr 2019 07:55:41 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "2.1.5", 72 | "tag": "@rawmodel/handlers_v2.1.5", 73 | "date": "Tue, 11 Dec 2018 10:35:14 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "2.1.4", 78 | "tag": "@rawmodel/handlers_v2.1.4", 79 | "date": "Tue, 11 Dec 2018 09:55:28 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "2.1.3", 84 | "tag": "@rawmodel/handlers_v2.1.3", 85 | "date": "Mon, 10 Dec 2018 22:15:09 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "2.1.2", 90 | "tag": "@rawmodel/handlers_v2.1.2", 91 | "date": "Sat, 10 Nov 2018 11:14:49 GMT", 92 | "comments": {} 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/parsers 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Version update only* 39 | 40 | ## 3.0.0 41 | Fri, 12 Jul 2019 17:57:56 GMT 42 | 43 | *Version update only* 44 | 45 | ## 2.3.0 46 | Thu, 11 Apr 2019 11:45:39 GMT 47 | 48 | *Version update only* 49 | 50 | ## 2.2.1 51 | Wed, 10 Apr 2019 17:10:31 GMT 52 | 53 | *Version update only* 54 | 55 | ## 2.2.0 56 | Wed, 10 Apr 2019 07:55:41 GMT 57 | 58 | *Version update only* 59 | 60 | ## 2.1.5 61 | Tue, 11 Dec 2018 10:35:14 GMT 62 | 63 | *Version update only* 64 | 65 | ## 2.1.4 66 | Tue, 11 Dec 2018 09:55:28 GMT 67 | 68 | *Version update only* 69 | 70 | ## 2.1.3 71 | Mon, 10 Dec 2018 22:15:09 GMT 72 | 73 | *Version update only* 74 | 75 | ## 2.1.2 76 | Sat, 10 Nov 2018 11:14:49 GMT 77 | 78 | *Initial release* 79 | 80 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/README.md: -------------------------------------------------------------------------------- 1 | > Collection of data parsers for [Rawmodel](https://github.com/rawmodel/. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/parsers", 3 | "version": "3.3.3", 4 | "description": "Collection of data parsers for RawModel.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "mongodb": "^3.5.7", 88 | "nyc": "^15.0.1", 89 | "ts-node": "^8.10.1", 90 | "@typescript-eslint/eslint-plugin": "2.34.0", 91 | "@typescript-eslint/parser": "2.34.0", 92 | "eslint-config-prettier": "6.11.0", 93 | "eslint-plugin-import": "2.20.2", 94 | "eslint-plugin-jsdoc": "25.4.2", 95 | "eslint-plugin-unicorn": "20.0.0", 96 | "eslint": "7.0.0", 97 | "typescript": "^3.8.3" 98 | }, 99 | "dependencies": { 100 | "@rawmodel/utils": "3.3.3" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './parsers/array'; 2 | export * from './parsers/boolean'; 3 | export * from './parsers/bson-object-id-string'; 4 | export * from './parsers/date'; 5 | export * from './parsers/float'; 6 | export * from './parsers/integer'; 7 | export * from './parsers/string'; 8 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/array.ts: -------------------------------------------------------------------------------- 1 | import { toArray } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to an array. 5 | */ 6 | export function arrayParser() { 7 | return (value: any) => { 8 | try { 9 | return toArray(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/boolean.ts: -------------------------------------------------------------------------------- 1 | import { toBoolean } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to a boolean value. 5 | */ 6 | export function booleanParser() { 7 | return (value: any) => { 8 | try { 9 | return toBoolean(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/bson-object-id-string.ts: -------------------------------------------------------------------------------- 1 | import { isHex, toString, isUndefined, isNull } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to an BSON Object string. 5 | */ 6 | export function bsonObjectIdStringParser() { 7 | return (v) => { 8 | if (isUndefined(v) || isNull(v)) { 9 | return v; 10 | } 11 | try { 12 | v = (toString(v) || '').replace(/\"/g, ''); 13 | return isHex(v) && v.length === 24 ? v : null; 14 | } catch (e) { 15 | return null; 16 | } 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/date.ts: -------------------------------------------------------------------------------- 1 | import { toDate } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to a date object. 5 | */ 6 | export function dateParser() { 7 | return (value: any) => { 8 | try { 9 | return toDate(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/float.ts: -------------------------------------------------------------------------------- 1 | import { toFloat } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to a decimal number. 5 | */ 6 | export function floatParser() { 7 | return (value: any) => { 8 | try { 9 | return toFloat(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/integer.ts: -------------------------------------------------------------------------------- 1 | import { toInteger } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to an integer number. 5 | */ 6 | export function integerParser() { 7 | return (value: any) => { 8 | try { 9 | return toInteger(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/parsers/string.ts: -------------------------------------------------------------------------------- 1 | import { toString } from '@rawmodel/utils'; 2 | 3 | /** 4 | * Returns parser function which converts a value to a string. 5 | */ 6 | export function stringParser() { 7 | return (value: any) => { 8 | try { 9 | return toString(value); 10 | } catch (e) { 11 | return null; 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as parsers from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!parsers.arrayParser); 8 | ctx.true(!!parsers.booleanParser); 9 | ctx.true(!!parsers.bsonObjectIdStringParser); 10 | ctx.true(!!parsers.dateParser); 11 | ctx.true(!!parsers.floatParser); 12 | ctx.true(!!parsers.integerParser); 13 | ctx.true(!!parsers.stringParser); 14 | }); 15 | 16 | export default spec; 17 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/array.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { arrayParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to an array', (ctx) => { 7 | ctx.deepEqual(arrayParser()([]), []); 8 | ctx.deepEqual(arrayParser()([1, 2]), [1, 2]); 9 | ctx.deepEqual(arrayParser()('foo'), ['foo']); 10 | ctx.deepEqual(arrayParser()(100), [100]); 11 | ctx.deepEqual(arrayParser()(true), [true]); 12 | ctx.deepEqual(arrayParser()(false), [false]); 13 | ctx.deepEqual(arrayParser()({}), [{}]); 14 | ctx.deepEqual(arrayParser()({ a: 1 }), [{ a: 1 }]); 15 | ctx.is(arrayParser()(null), null); 16 | ctx.is(arrayParser()(undefined), undefined); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { booleanParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to a boolean value', (ctx) => { 7 | ctx.is(booleanParser()(undefined), undefined); 8 | ctx.is(booleanParser()(null), null); 9 | ctx.is(booleanParser()(false), false); 10 | ctx.is(booleanParser()(NaN), false); 11 | ctx.is(booleanParser()(0), false); 12 | ctx.is(booleanParser()(-100), false); 13 | ctx.is(booleanParser()('-'), false); 14 | ctx.is(booleanParser()('0'), false); 15 | ctx.is(booleanParser()('-10'), false); 16 | ctx.is(booleanParser()('false'), false); 17 | ctx.is(booleanParser()(true), true); 18 | ctx.is(booleanParser()(1), true); 19 | ctx.is(booleanParser()(100), true); 20 | ctx.is(booleanParser()(Infinity), true); 21 | ctx.is(booleanParser()('+'), true); 22 | ctx.is(booleanParser()('1'), true); 23 | ctx.is(booleanParser()('100'), true); 24 | ctx.is(booleanParser()('true'), true); 25 | ctx.is(booleanParser()('yes'), true); 26 | }); 27 | 28 | export default spec; 29 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/bson-object-id-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { ObjectId } from 'mongodb'; 3 | import { bsonObjectIdStringParser } from '../..'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('converts any value to a BSON Object ID string', (ctx) => { 8 | const id = new ObjectId(); 9 | ctx.is(bsonObjectIdStringParser()(id), id.toString()); 10 | ctx.is(bsonObjectIdStringParser()('5d30817cfad30c9eebe7d877'), '5d30817cfad30c9eebe7d877'); 11 | ctx.is(bsonObjectIdStringParser()(null), null); 12 | ctx.is(bsonObjectIdStringParser()(undefined), undefined); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/date.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { dateParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to a date object', (ctx) => { 7 | const d = new Date(); 8 | ctx.is(dateParser()(d), d); 9 | ctx.deepEqual(dateParser()(100000), new Date(100000)); 10 | ctx.deepEqual(dateParser()('2016-01-02'), new Date('2016-01-02')); 11 | ctx.is(dateParser()(undefined), undefined); 12 | ctx.is(dateParser()(null), null); 13 | ctx.is(dateParser()('8sadufsdjfk1231'), null); 14 | }); 15 | 16 | export default spec; 17 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/float.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { floatParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to a decimal number', (ctx) => { 7 | ctx.is(floatParser()(''), 0); 8 | ctx.is(floatParser()('foo'), 0); 9 | ctx.is(floatParser()('100'), 100); 10 | ctx.is(floatParser()('100.3'), 100.3); 11 | ctx.is(floatParser()(200), 200); 12 | ctx.is(floatParser()(200.13), 200.13); 13 | ctx.is(floatParser()(true), 1); 14 | ctx.is(floatParser()(false), 0); 15 | ctx.is(floatParser()(null), null); 16 | ctx.is(floatParser()(undefined), undefined); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/integer.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { integerParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to an integer number', (ctx) => { 7 | ctx.is(integerParser()(''), 0); 8 | ctx.is(integerParser()('foo'), 0); 9 | ctx.is(integerParser()('100'), 100); 10 | ctx.is(integerParser()('100.3'), 100); 11 | ctx.is(integerParser()(200), 200); 12 | ctx.is(integerParser()(200.13), 200); 13 | ctx.is(integerParser()(true), 1); 14 | ctx.is(integerParser()(false), 0); 15 | ctx.is(integerParser()(null), null); 16 | ctx.is(integerParser()(undefined), undefined); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/src/tests/parsers/string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { stringParser } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('converts any value to a string', (ctx) => { 7 | ctx.is(stringParser()('foo'), 'foo'); 8 | ctx.is(stringParser()(100), '100'); 9 | ctx.is(stringParser()(false), 'false'); 10 | ctx.is(stringParser()({ a: 1 }), '{"a":1}'); 11 | ctx.is(stringParser()([{ a: 1 }]), '[{"a":1}]'); 12 | ctx.is(stringParser()(NaN), null); 13 | ctx.is(stringParser()(Infinity), null); 14 | ctx.is(stringParser()(null), null); 15 | ctx.is(stringParser()(undefined), undefined); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-parsers/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "one-line": [ 13 | true, 14 | "check-open-brace", 15 | "check-whitespace" 16 | ], 17 | "no-var-keyword": true, 18 | "quotemark": [ 19 | true, 20 | "single", 21 | "avoid-escape" 22 | ], 23 | "semicolon": [ 24 | true, 25 | "always", 26 | "ignore-bound-class-methods" 27 | ], 28 | "whitespace": [ 29 | true, 30 | "check-branch", 31 | "check-decl", 32 | "check-operator", 33 | "check-module", 34 | "check-separator", 35 | "check-type" 36 | ], 37 | "typedef-whitespace": [ 38 | true, 39 | { 40 | "call-signature": "nospace", 41 | "index-signature": "nospace", 42 | "parameter": "nospace", 43 | "property-declaration": "nospace", 44 | "variable-declaration": "nospace" 45 | }, 46 | { 47 | "call-signature": "onespace", 48 | "index-signature": "onespace", 49 | "parameter": "onespace", 50 | "property-declaration": "onespace", 51 | "variable-declaration": "onespace" 52 | } 53 | ], 54 | "no-internal-module": true, 55 | "no-trailing-whitespace": true, 56 | "no-null-keyword": false, 57 | "prefer-const": true, 58 | "jsdoc-format": true 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/schema", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/schema_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/schema_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/schema_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/schema_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/schema_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/schema_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/schema_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/schema 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Initial release* 39 | 40 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/README.md: -------------------------------------------------------------------------------- 1 | > JSON Schema utils for [Rawmodel](https://github.com/rawmodel/. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/schema", 3 | "version": "3.3.3", 4 | "description": "JSON Schema utils for RawModel.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "@rawmodel/handlers": "3.3.3", 88 | "@rawmodel/parsers": "3.3.3", 89 | "@rawmodel/validators": "3.3.3", 90 | "nyc": "^15.0.1", 91 | "ts-node": "^8.10.1", 92 | "@typescript-eslint/eslint-plugin": "2.34.0", 93 | "@typescript-eslint/parser": "2.34.0", 94 | "eslint-config-prettier": "6.11.0", 95 | "eslint-plugin-import": "2.20.2", 96 | "eslint-plugin-jsdoc": "25.4.2", 97 | "eslint-plugin-unicorn": "20.0.0", 98 | "eslint": "7.0.0", 99 | "typescript": "^3.8.3" 100 | }, 101 | "dependencies": { 102 | "@rawmodel/core": "3.3.3", 103 | "@rawmodel/utils": "3.3.3" 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/src/core/types.ts: -------------------------------------------------------------------------------- 1 | import { HandlerResolver, ParserResolver, SimpleResolver, ValidatorResolver } from '@rawmodel/core'; 2 | 3 | /** 4 | * Schema recipe for creating a model. 5 | */ 6 | export interface SchemaRecipe { 7 | context?: any; 8 | getters?: { [name: string]: (o?: any) => SimpleResolver }; 9 | setters?: { [name: string]: (o?: any) => SimpleResolver }; 10 | defaultValues?: { [name: string]: (o?: any) => (SimpleResolver | any) }; 11 | fakeValues?: { [name: string]: (o?: any) => (SimpleResolver | any) }; 12 | emptyValues?: { [name: string]: (o?: any) => (SimpleResolver | any) }; 13 | parsers?: { [name: string]: (o?: any) => ParserResolver }; 14 | validators?: { [name: string]: (o?: any) => ValidatorResolver }; 15 | handlers?: { [name: string]: (o?: any) => HandlerResolver }; 16 | props?: PropDefinition[]; 17 | } 18 | 19 | /** 20 | * Schema property recipe. 21 | */ 22 | export interface PropDefinition { 23 | name: string; 24 | setter?: string; 25 | getter?: string; 26 | parser?: ParserRecipe; 27 | defaultValue?: string; 28 | fakeValue?: string; 29 | emptyValue?: string; 30 | validators?: ValidatorRecipe[]; 31 | handlers?: HandlerRecipe[]; 32 | populatable?: string[]; 33 | serializable?: string[]; 34 | enumerable?: boolean; 35 | } 36 | 37 | /** 38 | * Property parser recipe. 39 | */ 40 | export interface ParserRecipe { 41 | array?: boolean; 42 | resolver?: string; 43 | options?: any; 44 | } 45 | 46 | /** 47 | * Validation recipe interface. 48 | */ 49 | export interface ValidatorRecipe { 50 | code: number; 51 | resolver: string; 52 | options?: any; 53 | } 54 | 55 | /** 56 | * Handler recipe interface. 57 | */ 58 | export interface HandlerRecipe { 59 | code: number; 60 | resolver: string; 61 | options?: any; 62 | } 63 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/types'; 2 | export * from './core/builder'; 3 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as rawmodel from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!rawmodel.createModelClass); 8 | }); 9 | 10 | export default spec; 11 | -------------------------------------------------------------------------------- /packages/rawmodel-schema/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/utils", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/utils_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/utils_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/utils_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/utils_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/utils_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/utils_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/utils_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "3.0.0", 48 | "tag": "@rawmodel/utils_v2.4.0", 49 | "date": "Fri, 12 Jul 2019 17:57:56 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "2.3.0", 54 | "tag": "@rawmodel/utils_v2.3.0", 55 | "date": "Thu, 11 Apr 2019 11:45:39 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "2.2.1", 60 | "tag": "@rawmodel/utils_v2.2.1", 61 | "date": "Wed, 10 Apr 2019 17:10:31 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "2.2.0", 66 | "tag": "@rawmodel/utils_v2.2.0", 67 | "date": "Wed, 10 Apr 2019 07:55:41 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "2.1.5", 72 | "tag": "@rawmodel/utils_v2.1.5", 73 | "date": "Tue, 11 Dec 2018 10:35:14 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "2.1.4", 78 | "tag": "@rawmodel/utils_v2.1.4", 79 | "date": "Tue, 11 Dec 2018 09:55:28 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "2.1.3", 84 | "tag": "@rawmodel/utils_v2.1.3", 85 | "date": "Mon, 10 Dec 2018 22:15:09 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "2.1.2", 90 | "tag": "@rawmodel/utils_v2.1.2", 91 | "date": "Sat, 10 Nov 2018 11:14:49 GMT", 92 | "comments": {} 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/utils 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Version update only* 39 | 40 | ## 3.0.0 41 | Fri, 12 Jul 2019 17:57:56 GMT 42 | 43 | *Version update only* 44 | 45 | ## 2.3.0 46 | Thu, 11 Apr 2019 11:45:39 GMT 47 | 48 | *Version update only* 49 | 50 | ## 2.2.1 51 | Wed, 10 Apr 2019 17:10:31 GMT 52 | 53 | *Version update only* 54 | 55 | ## 2.2.0 56 | Wed, 10 Apr 2019 07:55:41 GMT 57 | 58 | *Version update only* 59 | 60 | ## 2.1.5 61 | Tue, 11 Dec 2018 10:35:14 GMT 62 | 63 | *Version update only* 64 | 65 | ## 2.1.4 66 | Tue, 11 Dec 2018 09:55:28 GMT 67 | 68 | *Version update only* 69 | 70 | ## 2.1.3 71 | Mon, 10 Dec 2018 22:15:09 GMT 72 | 73 | *Version update only* 74 | 75 | ## 2.1.2 76 | Sat, 10 Nov 2018 11:14:49 GMT 77 | 78 | *Initial release* 79 | 80 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/README.md: -------------------------------------------------------------------------------- 1 | > Helper functions for [Rawmodel](https://github.com/rawmodel/. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/utils", 3 | "version": "3.3.3", 4 | "description": "Helper functions for RawModel.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "nyc": "^15.0.1", 88 | "ts-node": "^8.10.1", 89 | "@typescript-eslint/eslint-plugin": "2.34.0", 90 | "@typescript-eslint/parser": "2.34.0", 91 | "eslint-config-prettier": "6.11.0", 92 | "eslint-plugin-import": "2.20.2", 93 | "eslint-plugin-jsdoc": "25.4.2", 94 | "eslint-plugin-unicorn": "20.0.0", 95 | "eslint": "7.0.0", 96 | "typescript": "^3.8.3" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-array.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is an array. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isArray(v?: any) { 6 | return Array.isArray(v); 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-boolean.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is a boolean value. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isBoolean(v?: any) { 6 | return typeof v === 'boolean'; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-class-of.ts: -------------------------------------------------------------------------------- 1 | import { isPresent } from './is-present'; 2 | 3 | /** 4 | * Returns `true` if the provided value represents an subclass of a class. 5 | * @param v Arbitrary value. 6 | * @param k Class object. 7 | */ 8 | export function isClassOf(v?: any, k?: any) { 9 | try { 10 | return ( 11 | isPresent(v) 12 | && isPresent(k) 13 | && ( 14 | v.prototype instanceof k 15 | || v.prototype.constructor === k 16 | ) 17 | ); 18 | } catch (e) { 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-date.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | import { isInteger } from './is-integer'; 4 | 5 | /** 6 | * Returns `true` if the provided value is a Date object. 7 | * @param v Arbitrary value. 8 | */ 9 | export function isDate(v?: any) { 10 | return ( 11 | !isUndefined(v) 12 | && !isNull(v) 13 | && v.constructor === Date 14 | && isInteger(v.getTime()) 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-deep-equal.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided values are deeply equal. 3 | * @param a Value A. 4 | * @param b Value B. 5 | */ 6 | export function isDeepEqual(a, b) { 7 | if (a === b) { 8 | return true; 9 | } 10 | if (a == null || typeof a != 'object' || b == null || typeof b != 'object') { 11 | return false; 12 | } 13 | 14 | let propsInA = 0; 15 | let propsInB = 0; 16 | 17 | for (const prop in a) { 18 | if (a.hasOwnProperty(prop)) { 19 | propsInA += 1; 20 | } 21 | } 22 | 23 | for (const prop in b) { 24 | if (b.hasOwnProperty(prop)) { 25 | propsInB += 1; 26 | if (!(prop in a) || !isDeepEqual(a[prop], b[prop])) { 27 | return false; 28 | } 29 | } 30 | } 31 | return propsInA == propsInB; 32 | } 33 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-float.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from './is-number'; 2 | 3 | /** 4 | * Returns `true` if the provided value is a number. 5 | * @param v Arbitrary value. 6 | */ 7 | export function isFloat(v?: any) { 8 | return ( 9 | isNumber(v) 10 | && isFinite(v) 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-function.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value represents a function. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isFunction(v?: any) { 6 | return typeof v === 'function'; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-hex.ts: -------------------------------------------------------------------------------- 1 | import { isString } from './is-string'; 2 | 3 | /** 4 | * Returns `true` if the provided value represents a hexadecimal string. 5 | * @param v Arbitrary value. 6 | */ 7 | export function isHex(v?: any) { 8 | return isString(v) && /^[0-9A-F]+$/i.test(v); 9 | } 10 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-infinite.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is infinite number. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isInfinite(v?: any) { 6 | return v === Infinity; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-instance-of.ts: -------------------------------------------------------------------------------- 1 | import { isPresent } from './is-present'; 2 | 3 | /** 4 | * Returns `true` if the provided value represents an instance of a class. 5 | * @param v Arbitrary value. 6 | * @param k Class object. 7 | */ 8 | export function isInstanceOf(v?: any, k?: any) { 9 | try { 10 | return ( 11 | isPresent(v) 12 | && isPresent(k) 13 | && v instanceof k 14 | ); 15 | } catch (e) { 16 | return false; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-integer.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from './is-number'; 2 | 3 | /** 4 | * Returns `true` if the provided value represents an integer number. 5 | * @param v Arbitrary value. 6 | */ 7 | export function isInteger(v?: any) { 8 | return isNumber(v) ? v % 1 === 0 : false; 9 | } 10 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-null.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is null. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isNull(v?: any) { 6 | return v === null; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-number.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is a number. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isNumber(v?: any) { 6 | return typeof v === 'number'; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-object.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | 4 | /** 5 | * Returns `true` if the provided value is an object. 6 | * @param v Arbitrary value. 7 | */ 8 | export function isObject(v?: any) { 9 | return ( 10 | !isUndefined(v) 11 | && !isNull(v) 12 | && v.constructor === Object 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-present.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | import { isNumber } from './is-number'; 4 | import { isString } from './is-string'; 5 | import { isArray } from './is-array'; 6 | import { isObject } from './is-object'; 7 | 8 | /** 9 | * Returns `true` if the provided value is not empty. 10 | * @param v Arbitrary value. 11 | */ 12 | export function isPresent(v?: any) { 13 | return !( 14 | isUndefined(v) 15 | || isNull(v) 16 | || (isNumber(v) && isNaN(v)) 17 | || isString(v) && v === '' 18 | || isArray(v) && v.length === 0 19 | || isObject(v) && Object.keys(v).length === 0 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-string.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is a string. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isString(v?: any) { 6 | return typeof v === 'string'; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-undefined.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns `true` if the provided value is undefined. 3 | * @param v Arbitrary value. 4 | */ 5 | export function isUndefined(v?: any) { 6 | return typeof v === 'undefined' || v === undefined; 7 | } 8 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/is-value.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | import { isNumber } from './is-number'; 4 | import { isInfinite } from './is-infinite'; 5 | 6 | /** 7 | * Returns `true` if the provided value represents a value. 8 | * @param v Arbitrary value. 9 | */ 10 | export function isValue(v?: any) { 11 | return ( 12 | !isUndefined(v) 13 | && !isNull(v) 14 | && !(isNumber(v) && isNaN(v)) 15 | && !isInfinite(v) 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/normalize.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | 4 | /** 5 | * Converts the provided data to primitive data type. 6 | */ 7 | export function normalize(data: any) { 8 | if (isUndefined(data) || isNull(data)) { 9 | return data; 10 | } 11 | try { 12 | return JSON.parse(JSON.stringify(data)); 13 | } catch (e) { 14 | return data; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/realize.ts: -------------------------------------------------------------------------------- 1 | import { isFunction } from './is-function'; 2 | 3 | /** 4 | * Executes the value if the value is a function otherwise the value is returned. 5 | * @param value Function or a value. 6 | * @param context Value function context. 7 | * @param args Value function arguments. 8 | */ 9 | export function realize(value: any, context?: any, args?: any[]) { 10 | try { 11 | return isFunction(value) 12 | ? value.call(context, ...(args || [])) 13 | : value; 14 | } catch (e) { 15 | return value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-array.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from './is-array'; 2 | import { isUndefined } from './is-undefined'; 3 | import { isNull } from './is-null'; 4 | 5 | /** 6 | * Converts the provided value to array. 7 | * @param v Arbitrary value. 8 | */ 9 | export function toArray(v?: any): Array { 10 | if (isArray(v) || isUndefined(v) || isNull(v)) { 11 | return v; 12 | } else { 13 | return [v]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-boolean.ts: -------------------------------------------------------------------------------- 1 | import { isBoolean } from './is-boolean'; 2 | import { isUndefined } from './is-undefined'; 3 | import { isNull } from './is-null'; 4 | import { isInfinite } from './is-infinite'; 5 | 6 | /** 7 | * Converts the provided value to boolean. 8 | * @param v Arbitrary value. 9 | */ 10 | export function toBoolean(v?: any) { 11 | if (isBoolean(v) || isUndefined(v) || isNull(v)) { 12 | return v; 13 | } else { 14 | return ( 15 | parseFloat(v) > 0 16 | || isInfinite(v) 17 | || v === '1' 18 | || v === 'true' 19 | || v === 'yes' 20 | || v === '+' 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-date.ts: -------------------------------------------------------------------------------- 1 | import { isDate } from './is-date'; 2 | import { isUndefined } from './is-undefined'; 3 | import { isNull } from './is-null'; 4 | import { isPresent } from './is-present'; 5 | import { isInteger } from './is-integer'; 6 | 7 | /** 8 | * Converts the provided value to date. 9 | * @param v Arbitrary value. 10 | */ 11 | export function toDate(v?: any): Date { 12 | if (isDate(v) || isUndefined(v) || isNull(v)) { 13 | return v; 14 | } 15 | const date = new Date(v); 16 | return isInteger(date.getTime()) ? date : null; 17 | } 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-float.ts: -------------------------------------------------------------------------------- 1 | import { isFloat } from './is-float'; 2 | import { isUndefined } from './is-undefined'; 3 | import { isNull } from './is-null'; 4 | import { toBoolean } from './to-boolean'; 5 | 6 | /** 7 | * Converts the provided value to number. 8 | * @param v Arbitrary value. 9 | */ 10 | export function toFloat(v?: any) { 11 | if (isFloat(v) || isUndefined(v) || isNull(v)) { 12 | return v; 13 | } 14 | 15 | const pv = parseFloat(v); 16 | if (isFloat(pv)) { 17 | return pv; 18 | } else if (toBoolean(v)) { 19 | return 1; 20 | } else { 21 | return 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-integer.ts: -------------------------------------------------------------------------------- 1 | import { isFloat } from './is-float'; 2 | import { isUndefined } from './is-undefined'; 3 | import { isNull } from './is-null'; 4 | import { isInteger } from './is-integer'; 5 | import { toBoolean } from './to-boolean'; 6 | 7 | /** 8 | * Converts the provided value to integer. 9 | * @param v Arbitrary value. 10 | */ 11 | export function toInteger(v?: any) { 12 | if (isInteger(v) || isUndefined(v) || isNull(v)) { 13 | return v; 14 | } else if (isFloat(v)) { 15 | return parseInt(v); 16 | } else { 17 | const pv = parseInt(v); 18 | if (isInteger(pv)) { 19 | return pv; 20 | } else if (toBoolean(v)) { 21 | return 1; 22 | } else { 23 | return 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-number.ts: -------------------------------------------------------------------------------- 1 | import { toFloat } from './to-float'; 2 | 3 | /** 4 | * Converts the provided value to number (alias). 5 | * @param v Arbitrary value. 6 | */ 7 | export function toNumber(v?: any) { 8 | return toFloat(v); 9 | } 10 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/helpers/to-string.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from './is-undefined'; 2 | import { isNull } from './is-null'; 3 | import { isString } from './is-string'; 4 | import { isNumber } from './is-number'; 5 | import { isInfinite } from './is-infinite'; 6 | 7 | /** 8 | * Converts the provided value to string. 9 | * @param v Arbitrary value. 10 | */ 11 | export function toString(v?: any) { 12 | if (isString(v) || isUndefined(v) || isNull(v)) { 13 | return v; 14 | } else if (isNumber(v) && (isNaN(v) || isInfinite(v))) { 15 | return null; 16 | } else { 17 | return JSON.stringify(v); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './helpers/is-array'; 2 | export * from './helpers/is-boolean'; 3 | export * from './helpers/is-class-of'; 4 | export * from './helpers/is-date'; 5 | export * from './helpers/is-deep-equal'; 6 | export * from './helpers/is-float'; 7 | export * from './helpers/is-function'; 8 | export * from './helpers/is-hex'; 9 | export * from './helpers/is-infinite'; 10 | export * from './helpers/is-instance-of'; 11 | export * from './helpers/is-integer'; 12 | export * from './helpers/is-null'; 13 | export * from './helpers/is-number'; 14 | export * from './helpers/is-object'; 15 | export * from './helpers/is-present'; 16 | export * from './helpers/is-string'; 17 | export * from './helpers/is-undefined'; 18 | export * from './helpers/is-value'; 19 | export * from './helpers/normalize'; 20 | export * from './helpers/realize'; 21 | export * from './helpers/to-array'; 22 | export * from './helpers/to-boolean'; 23 | export * from './helpers/to-date'; 24 | export * from './helpers/to-float'; 25 | export * from './helpers/to-integer'; 26 | export * from './helpers/to-number'; 27 | export * from './helpers/to-string'; 28 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-array.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isArray } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isArray([]), true); 8 | ctx.is(isArray([1]), true); 9 | ctx.is(isArray({}), false); 10 | ctx.is(isArray(Infinity), false); 11 | ctx.is(isArray(NaN), false); 12 | ctx.is(isArray(null), false); 13 | ctx.is(isArray(undefined), false); 14 | ctx.is(isArray(0), false); 15 | ctx.is(isArray(''), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isBoolean } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isBoolean(true), true); 8 | ctx.is(isBoolean(false), true); 9 | ctx.is(isBoolean('true'), false); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-class-of.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-extraneous-class */ 2 | import { Spec } from '@hayspec/spec'; 3 | import { isClassOf } from '../..'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('perform tests', (ctx) => { 8 | class Fake {} 9 | class Base {} 10 | class User extends Base {} 11 | ctx.true(isClassOf(Base, Base)); 12 | ctx.true(isClassOf(User, Base)); 13 | ctx.false(isClassOf(Fake, Base)); 14 | ctx.false(isClassOf(Base, 'foo')); 15 | ctx.false(isClassOf(null, Base)); 16 | ctx.false(isClassOf(undefined, Base)); 17 | ctx.false(isClassOf('foo', Base)); 18 | ctx.false(isClassOf(false, Base)); 19 | }); 20 | 21 | export default spec; 22 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-date.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isDate } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isDate(new Date()), true); 8 | ctx.is(isDate(new Date('ksjlfjsdfjsd')), false); 9 | ctx.is(isDate(null), false); 10 | ctx.is(isDate(undefined), false); 11 | ctx.is(isDate(NaN), false); 12 | ctx.is(isDate(Infinity), false); 13 | ctx.is(isDate(0), false); 14 | ctx.is(isDate(100), false); 15 | ctx.is(isDate(''), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-deep-equal.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isDeepEqual } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.true(isDeepEqual('foo', 'foo')); 8 | ctx.true(isDeepEqual('', '')); 9 | ctx.false(isDeepEqual('', 'foo')); 10 | ctx.true(isDeepEqual(null, null)); 11 | ctx.true(isDeepEqual(undefined, undefined)); 12 | ctx.false(isDeepEqual(null, undefined)); 13 | ctx.true(isDeepEqual(false, false)); 14 | ctx.true(isDeepEqual(true, true)); 15 | ctx.false(isDeepEqual(false, true)); 16 | ctx.true(isDeepEqual({ a: 1, b: 2 }, { a: 1, b: 2 })); 17 | ctx.true(isDeepEqual({ a: 1, b: 2 }, { b: 2, a: 1 })); 18 | ctx.true(isDeepEqual({ a: 1, b: { c: [1, 2] }}, { a: 1, b: { c: [1, 2] }})); 19 | ctx.false(isDeepEqual({ a: 1, b: { c: [1, 2] }}, { a: 1, b: { c: [2, 1] }})); 20 | }); 21 | 22 | export default spec; 23 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-float.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isFloat } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isFloat(0), true); 8 | ctx.is(isFloat(-100), true); 9 | ctx.is(isFloat(100), true); 10 | ctx.is(isFloat(0.1), true); 11 | ctx.is(isFloat(-0.1), true); 12 | ctx.is(isFloat(Infinity), false); 13 | ctx.is(isFloat(NaN), false); 14 | ctx.is(isFloat(null), false); 15 | ctx.is(isFloat(undefined), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-function.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-empty-function */ 2 | /* eslint-disable @typescript-eslint/no-extraneous-class */ 3 | import { Spec } from '@hayspec/spec'; 4 | import { isFunction } from '../..'; 5 | 6 | const spec = new Spec(); 7 | 8 | spec.test('perform tests', (ctx) => { 9 | ctx.is(isFunction(undefined), false); 10 | ctx.is(isFunction(null), false); 11 | ctx.is(isFunction(NaN), false); 12 | ctx.is(isFunction(() => {}), true); 13 | ctx.is(isFunction(function() {}), true); 14 | ctx.is(isFunction(class {}), true); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-hex.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isHex } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.true(isHex('ff0044')); 8 | ctx.false(isHex(true)); 9 | ctx.false(isHex('abcdefg')); 10 | ctx.false(isHex([])); 11 | ctx.false(isHex(null)); 12 | ctx.false(isHex(undefined)); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-infinite.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isInfinite } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isInfinite(Infinity), true); 8 | ctx.is(isInfinite(0), false); 9 | ctx.is(isInfinite(''), false); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-instance-of.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-extraneous-class */ 2 | import { Spec } from '@hayspec/spec'; 3 | import { isInstanceOf } from '../..'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('perform tests', (ctx) => { 8 | class Fake {} 9 | class Base {} 10 | class User extends Base {} 11 | ctx.true(isInstanceOf(new Base(), Base)); 12 | ctx.true(isInstanceOf(new User(), Base)); 13 | ctx.false(isInstanceOf(new Fake(), Base)); 14 | ctx.false(isInstanceOf(new Base(), 'foo')); 15 | ctx.false(isInstanceOf(null, Base)); 16 | ctx.false(isInstanceOf(undefined, Base)); 17 | ctx.false(isInstanceOf('foo', Base)); 18 | ctx.false(isInstanceOf(false, Base)); 19 | }); 20 | 21 | export default spec; 22 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-integer.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isInteger } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isInteger(0), true); 8 | ctx.is(isInteger(10), true); 9 | ctx.is(isInteger(-10), true); 10 | ctx.is(isInteger(10.1), false); 11 | ctx.is(isInteger(Infinity), false); 12 | ctx.is(isInteger(NaN), false); 13 | ctx.is(isInteger(null), false); 14 | ctx.is(isInteger(undefined), false); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-null.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isNull } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isNull(null), true); 8 | ctx.is(isNull(undefined), false); 9 | ctx.is(isNull(''), false); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-number.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isNumber } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isNumber(0), true); 8 | ctx.is(isNumber(100.0), true); 9 | ctx.is(isNumber(-100.0), true); 10 | ctx.is(isNumber(NaN), true); 11 | ctx.is(isNumber(Infinity), true); 12 | ctx.is(isNumber(undefined), false); 13 | ctx.is(isNumber(null), false); 14 | ctx.is(isNumber(''), false); 15 | ctx.is(isNumber('100'), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-object.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isObject } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isObject({}), true); 8 | ctx.is(isObject(Infinity), false); 9 | ctx.is(isObject(NaN), false); 10 | ctx.is(isObject(null), false); 11 | ctx.is(isObject(undefined), false); 12 | ctx.is(isObject(0), false); 13 | ctx.is(isObject(''), false); 14 | ctx.is(isObject(new Date()), false); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-present.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isPresent } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isPresent(0), true); 8 | ctx.is(isPresent(Infinity), true); 9 | ctx.is(isPresent([1]), true); 10 | ctx.is(isPresent(undefined), false); 11 | ctx.is(isPresent(null), false); 12 | ctx.is(isPresent(NaN), false); 13 | ctx.is(isPresent([]), false); 14 | ctx.is(isPresent({}), false); 15 | ctx.is(isPresent(''), false); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isString } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isString(''), true); 8 | ctx.is(isString('foo'), true); 9 | ctx.is(isString(null), false); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-undefined.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isUndefined } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isUndefined(), true); 8 | ctx.is(isUndefined(undefined), true); 9 | ctx.is(isUndefined(''), false); 10 | }); 11 | 12 | export default spec; 13 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/is-value.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { isValue } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(isValue(undefined), false); 8 | ctx.is(isValue(null), false); 9 | ctx.is(isValue(NaN), false); 10 | ctx.is(isValue(Infinity), false); 11 | ctx.is(isValue(0), true); 12 | ctx.is(isValue(''), true); 13 | ctx.is(isValue(new Date()), true); 14 | ctx.is(isValue([]), true); 15 | ctx.is(isValue({}), true); 16 | }); 17 | 18 | export default spec; 19 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/normalize.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { normalize } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | class User { 8 | public foo = 'Foo'; 9 | public bar = 'Bar'; 10 | } 11 | const user = new User(); 12 | ctx.false(normalize(user) instanceof User); 13 | ctx.is(normalize(null), null); 14 | ctx.is(normalize(undefined), undefined); // nullify 15 | ctx.is(normalize(false), false); 16 | ctx.deepEqual(normalize(user), { 17 | foo: 'Foo', 18 | bar: 'Bar', 19 | }); 20 | }); 21 | 22 | export default spec; 23 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/realize.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | import { Spec } from '@hayspec/spec'; 3 | import { realize } from '../..'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('perform tests', (ctx) => { 8 | ctx.is(realize('foo'), 'foo'); 9 | ctx.is(realize(100), 100); 10 | ctx.is(realize(() => 'bar'), 'bar'); 11 | ctx.is(realize(function() { 12 | return `${this.foo}bar`; 13 | }, { foo: 'foo' }), 'foobar'); 14 | ctx.is(realize(function(a, b) { 15 | return `${a}${b}baz`; 16 | }, null, ['foo', 'bar']), 'foobarbaz'); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-array.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toArray } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.deepEqual(toArray(), undefined); 8 | ctx.deepEqual(toArray(undefined), undefined); 9 | ctx.deepEqual(toArray(null), null); 10 | ctx.is(toArray(NaN)[0], NaN); 11 | ctx.deepEqual(toArray(Infinity), [Infinity]); 12 | ctx.deepEqual(toArray([]), []); 13 | ctx.deepEqual(toArray({}), [{}]); 14 | ctx.deepEqual(toArray(''), ['']); 15 | ctx.deepEqual(toArray(0), [0]); 16 | ctx.deepEqual(toArray('john'), ['john']); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toBoolean } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(toBoolean(), undefined); 8 | ctx.is(toBoolean(undefined), undefined); 9 | ctx.is(toBoolean(null), null); 10 | ctx.is(toBoolean(false), false); 11 | ctx.is(toBoolean(NaN), false); 12 | ctx.is(toBoolean(0), false); 13 | ctx.is(toBoolean(-100), false); 14 | ctx.is(toBoolean('-'), false); 15 | ctx.is(toBoolean('0'), false); 16 | ctx.is(toBoolean('-10'), false); 17 | ctx.is(toBoolean('false'), false); 18 | ctx.is(toBoolean(true), true); 19 | ctx.is(toBoolean(1), true); 20 | ctx.is(toBoolean(100), true); 21 | ctx.is(toBoolean(Infinity), true); 22 | ctx.is(toBoolean('+'), true); 23 | ctx.is(toBoolean('1'), true); 24 | ctx.is(toBoolean('100'), true); 25 | ctx.is(toBoolean('true'), true); 26 | ctx.is(toBoolean('yes'), true); 27 | }); 28 | 29 | export default spec; 30 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-date.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toDate } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | const d = new Date(); 8 | ctx.is(toDate(d), d); 9 | ctx.deepEqual(toDate(100000), new Date(100000)); 10 | ctx.deepEqual(toDate('2016-01-02'), new Date('2016-01-02')); 11 | ctx.is(toDate(), undefined); 12 | ctx.is(toDate(undefined), undefined); 13 | ctx.is(toDate(null), null); 14 | ctx.is(toDate('8sadufsdjfk1231'), null); 15 | }); 16 | 17 | export default spec; 18 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-float.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toFloat } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(toFloat(), undefined); 8 | ctx.is(toFloat(undefined), undefined); 9 | ctx.is(toFloat(null), null); 10 | ctx.is(toFloat(false), 0); 11 | ctx.is(toFloat(NaN), 0); 12 | ctx.is(toFloat(0), 0); 13 | ctx.is(toFloat(-100), -100); 14 | ctx.is(toFloat('-100'), -100); 15 | ctx.is(toFloat('-100.0'), -100); 16 | ctx.is(toFloat('-100.99'), -100.99); 17 | ctx.is(toFloat('false'), 0); 18 | ctx.is(toFloat(Infinity), 1); 19 | ctx.is(toFloat('true'), 1); 20 | ctx.is(toFloat('yes'), 1); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-integer.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toInteger } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(toInteger(), undefined); 8 | ctx.is(toInteger(undefined), undefined); 9 | ctx.is(toInteger(null), null); 10 | ctx.is(toInteger(false), 0); 11 | ctx.is(toInteger(NaN), 0); 12 | ctx.is(toInteger(0), 0); 13 | ctx.is(toInteger(-100), -100); 14 | ctx.is(toInteger('-100'), -100); 15 | ctx.is(toInteger('-100.0'), -100); 16 | ctx.is(toInteger('false'), 0); 17 | ctx.is(toInteger(Infinity), 1); 18 | ctx.is(toInteger('true'), 1); 19 | ctx.is(toInteger('yes'), 1); 20 | }); 21 | 22 | export default spec; 23 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-number.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toNumber } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(toNumber(), undefined); 8 | ctx.is(toNumber(undefined), undefined); 9 | ctx.is(toNumber(null), null); 10 | ctx.is(toNumber(false), 0); 11 | ctx.is(toNumber(NaN), 0); 12 | ctx.is(toNumber(0), 0); 13 | ctx.is(toNumber(-100), -100); 14 | ctx.is(toNumber('-100'), -100); 15 | ctx.is(toNumber('-100.0'), -100); 16 | ctx.is(toNumber('-100.99'), -100.99); 17 | ctx.is(toNumber('false'), 0); 18 | ctx.is(toNumber(Infinity), 1); 19 | ctx.is(toNumber('true'), 1); 20 | ctx.is(toNumber('yes'), 1); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/helpers/to-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { toString } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('perform tests', (ctx) => { 7 | ctx.is(toString(), undefined); 8 | ctx.is(toString(undefined), undefined); 9 | ctx.is(toString(null), null); 10 | ctx.is(toString(''), ''); 11 | ctx.is(toString('foo'), 'foo'); 12 | ctx.is(toString(NaN), null); 13 | ctx.is(toString(Infinity), null); 14 | ctx.is(toString(true), 'true'); 15 | ctx.is(toString(100.1), '100.1'); 16 | ctx.is(toString({ a: 1 }), '{"a":1}'); 17 | ctx.is(toString([1, 2]), '[1,2]'); 18 | }); 19 | 20 | export default spec; 21 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as rawmodel from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!rawmodel.isArray); 8 | ctx.true(!!rawmodel.isBoolean); 9 | ctx.true(!!rawmodel.isClassOf); 10 | ctx.true(!!rawmodel.isDate); 11 | ctx.true(!!rawmodel.isDeepEqual); 12 | ctx.true(!!rawmodel.isFloat); 13 | ctx.true(!!rawmodel.isFunction); 14 | ctx.true(!!rawmodel.isHex); 15 | ctx.true(!!rawmodel.isInfinite); 16 | ctx.true(!!rawmodel.isInstanceOf); 17 | ctx.true(!!rawmodel.isInteger); 18 | ctx.true(!!rawmodel.isNull); 19 | ctx.true(!!rawmodel.isNumber); 20 | ctx.true(!!rawmodel.isObject); 21 | ctx.true(!!rawmodel.isPresent); 22 | ctx.true(!!rawmodel.isString); 23 | ctx.true(!!rawmodel.isUndefined); 24 | ctx.true(!!rawmodel.isValue); 25 | ctx.true(!!rawmodel.normalize); 26 | ctx.true(!!rawmodel.realize); 27 | ctx.true(!!rawmodel.toArray); 28 | ctx.true(!!rawmodel.toBoolean); 29 | ctx.true(!!rawmodel.toDate); 30 | ctx.true(!!rawmodel.toFloat); 31 | ctx.true(!!rawmodel.toInteger); 32 | ctx.true(!!rawmodel.toNumber); 33 | ctx.true(!!rawmodel.toString); 34 | }); 35 | 36 | export default spec; 37 | -------------------------------------------------------------------------------- /packages/rawmodel-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/validators", 3 | "entries": [ 4 | { 5 | "version": "3.3.3", 6 | "tag": "@rawmodel/validators_v3.3.3", 7 | "date": "Wed, 23 Oct 2019 07:59:15 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "3.3.2", 12 | "tag": "@rawmodel/validators_v3.3.2", 13 | "date": "Wed, 23 Oct 2019 06:38:22 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "3.3.1", 18 | "tag": "@rawmodel/validators_v3.3.1", 19 | "date": "Thu, 03 Oct 2019 20:16:12 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "3.3.0", 24 | "tag": "@rawmodel/validators_v3.3.0", 25 | "date": "Thu, 03 Oct 2019 15:49:09 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "3.2.1", 30 | "tag": "@rawmodel/validators_v3.2.1", 31 | "date": "Sun, 29 Sep 2019 10:22:42 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "3.2.0", 36 | "tag": "@rawmodel/validators_v3.2.0", 37 | "date": "Fri, 27 Sep 2019 23:06:25 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "3.1.0", 42 | "tag": "@rawmodel/validators_v3.1.0", 43 | "date": "Fri, 27 Sep 2019 22:48:59 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "3.0.0", 48 | "tag": "@rawmodel/validators_v2.4.0", 49 | "date": "Fri, 12 Jul 2019 17:57:56 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "2.3.0", 54 | "tag": "@rawmodel/validators_v2.3.0", 55 | "date": "Thu, 11 Apr 2019 11:45:39 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "2.2.1", 60 | "tag": "@rawmodel/validators_v2.2.1", 61 | "date": "Wed, 10 Apr 2019 17:10:31 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "2.2.0", 66 | "tag": "@rawmodel/validators_v2.2.0", 67 | "date": "Wed, 10 Apr 2019 07:55:41 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "2.1.5", 72 | "tag": "@rawmodel/validators_v2.1.5", 73 | "date": "Tue, 11 Dec 2018 10:35:14 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "2.1.4", 78 | "tag": "@rawmodel/validators_v2.1.4", 79 | "date": "Tue, 11 Dec 2018 09:55:28 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "2.1.3", 84 | "tag": "@rawmodel/validators_v2.1.3", 85 | "date": "Mon, 10 Dec 2018 22:15:09 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "2.1.2", 90 | "tag": "@rawmodel/validators_v2.1.2", 91 | "date": "Sat, 10 Nov 2018 11:14:49 GMT", 92 | "comments": {} 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @rawmodel/validators 2 | 3 | This log was last generated on Wed, 23 Oct 2019 07:59:15 GMT and should not be manually modified. 4 | 5 | ## 3.3.3 6 | Wed, 23 Oct 2019 07:59:15 GMT 7 | 8 | *Version update only* 9 | 10 | ## 3.3.2 11 | Wed, 23 Oct 2019 06:38:22 GMT 12 | 13 | *Version update only* 14 | 15 | ## 3.3.1 16 | Thu, 03 Oct 2019 20:16:12 GMT 17 | 18 | *Version update only* 19 | 20 | ## 3.3.0 21 | Thu, 03 Oct 2019 15:49:09 GMT 22 | 23 | *Version update only* 24 | 25 | ## 3.2.1 26 | Sun, 29 Sep 2019 10:22:42 GMT 27 | 28 | *Version update only* 29 | 30 | ## 3.2.0 31 | Fri, 27 Sep 2019 23:06:25 GMT 32 | 33 | *Version update only* 34 | 35 | ## 3.1.0 36 | Fri, 27 Sep 2019 22:48:59 GMT 37 | 38 | *Version update only* 39 | 40 | ## 3.0.0 41 | Fri, 12 Jul 2019 17:57:56 GMT 42 | 43 | *Version update only* 44 | 45 | ## 2.3.0 46 | Thu, 11 Apr 2019 11:45:39 GMT 47 | 48 | *Version update only* 49 | 50 | ## 2.2.1 51 | Wed, 10 Apr 2019 17:10:31 GMT 52 | 53 | *Version update only* 54 | 55 | ## 2.2.0 56 | Wed, 10 Apr 2019 07:55:41 GMT 57 | 58 | *Version update only* 59 | 60 | ## 2.1.5 61 | Tue, 11 Dec 2018 10:35:14 GMT 62 | 63 | *Version update only* 64 | 65 | ## 2.1.4 66 | Tue, 11 Dec 2018 09:55:28 GMT 67 | 68 | *Version update only* 69 | 70 | ## 2.1.3 71 | Mon, 10 Dec 2018 22:15:09 GMT 72 | 73 | *Version update only* 74 | 75 | ## 2.1.2 76 | Sat, 10 Nov 2018 11:14:49 GMT 77 | 78 | *Initial release* 79 | 80 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/README.md: -------------------------------------------------------------------------------- 1 | > Collection of validators for [Rawmodel](https://github.com/rawmodel/. 2 | 3 | [Rawmodel](https://github.com/rawmodel/framework) is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the **server** and **browser** (using module bundler), written with [TypeScript](https://www.typescriptlang.org). It's actively maintained, well tested and already used in production environments. The source code is available on [GitHub](https://github.com/rawmodel/framework) where you can also find our [issue tracker](https://github.com/rawmodel/framework/issues). 4 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rawmodel/validators", 3 | "version": "3.3.3", 4 | "description": "Collection of validators for RawModel.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "clean": "rm -Rf ./dist", 9 | "build": "npm run clean; npx tsc", 10 | "lint": "npx eslint 'src/**/*.ts?(x)'", 11 | "test": "npx nyc npx hayspec test" 12 | }, 13 | "hayspec": { 14 | "require": [ 15 | "ts-node/register" 16 | ], 17 | "match": [ 18 | "./src/tests/**/*.test.ts" 19 | ] 20 | }, 21 | "nyc": { 22 | "extension": [ 23 | ".ts" 24 | ], 25 | "require": [ 26 | "ts-node/register" 27 | ], 28 | "exclude": [ 29 | "src/tests" 30 | ] 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/rawmodel/framework.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/rawmodel/framework/issues" 38 | }, 39 | "homepage": "https://github.com/rawmodel/framework#readme", 40 | "keywords": [ 41 | "model", 42 | "modeling", 43 | "document", 44 | "object", 45 | "schema", 46 | "orm", 47 | "odm", 48 | "map", 49 | "mapping", 50 | "context", 51 | "contextify", 52 | "rawmodel", 53 | "class", 54 | "db", 55 | "database", 56 | "storage", 57 | "structure", 58 | "structuring", 59 | "error", 60 | "errors", 61 | "handling", 62 | "handle", 63 | "valid", 64 | "validate", 65 | "validation", 66 | "validator", 67 | "validating", 68 | "type", 69 | "cast", 70 | "casting", 71 | "history", 72 | "tracking", 73 | "change", 74 | "field", 75 | "fields", 76 | "serialize", 77 | "serialization", 78 | "serializable", 79 | "schema", 80 | "json" 81 | ], 82 | "author": "Kristijan Sedlak (Xpepermint)", 83 | "license": "MIT", 84 | "devDependencies": { 85 | "@hayspec/cli": "^0.10.0", 86 | "@hayspec/spec": "^0.10.0", 87 | "mongodb": "^3.5.7", 88 | "nyc": "^15.0.1", 89 | "ts-node": "^8.10.1", 90 | "@typescript-eslint/eslint-plugin": "2.34.0", 91 | "@typescript-eslint/parser": "2.34.0", 92 | "eslint-config-prettier": "6.11.0", 93 | "eslint-plugin-import": "2.20.2", 94 | "eslint-plugin-jsdoc": "25.4.2", 95 | "eslint-plugin-unicorn": "20.0.0", 96 | "eslint": "7.0.0", 97 | "typescript": "^3.8.3" 98 | }, 99 | "dependencies": { 100 | "@rawmodel/utils": "3.3.3" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './validators/absence'; 2 | export * from './validators/array-exclusion'; 3 | export * from './validators/array-inclusion'; 4 | export * from './validators/array-length'; 5 | export * from './validators/base64'; 6 | export * from './validators/bson-object-id'; 7 | export * from './validators/date'; 8 | export * from './validators/email'; 9 | export * from './validators/eth-address'; 10 | export * from './validators/exclusion'; 11 | export * from './validators/fqdn'; 12 | export * from './validators/hex-color'; 13 | export * from './validators/hex'; 14 | export * from './validators/inclusion'; 15 | export * from './validators/json-string'; 16 | export * from './validators/downcase-string'; 17 | export * from './validators/match'; 18 | export * from './validators/number-size'; 19 | export * from './validators/presence'; 20 | export * from './validators/string-exclusion'; 21 | export * from './validators/string-inclusion'; 22 | export * from './validators/string-length'; 23 | export * from './validators/upcase-string'; 24 | export * from './validators/uuid'; 25 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import * as validators from '..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('exposed content', (ctx) => { 7 | ctx.true(!!validators.absenceValidator); 8 | ctx.true(!!validators.arrayExclusionValidator); 9 | ctx.true(!!validators.arrayInclusionValidator); 10 | ctx.true(!!validators.arrayLengthValidator); 11 | ctx.true(!!validators.base64Validator); 12 | ctx.true(!!validators.bsonObjectIdValidator); 13 | ctx.true(!!validators.dateValidator); 14 | ctx.true(!!validators.emailValidator); 15 | ctx.true(!!validators.ethAddressValidator); 16 | ctx.true(!!validators.exclusionValidator); 17 | ctx.true(!!validators.fqdnValidator); 18 | ctx.true(!!validators.hexColorValidator); 19 | ctx.true(!!validators.hexValidator); 20 | ctx.true(!!validators.inclusionValidator); 21 | ctx.true(!!validators.jsonStringValidator); 22 | ctx.true(!!validators.downcaseStringValidator); 23 | ctx.true(!!validators.matchValidator); 24 | ctx.true(!!validators.numberSizeValidator); 25 | ctx.true(!!validators.presenceValidator); 26 | ctx.true(!!validators.stringExclusionValidator); 27 | ctx.true(!!validators.stringInclusionValidator); 28 | ctx.true(!!validators.stringLengthValidator); 29 | ctx.true(!!validators.upcaseStringValidator); 30 | ctx.true(!!validators.uuidValidator); 31 | }); 32 | 33 | export default spec; 34 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/absence.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { absenceValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes when null', (ctx) => { 7 | ctx.true(absenceValidator()(null)); 8 | }); 9 | 10 | spec.test('passes when undefined', (ctx) => { 11 | ctx.true(absenceValidator()()); 12 | }); 13 | 14 | spec.test('passes when blank', (ctx) => { 15 | ctx.true(absenceValidator()('')); 16 | ctx.true(absenceValidator()([])); 17 | }); 18 | 19 | spec.test('fails when not blank', (ctx) => { 20 | ctx.false(absenceValidator()('text')); 21 | ctx.false(absenceValidator()([''])); 22 | ctx.false(absenceValidator()(['text'])); 23 | }); 24 | 25 | export default spec; 26 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/array-exclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { arrayExclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes when value not present', (ctx) => { 7 | ctx.true(arrayExclusionValidator()(undefined)); 8 | ctx.true(arrayExclusionValidator()(null)); 9 | }); 10 | 11 | spec.test('passes when not included in the list', (ctx) => { 12 | ctx.true(arrayExclusionValidator({ values: [1, 2, 3] })([2, 4])); 13 | }); 14 | 15 | spec.test('fails when included in the list', (ctx) => { 16 | ctx.false(arrayExclusionValidator({ values: [1, 2, 3] })([1, 2])); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/array-inclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { arrayInclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes when value not present', (ctx) => { 7 | ctx.true(arrayInclusionValidator()(undefined)); 8 | ctx.true(arrayInclusionValidator()(null)); 9 | }); 10 | 11 | spec.test('passes when included in the list', (ctx) => { 12 | ctx.true(arrayInclusionValidator({ values: [1, 2, 3] })([1, 2])); 13 | }); 14 | 15 | spec.test('fails when not included in the list', (ctx) => { 16 | ctx.false(arrayInclusionValidator({ values: [1, 2, 3] })([1, 4])); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/array-length.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { arrayLengthValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not an array', (ctx) => { 7 | ctx.false(arrayLengthValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when too small', (ctx) => { 11 | ctx.false(arrayLengthValidator({ min: 3 })([1, 2])); 12 | }); 13 | 14 | spec.test('fails when too large', (ctx) => { 15 | ctx.false(arrayLengthValidator({ max: 2 })([1, 2, 3])); 16 | }); 17 | 18 | spec.test('passes when value not present', (ctx) => { 19 | ctx.true(arrayLengthValidator()(undefined)); 20 | ctx.true(arrayLengthValidator()(null)); 21 | }); 22 | 23 | spec.test('passes without options', (ctx) => { 24 | ctx.true(arrayLengthValidator()([1, 2, 3])); 25 | }); 26 | 27 | spec.test('passes when valid', (ctx) => { 28 | ctx.true(arrayLengthValidator({ min: 2, max: 4 })([1, 2, 3])); 29 | ctx.true(arrayLengthValidator({ minOrEqual: 2 })([1, 2])); 30 | ctx.true(arrayLengthValidator({ maxOrEqual: 2 })([1, 2])); 31 | }); 32 | 33 | export default spec; 34 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/base64.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { base64Validator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(base64Validator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(base64Validator()('1')); 12 | ctx.false(base64Validator()('12345')); 13 | ctx.false(base64Validator()('')); 14 | ctx.false(base64Validator()('Vml2YW11cyBmZXJtZtesting123')); 15 | ctx.false(base64Validator()('Zg=')); 16 | ctx.false(base64Validator()('Z===')); 17 | ctx.false(base64Validator()('Zm=8')); 18 | ctx.false(base64Validator()('=m9vYg==')); 19 | ctx.false(base64Validator()('Zm9vYmFy====')); 20 | }); 21 | 22 | spec.test('passes when value not present', (ctx) => { 23 | ctx.true(base64Validator()(undefined)); 24 | ctx.true(base64Validator()(null)); 25 | }); 26 | 27 | spec.test('passes when valid', (ctx) => { 28 | ctx.true(base64Validator()('Zg==')); 29 | ctx.true(base64Validator()('Zm8=')); 30 | ctx.true(base64Validator()('Zm9v')); 31 | ctx.true(base64Validator()('Zm9vYg==')); 32 | ctx.true(base64Validator()('Zm9vYmE=')); 33 | ctx.true(base64Validator()('Zm9vYmFy')); 34 | ctx.true(base64Validator()('dGVzdA==')); 35 | ctx.true(base64Validator()('TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=')); 36 | ctx.true(base64Validator()('Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==')); 37 | ctx.true(base64Validator()('U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==')); 38 | ctx.true(base64Validator()('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNwUAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0YerhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5TkukhxQmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZFwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZHQIDAQAB')); 39 | }); 40 | 41 | export default spec; 42 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/bson-object-id.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { bsonObjectIdValidator } from '../..'; 3 | import { ObjectId } from 'mongodb'; 4 | 5 | const spec = new Spec(); 6 | 7 | spec.test('fails when not a string', (ctx) => { 8 | ctx.false(bsonObjectIdValidator()(true)); 9 | }); 10 | 11 | spec.test('fails when invalid', (ctx) => { 12 | ctx.false(bsonObjectIdValidator()('507f1f77bcf86cd7994390')); 13 | }); 14 | 15 | spec.test('passes when value not present', (ctx) => { 16 | ctx.true(bsonObjectIdValidator()(undefined)); 17 | ctx.true(bsonObjectIdValidator()(null)); 18 | }); 19 | 20 | spec.test('passes when valid', (ctx) => { 21 | ctx.true(bsonObjectIdValidator()('5d30817cfad30c9eebe7d877')); 22 | ctx.true(bsonObjectIdValidator()(new ObjectId())); 23 | }); 24 | 25 | export default spec; 26 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/date.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { dateValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(dateValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(dateValidator()('x')); 12 | }); 13 | 14 | spec.test('fails when invalid iso8601', (ctx) => { 15 | ctx.false(dateValidator({ iso: true })('12.12.2016')); 16 | }); 17 | 18 | spec.test('passes when value not present', (ctx) => { 19 | ctx.true(dateValidator()(undefined)); 20 | ctx.true(dateValidator()(null)); 21 | }); 22 | 23 | spec.test('passes when valid', (ctx) => { 24 | ctx.true(dateValidator()('2009')); 25 | }); 26 | 27 | spec.test('passes when valid iso8601', (ctx) => { 28 | ctx.true(dateValidator({ iso: true })('2009-12T12:34')); 29 | }); 30 | 31 | export default spec; 32 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/downcase-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { downcaseStringValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(downcaseStringValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(downcaseStringValidator()('Hello')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(downcaseStringValidator()(undefined)); 16 | ctx.true(downcaseStringValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when valid', (ctx) => { 20 | ctx.true(downcaseStringValidator()('hello')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/email.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { emailValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(emailValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(emailValidator()('john')); 12 | }); 13 | 14 | spec.test('fails when display name', (ctx) => { 15 | ctx.false(emailValidator()('John ')); 16 | }); 17 | 18 | spec.test('fails with UTF8 characters', (ctx) => { 19 | ctx.false(emailValidator()('šžćč@domain.com')); 20 | }); 21 | 22 | spec.test('fails without top-level domain name', (ctx) => { 23 | ctx.false(emailValidator()('john@domain')); 24 | }); 25 | 26 | spec.test('fails without top-level domain name', (ctx) => { 27 | ctx.true(emailValidator({ requireTld: false })('john@domain')); 28 | ctx.false(emailValidator({ requireTld: true })('john@domain')); 29 | }); 30 | 31 | spec.test('passes when value not present', (ctx) => { 32 | ctx.true(emailValidator()(undefined)); 33 | ctx.true(emailValidator()(null)); 34 | }); 35 | 36 | spec.test('passes with display name when allowDisplayName is true', (ctx) => { 37 | ctx.true(emailValidator({ allowDisplayName: true })('John ')); 38 | ctx.false(emailValidator({ allowDisplayName: false })('John ')); 39 | }); 40 | 41 | spec.test('passes with UTF8 characters when allowUtf8LocalPart is true', (ctx) => { 42 | ctx.true(emailValidator({ allowUtf8LocalPart: true })('đšpŽĆČ@domain.com')); 43 | ctx.false(emailValidator({ allowUtf8LocalPart: false })('đšpŽĆČ@domain.com')); 44 | }); 45 | 46 | export default spec; 47 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/eth-address.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { ethAddressValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(ethAddressValidator()(true)); 8 | }); 9 | 10 | spec.test('fails on invalid address', (ctx) => { 11 | ctx.false(ethAddressValidator()('domain')); 12 | ctx.false(ethAddressValidator()('0x0')); 13 | }); 14 | 15 | spec.test('passes when value not present', (ctx) => { 16 | ctx.true(ethAddressValidator()(undefined)); 17 | ctx.true(ethAddressValidator()(null)); 18 | }); 19 | 20 | spec.test('passes on valid address', (ctx) => { 21 | ctx.true(ethAddressValidator()('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed')); 22 | ctx.true(ethAddressValidator()('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359')); 23 | ctx.true(ethAddressValidator()('0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB')); 24 | ctx.true(ethAddressValidator()('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb')); 25 | }); 26 | 27 | export default spec; 28 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/exclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { exclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes when value not present', (ctx) => { 7 | ctx.true(exclusionValidator()(undefined)); 8 | ctx.true(exclusionValidator()(null)); 9 | }); 10 | 11 | spec.test('passes when not included in the list', (ctx) => { 12 | ctx.false(exclusionValidator({ values: [false, true] })(true)); 13 | }); 14 | 15 | spec.test('fails when included in the list', (ctx) => { 16 | ctx.true(exclusionValidator({ values: [false] })(true)); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/fqdn.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { fqdnValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(fqdnValidator()(true)); 8 | }); 9 | 10 | spec.test('fails without top-level domain name', (ctx) => { 11 | ctx.false(fqdnValidator()('domain')); 12 | }); 13 | 14 | spec.test('fails when including underscore', (ctx) => { 15 | ctx.false(fqdnValidator()('do_main.com')); 16 | }); 17 | 18 | spec.test('fails when including trailing dot', (ctx) => { 19 | ctx.false(fqdnValidator()('domain.com.')); 20 | }); 21 | 22 | spec.test('passes when value not present', (ctx) => { 23 | ctx.true(fqdnValidator()(undefined)); 24 | ctx.true(fqdnValidator()(null)); 25 | }); 26 | 27 | spec.test('passes with top-level domain name', (ctx) => { 28 | ctx.true(fqdnValidator()('domain.com')); 29 | }); 30 | 31 | spec.test('passes when including underscore where allowUnderscores is true', (ctx) => { 32 | ctx.true(fqdnValidator({ allowUnderscores: true })('do_main.com')); 33 | }); 34 | 35 | spec.test('passes when including trailing dot where allowTrailingDot is true', (ctx) => { 36 | ctx.true(fqdnValidator({ allowTrailingDot: true })('domain.com.')); 37 | }); 38 | 39 | export default spec; 40 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/hex-color.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { hexColorValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(hexColorValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(hexColorValidator()('#ff')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(hexColorValidator()(undefined)); 16 | ctx.true(hexColorValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when valid', (ctx) => { 20 | ctx.true(hexColorValidator()('#ff0034')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/hex.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { hexValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(hexValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(hexValidator()('abcdefg')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(hexValidator()(undefined)); 16 | ctx.true(hexValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when valid', (ctx) => { 20 | ctx.true(hexValidator()('ff0044')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/inclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { inclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('passes when value not present', (ctx) => { 7 | ctx.true(inclusionValidator()(undefined)); 8 | ctx.true(inclusionValidator()(null)); 9 | }); 10 | 11 | spec.test('passes when included in the list', (ctx) => { 12 | ctx.true(inclusionValidator({ values: [false, true] })(true)); 13 | }); 14 | 15 | spec.test('fails when not included in the list', (ctx) => { 16 | ctx.false(inclusionValidator({ values: [false] })(true)); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/json-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { jsonStringValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(jsonStringValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(jsonStringValidator()('{key: "value"}')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(jsonStringValidator()(undefined)); 16 | ctx.true(jsonStringValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when valid', (ctx) => { 20 | ctx.true(jsonStringValidator()('{"key": "value"}')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/match.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { matchValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails with an invalid pattern', (ctx) => { 7 | ctx.false(matchValidator({ regexp: /me/i })('foo')); 8 | }); 9 | 10 | spec.test('passes when value not present', (ctx) => { 11 | ctx.true(matchValidator()(undefined)); 12 | ctx.true(matchValidator()(null)); 13 | }); 14 | 15 | spec.test('passes with a valid pattern', (ctx) => { 16 | ctx.true(matchValidator({ regexp: /me/i })('me')); 17 | }); 18 | 19 | export default spec; 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/number-size.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { numberSizeValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a number', (ctx) => { 7 | ctx.false(numberSizeValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when too small', (ctx) => { 11 | ctx.false(numberSizeValidator({ min: 200 })(100)); 12 | }); 13 | 14 | spec.test('fails when too large', (ctx) => { 15 | ctx.false(numberSizeValidator({ max: 20 })(100)); 16 | }); 17 | 18 | spec.test('passes when value not present', (ctx) => { 19 | ctx.true(numberSizeValidator()(undefined)); 20 | ctx.true(numberSizeValidator()(null)); 21 | }); 22 | 23 | spec.test('passes without options', (ctx) => { 24 | ctx.true(numberSizeValidator()(100)); 25 | }); 26 | 27 | spec.test('passes when valid', (ctx) => { 28 | ctx.true(numberSizeValidator({ min: 10, max: 1000 })(100)); 29 | ctx.true(numberSizeValidator({ minOrEqual: 100 })(100)); 30 | ctx.true(numberSizeValidator({ maxOrEqual: 100 })(100)); 31 | }); 32 | 33 | export default spec; 34 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/presence.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { presenceValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when null', (ctx) => { 7 | ctx.false(presenceValidator()(null)); 8 | }); 9 | 10 | spec.test('fails when undefined', (ctx) => { 11 | ctx.false(presenceValidator()(undefined)); 12 | }); 13 | 14 | spec.test('fails when blank', (ctx) => { 15 | ctx.false(presenceValidator()('')); 16 | }); 17 | 18 | spec.test('passes when present', (ctx) => { 19 | ctx.true(presenceValidator()('john')); 20 | }); 21 | 22 | export default spec; 23 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/string-exclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { stringExclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when a string', (ctx) => { 7 | ctx.true(stringExclusionValidator({ seed: 'true' })(true)); 8 | }); 9 | 10 | spec.test('fails when containing the provided seed', (ctx) => { 11 | ctx.true(stringExclusionValidator({ seed: 'black' })('my fake2 description')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(stringExclusionValidator()(undefined)); 16 | ctx.true(stringExclusionValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when not containing the provided seed', (ctx) => { 20 | ctx.false(stringExclusionValidator({ seed: 'fake' })('my fake description')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/string-inclusion.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { stringInclusionValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(stringInclusionValidator({ seed: 'true' })(true)); 8 | }); 9 | 10 | spec.test('fails when not containing the provided seed', (ctx) => { 11 | ctx.false(stringInclusionValidator({ seed: 'black' })('my fake2 description')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(stringInclusionValidator()(undefined)); 16 | ctx.true(stringInclusionValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when containing the provided seed', (ctx) => { 20 | ctx.true(stringInclusionValidator({ seed: 'fake' })('my fake description')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/string-length.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { stringLengthValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(stringLengthValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when too short', (ctx) => { 11 | ctx.false(stringLengthValidator({ min: 10 })('hello')); 12 | }); 13 | 14 | spec.test('fails when too long', (ctx) => { 15 | ctx.false(stringLengthValidator({ max: 2 })('hello')); 16 | }); 17 | 18 | spec.test('passes when value not present', (ctx) => { 19 | ctx.true(stringLengthValidator()(undefined)); 20 | ctx.true(stringLengthValidator()(null)); 21 | }); 22 | 23 | spec.test('passes without options', (ctx) => { 24 | ctx.true(stringLengthValidator()('hello')); 25 | }); 26 | 27 | spec.test('supports bytes length', (ctx) => { 28 | ctx.false(stringLengthValidator({ bytes: true, max: 3 })('ašč')); 29 | ctx.true(stringLengthValidator({ bytes: true, max: 6 })('ašč')); 30 | ctx.true(stringLengthValidator({ minOrEqual: 3 })('ašč')); 31 | ctx.true(stringLengthValidator({ maxOrEqual: 3 })('ašč')); 32 | }); 33 | 34 | export default spec; 35 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/upcase-string.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { upcaseStringValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(upcaseStringValidator()(true)); 8 | }); 9 | 10 | spec.test('fails when invalid', (ctx) => { 11 | ctx.false(upcaseStringValidator()('Hello')); 12 | }); 13 | 14 | spec.test('passes when value not present', (ctx) => { 15 | ctx.true(upcaseStringValidator()(undefined)); 16 | ctx.true(upcaseStringValidator()(null)); 17 | }); 18 | 19 | spec.test('passes when valid', (ctx) => { 20 | ctx.true(upcaseStringValidator()('HELLO')); 21 | }); 22 | 23 | export default spec; 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/tests/validators/uuid.test.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@hayspec/spec'; 2 | import { uuidValidator } from '../..'; 3 | 4 | const spec = new Spec(); 5 | 6 | spec.test('fails when not a string', (ctx) => { 7 | ctx.false(uuidValidator()(true)); 8 | }); 9 | 10 | spec.test('passes when value not present', (ctx) => { 11 | ctx.true(uuidValidator()(undefined)); 12 | ctx.true(uuidValidator()(null)); 13 | }); 14 | 15 | spec.test('passes for valid v1', (ctx) => { 16 | ctx.true(uuidValidator({ version: 1 })('857b3f0a-a777-11e5-bf7f-feff819cdc9f')); 17 | ctx.true(uuidValidator({ version: 1 })('857b4504-a777-11e5-bf7f-feff819cdc9f')); 18 | }); 19 | 20 | spec.test('passes for valid v2', (ctx) => { 21 | ctx.true(uuidValidator({ version: 2 })('a14e3bb3-d7a3-2ea8-9481-881eaf75fdc5')); 22 | ctx.true(uuidValidator({ version: 2 })('5a3c2348-6e2f-280e-aade-7dc8afdb18b9')); 23 | }); 24 | 25 | spec.test('passes for valid v3', (ctx) => { 26 | ctx.true(uuidValidator({ version: 3 })('49072879-c5c6-3b4e-9900-34e5df285522')); 27 | ctx.true(uuidValidator({ version: 3 })('5a3c2348-6e2f-380e-aade-7dc8afdb18b9')); 28 | }); 29 | 30 | spec.test('passes for valid v4', (ctx) => { 31 | ctx.true(uuidValidator({ version: 4 })('82ca85b8-7841-42f0-80d8-48bbe11a005b')); 32 | ctx.true(uuidValidator({ version: 4 })('58dbb3a5-a95a-4120-b4e0-483eea26ab74')); 33 | }); 34 | 35 | spec.test('passes for valid v5', (ctx) => { 36 | ctx.true(uuidValidator({ version: 5 })('482d11be-b03f-5ff3-b99d-9b6ceef18874')); 37 | ctx.true(uuidValidator({ version: 5 })('6a5b4d3f-02cf-5e2d-89d5-2f2163bb69f9')); 38 | }); 39 | 40 | export default spec; 41 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/absence.ts: -------------------------------------------------------------------------------- 1 | import { isPresent } from '@rawmodel/utils/dist/helpers/is-present'; 2 | 3 | /** 4 | * Returns a function for detecting empty values. 5 | */ 6 | export function absenceValidator() { 7 | return (value?: any) => { 8 | return !isPresent(value); 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/array-exclusion.ts: -------------------------------------------------------------------------------- 1 | import { arrayInclusionValidator } from './array-inclusion'; 2 | import { isPresent } from '@rawmodel/utils'; 3 | 4 | /** 5 | * Returns a function for detecting values that do not exist in the array. 6 | */ 7 | export function arrayExclusionValidator(options: { 8 | values?: any[]; 9 | } = {}) { 10 | return (value?: any[]) => { 11 | 12 | console.log( 13 | !arrayInclusionValidator(options)(value) 14 | ); 15 | 16 | return ( 17 | !isPresent(value) 18 | || !arrayInclusionValidator(options)(value) 19 | ); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/array-inclusion.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@rawmodel/utils/dist/helpers/is-array'; 2 | import { isPresent } from '@rawmodel/utils'; 3 | 4 | /** 5 | * Returns a function for detecting values that exist in the array. 6 | */ 7 | export function arrayInclusionValidator(options: { 8 | values?: any[]; 9 | } = {}) { 10 | return (value?: any[]) => { 11 | const { values } = { ...options }; 12 | 13 | if ( 14 | !isPresent(value) 15 | || !isArray(value) 16 | || !isArray(values) 17 | ) { 18 | return true; 19 | } 20 | 21 | return values.filter((e) => value.indexOf(e) !== -1).length === value.length; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/array-length.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@rawmodel/utils/dist/helpers/is-array'; 2 | import { isNumber } from '@rawmodel/utils/dist/helpers/is-number'; 3 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 4 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 5 | 6 | /** 7 | * Returns a function for detecting array size. 8 | */ 9 | export function arrayLengthValidator(options: { 10 | min?: number; 11 | minOrEqual?: number; 12 | max?: number; 13 | maxOrEqual?: number; 14 | } = {}) { 15 | return (value?: any) => { 16 | 17 | if (isUndefined(value) || isNull(value)) { 18 | return true; 19 | } else if (!isArray(value)) { 20 | return false; 21 | } 22 | 23 | const size = value.length; 24 | const { min, minOrEqual, max, maxOrEqual } = options; 25 | if (isNumber(min) && !(size > min)) { 26 | return false; 27 | } 28 | if (isNumber(minOrEqual) && !(size >= minOrEqual)) { 29 | return false; 30 | } 31 | if (isNumber(max) && !(size < max)) { 32 | return false; 33 | } 34 | if (isNumber(maxOrEqual) && !(size <= maxOrEqual)) { 35 | return false; 36 | } 37 | 38 | return true; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/base64.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/; 6 | 7 | /** 8 | * Returns a function for detecting base64 strings. 9 | */ 10 | export function base64Validator() { 11 | return (value?: any) => { 12 | return ( 13 | isUndefined(value) 14 | || isNull(value) 15 | || isString(value) && BASE64_REGEX.test(value) 16 | ); 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/bson-object-id.ts: -------------------------------------------------------------------------------- 1 | import { toString } from '@rawmodel/utils/dist/helpers/to-string'; 2 | import { isHex } from '@rawmodel/utils/dist/helpers/is-hex'; 3 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 4 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 5 | 6 | /** 7 | * Returns a function for detecting BSON ObjectId objects. 8 | */ 9 | export function bsonObjectIdValidator() { 10 | return (value?: any) => { 11 | 12 | if (isUndefined(value) || isNull(value)) { 13 | return true; 14 | } 15 | 16 | value = (toString(value) || '').replace(/\"/g, ''); 17 | return ( 18 | isHex(value) 19 | && value.length === 24 20 | ); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/date.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | const ISO8601_REGEX = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/; 6 | 7 | /** 8 | * Returns a function for detecting date values. 9 | */ 10 | export function dateValidator(recipe: { 11 | iso?: boolean; 12 | } = {}) { 13 | return (value?: any) => { 14 | 15 | if (isUndefined(value) || isNull(value)) { 16 | return true; 17 | } else if (!isString(value)) { 18 | return false; 19 | } 20 | 21 | const date = Date.parse(value); 22 | if (!date) { 23 | return false; 24 | } 25 | 26 | const { iso } = recipe; 27 | if (iso) { 28 | return ISO8601_REGEX.test(value); 29 | } 30 | 31 | return true; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/downcase-string.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting lower cased strings. 7 | */ 8 | export function downcaseStringValidator() { 9 | return (value?: any) => { 10 | return ( 11 | isUndefined(value) 12 | || isNull(value) 13 | || isString(value) && value === value.toLowerCase() 14 | ); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/eth-address.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting Ethereum address. 7 | */ 8 | export function ethAddressValidator() { 9 | return (value?: any) => { 10 | return ( 11 | isUndefined(value) 12 | || isNull(value) 13 | || isString(value) && /^0x[a-fA-F0-9]{40}$/i.test(value) 14 | ); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/exclusion.ts: -------------------------------------------------------------------------------- 1 | import { inclusionValidator } from './inclusion'; 2 | import { isPresent } from '@rawmodel/utils'; 3 | 4 | /** 5 | * Returns a function for detecting values that do not exist in the array. 6 | */ 7 | export function exclusionValidator(options: { 8 | values?: any[]; 9 | } = {}) { 10 | return (value?: any) => { 11 | return ( 12 | !isPresent(value) 13 | || !inclusionValidator(options)(value) 14 | ); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/fqdn.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting domain names. 7 | */ 8 | export function fqdnValidator(options: { 9 | requireTld?: boolean; 10 | allowUnderscores?: boolean; 11 | allowTrailingDot?: boolean; 12 | } = {}) { 13 | return (value?: any) => { 14 | 15 | const { requireTld = true, allowUnderscores = false, allowTrailingDot = false } = options; 16 | 17 | if (isUndefined(value) || isNull(value)) { 18 | return true; 19 | } else if (!isString(value)) { 20 | return false; 21 | } 22 | 23 | if (allowTrailingDot && value[value.length - 1] === '.') { 24 | value = value.substring(0, value.length - 1); 25 | } 26 | 27 | const parts = value.split('.'); 28 | 29 | if (requireTld) { 30 | const tld = parts.pop(); 31 | 32 | if (!parts.length || !/^([a-z\u00a1-\uffff]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) { 33 | return false; 34 | } 35 | } 36 | 37 | for (let part, i = 0; i < parts.length; i++) { 38 | part = parts[i]; 39 | 40 | if (allowUnderscores) { 41 | if (part.indexOf('__') >= 0) { 42 | return false; 43 | } else { 44 | part = part.replace(/_/g, ''); 45 | } 46 | } 47 | 48 | if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) { 49 | return false; 50 | } else if (/[\uff01-\uff5e]/.test(part)) { 51 | return false; // disallow full-width chars 52 | } else if (part[0] === '-' || part[part.length - 1] === '-') { 53 | return false; 54 | } 55 | } 56 | 57 | return true; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/hex-color.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting hexadecimal colors. 7 | */ 8 | export function hexColorValidator() { 9 | return (value?: any) => { 10 | return ( 11 | isUndefined(value) 12 | || isNull(value) 13 | || isString(value) && /^#?([0-9A-F]{3}|[0-9A-F]{6})$/i.test(value) 14 | ); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/hex.ts: -------------------------------------------------------------------------------- 1 | import { isHex } from '@rawmodel/utils/dist/helpers/is-hex'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting hexadecimal values. 7 | */ 8 | export function hexValidator() { 9 | return (value?: any) => ( 10 | isUndefined(value) 11 | || isNull(value) 12 | || isHex(value) 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/inclusion.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@rawmodel/utils/dist/helpers/is-array'; 2 | import { isPresent } from '@rawmodel/utils'; 3 | 4 | /** 5 | * Returns a function for detecting values that exist in the array. 6 | */ 7 | export function inclusionValidator(options: { 8 | values?: any[]; 9 | } = {}) { 10 | return (value?: any) => { 11 | const { values } = { ...options }; 12 | 13 | return ( 14 | !isPresent(value) 15 | || !isArray(values) 16 | || isArray(values) && values.indexOf(value) !== -1 17 | ); 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/json-string.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting JSON strings. 7 | */ 8 | export function jsonStringValidator() { 9 | return (value?: any) => { 10 | 11 | if (isUndefined(value) || isNull(value)) { 12 | return true; 13 | } else if (!isString(value)) { 14 | return false; 15 | } 16 | 17 | try { 18 | const obj = JSON.parse(value); 19 | return !!obj && typeof obj === 'object'; 20 | // eslint-disable-next-line no-empty 21 | } catch (e) {} 22 | 23 | return false; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/match.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting values based on regular expressions. 7 | */ 8 | export function matchValidator(options: { 9 | regexp?: RegExp; 10 | } = {}) { 11 | return (value?: any) => { 12 | 13 | if (isUndefined(value) || isNull(value)) { 14 | return true; 15 | } else if (!isString(value)) { 16 | return false; 17 | } 18 | 19 | const { regexp } = { ...options }; 20 | return regexp.test(value); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/number-size.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from '@rawmodel/utils'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting number size. 7 | */ 8 | export function numberSizeValidator(options: { 9 | min?: number; 10 | minOrEqual?: number; 11 | max?: number; 12 | maxOrEqual?: number; 13 | } = {}) { 14 | return (value?: any) => { 15 | 16 | if (isUndefined(value) || isNull(value)) { 17 | return true; 18 | } else if (!isNumber(value)) { 19 | return false; 20 | } 21 | 22 | const { min, minOrEqual, max, maxOrEqual } = options; 23 | if (isNumber(min) && !(value > min)) { 24 | return false; 25 | } 26 | if (isNumber(minOrEqual) && !(value >= minOrEqual)) { 27 | return false; 28 | } 29 | if (isNumber(max) && !(value < max)) { 30 | return false; 31 | } 32 | if (isNumber(maxOrEqual) && !(value <= maxOrEqual)) { 33 | return false; 34 | } 35 | 36 | return true; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/presence.ts: -------------------------------------------------------------------------------- 1 | import { isPresent } from '@rawmodel/utils/dist/helpers/is-present'; 2 | 3 | /** 4 | * Returns a function for detecting if the value exists. 5 | */ 6 | export function presenceValidator() { 7 | return (value?: any) => isPresent(value); 8 | } 9 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/string-exclusion.ts: -------------------------------------------------------------------------------- 1 | import { stringInclusionValidator } from './string-inclusion'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting words that do not exist in a string. 7 | */ 8 | export function stringExclusionValidator(options: { 9 | seed?: string; 10 | } = {}) { 11 | return (value?: any) => ( 12 | isUndefined(value) 13 | || isNull(value) 14 | || !stringInclusionValidator(options)(value) 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/string-inclusion.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { toString } from '@rawmodel/utils/dist/helpers/to-string'; 3 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 4 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 5 | 6 | /** 7 | * Returns a function for detecting words that exist in a string. 8 | */ 9 | export function stringInclusionValidator(options?: { seed?: string }) { 10 | return (value?: any) => { 11 | 12 | if (isUndefined(value) || isNull(value)) { 13 | return true; 14 | } else if (!isString(value)) { 15 | return false; 16 | } 17 | 18 | const { seed } = { ...options }; 19 | return value.indexOf(toString(seed)) >= 0; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/string-length.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isNumber } from '@rawmodel/utils/dist/helpers/is-number'; 3 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 4 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 5 | 6 | /** 7 | * Returns a function for detecting string length. 8 | */ 9 | export function stringLengthValidator(recipe: { 10 | bytes?: boolean; 11 | min?: number; 12 | minOrEqual?: number; 13 | max?: number; 14 | maxOrEqual?: number; 15 | } = {}) { 16 | return (value?: any) => { 17 | 18 | if (isUndefined(value) || isNull(value)) { 19 | return true; 20 | } else if (!isString(value)) { 21 | return false; 22 | } 23 | 24 | const { bytes = false, min, minOrEqual, max, maxOrEqual } = recipe; 25 | const len = bytes 26 | ? encodeURI(value).split(/%..|./).length - 1 27 | : value.length; 28 | 29 | if (isNumber(min) && !(len > min)) { 30 | return false; 31 | } else if (isNumber(minOrEqual) && !(len >= minOrEqual)) { 32 | return false; 33 | } else if (isNumber(max) && !(len < max)) { 34 | return false; 35 | } else if (isNumber(maxOrEqual) && !(len <= maxOrEqual)) { 36 | return false; 37 | } 38 | return true; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/upcase-string.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | /** 6 | * Returns a function for detecting uppercased string. 7 | */ 8 | export function upcaseStringValidator() { 9 | return (value?: any) => { 10 | return ( 11 | isUndefined(value) 12 | || isNull(value) 13 | || isString(value) && value === value.toUpperCase() 14 | ); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/src/validators/uuid.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@rawmodel/utils/dist/helpers/is-string'; 2 | import { isUndefined } from '@rawmodel/utils/dist/helpers/is-undefined'; 3 | import { isNull } from '@rawmodel/utils/dist/helpers/is-null'; 4 | 5 | const V1_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 6 | const V2_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[2][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 7 | const V3_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[3][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 8 | const V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 9 | const V5_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 10 | 11 | /** 12 | * Returns a function for detecting UUID values. 13 | */ 14 | export function uuidValidator(recipe: { 15 | version?: number; 16 | } = {}) { 17 | return (value?: any) => { 18 | 19 | if (isUndefined(value) || isNull(value)) { 20 | return true; 21 | } else if (!isString(value)) { 22 | return false; 23 | } 24 | 25 | const { version } = recipe; 26 | switch (version) { 27 | case 1: 28 | return V1_REGEX.test(value); 29 | case 2: 30 | return V2_REGEX.test(value); 31 | case 3: 32 | return V3_REGEX.test(value); 33 | case 4: 34 | return V4_REGEX.test(value); 35 | case 5: 36 | return V5_REGEX.test(value); 37 | default: 38 | return ( 39 | V1_REGEX.test(value) 40 | || V2_REGEX.test(value) 41 | || V3_REGEX.test(value) 42 | || V4_REGEX.test(value) 43 | || V5_REGEX.test(value) 44 | ); 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /packages/rawmodel-validators/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /rush.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", 3 | "rushVersion": "5.5.1", 4 | "npmVersion": "6.4.1", 5 | "nodeSupportedVersionRange": ">=11.0.0", 6 | "gitPolicy": {}, 7 | "repository": {}, 8 | "eventHooks": { 9 | "preRushInstall": [], 10 | "postRushInstall": [], 11 | "preRushBuild": [], 12 | "postRushBuild": [] 13 | }, 14 | "projects": [ 15 | { 16 | "packageName": "@rawmodel/core", 17 | "projectFolder": "packages/rawmodel-core", 18 | "versionPolicyName": "patchAll" 19 | }, 20 | { 21 | "packageName": "@rawmodel/handlers", 22 | "projectFolder": "packages/rawmodel-handlers", 23 | "versionPolicyName": "patchAll" 24 | }, 25 | { 26 | "packageName": "@rawmodel/parsers", 27 | "projectFolder": "packages/rawmodel-parsers", 28 | "versionPolicyName": "patchAll" 29 | }, 30 | { 31 | "packageName": "@rawmodel/schema", 32 | "projectFolder": "packages/rawmodel-schema", 33 | "versionPolicyName": "patchAll" 34 | }, 35 | { 36 | "packageName": "@rawmodel/utils", 37 | "projectFolder": "packages/rawmodel-utils", 38 | "versionPolicyName": "patchAll" 39 | }, 40 | { 41 | "packageName": "@rawmodel/validators", 42 | "projectFolder": "packages/rawmodel-validators", 43 | "versionPolicyName": "patchAll" 44 | } 45 | ] 46 | } 47 | --------------------------------------------------------------------------------