Skip to content

Commit

Permalink
Structure 2 (#130)
Browse files Browse the repository at this point in the history
* Bump major to alpha

* Move Node version to 10

* Replace Object.assign with spread

* Replace every var with let or const

* Migrate tests that run on Node to use Jest

* Update Node version on Travis

* Base on Node 8 instead of 10

* Change linter to accept jest tests

* Update joi without considering cases where lazy schema is needed

* Handle dynamic types validations with link + shared API

* Begin to refactor to a new internal structure

* Rename descriptors concept to definitions

* Implement initialization

* Implement coercion for non-array types

* Adjust tests to coercion without considering nested

* Implement coercion for array types

* Allow to subclass structures and inherit attributes

* Implement strict mode (missing validation)

* Implement validation to new core (#102)

* Implement validation

* Implement serialization (#101)

* Implement validation for nested types

* Implement clone to the new core (#103)

* Implement clone to the new core

* Make linter happy

* Increase coverage

* Refactors Descriptors to be a function instead of a class

* Improve function naming for better debugging

* Ensure that when reusing an attribute, it uses the new schema

* Reformat according to prettier

* Upgrade browser build (#105)

* Webpack setup and begin to setup tests

* Add electron to dev dependencies

* Improve Webpack output during tests

* Add browser tests to Travis

* Remove unecessary dependencies

* Update readme about browser and support

* Separate travis lifecycles

* Attempt to avoid hanging electron test

* Update coveralls

* Move to lerna (#106)

* Move current code to packages

* Share prettier config

* Add coveralls to root package

* Fix Coveralls script

* Add coverage to root package

* Create jest structure (#107)

* Begin to implement assertions

* Migrate boolean validation assertions to use jest-structure

* Assert no expected for valid/invalid matchers

* Assert attribute path is passed

* Add package to automatically add assertions to jest

* Begin to write tests

* Add tests for validating error messages

* Reorganize and begin to write toHaveInvalidAttributes

* Implement toHaveInvalidAttributes and cover with tests

* Rename auto.js to extend-expect.js

* Refactor checking of path presence and usage hint

* Refactor and remove hint from validity check of toHaveInvalidAttributes

* Remove hint from validity check of toHaveInvalidAttribute

* Refactor checking of attribute validity

* Refactor usage error and remove hint for non-usage-related errors

* Replace usage of assertValid with expect().toBeValid()

* Replace validitationMatchers with jest-structure in array specs

* Migrate whole structure spec to use jest-structure

* Rename validity assertions to contain 'structure' in the name

* Fix coverage script

* Add tests for when using arrayContaining with jest-structure

* Add readme

* Allow defaulting when null and not nullable (#108)

* Fallback to default when value is null and not nullable

* Update changelog

* Update docs about nullable attributes

* Refactor name of dynamic default instance variable

* Update changelog (#109)

* Allow to pass custom identifier for dynamic types (#111)

* Allow to pass custom identifier for dynamic types

* Improve documentation wording

* Improve changelog wording

* Apply suggestions from code review

Co-Authored-By: Leonardo Negreiros de Oliveira <negreirosleo12@gmail.com>

* Update docs/schema-concept/circular-references-and-dynamic-types.md

Co-Authored-By: Leonardo Negreiros de Oliveira <negreirosleo12@gmail.com>

* Allow to declare custom setter and getter (#112)

* Allow to use custom setters and getters to attributes

* Add docs about custom getters and setters

* Allow to inherit custom accessors

* reduce function complexity

* Add docs about custom accessors and inheritance

* update joi (#114)

* Add alpha patch (#115)

* Make versioning consistent (#116)

* Update dependencies node and generate build (#117)

* Update dependencies and Node

* Generate build

* Remove Node 8 from Travis build

* Make linter happy

* Add missing symlinks (#118)

* Invert symlinks (#119)

* Invert symlinks

* Bump alpha patch

* Gix Gitbook refs (#120)

* Gix Gitbook refs

* New organization

* Remove introduction duplicate link

* Prepare to release new alpha

* Gitbook testing docs (#124)

* Add testing to docs and prettify md files

* Fix formatting

* Publish only src folder for jest-structure (#125)

* Update Joi links (#126)

* Allow to disable coercion (#127)

* Update paths and messages of errors in docs (#128)

* Improve docs (#129)

* Improve docs

* Improve verbiage

* Update build

* Bump version to 2.0.0

* Point links to master docs

* Update changelog and add migration guide

* Point CodeClimate to use eslint 6

* Use normal quotes where needed

Co-authored-by: Leonardo Negreiros de Oliveira <negreirosleo12@gmail.com>
  • Loading branch information
talyssonoc and negreirosleo committed Mar 31, 2020
1 parent b48d1ba commit 3f527c1
Show file tree
Hide file tree
Showing 178 changed files with 15,349 additions and 7,322 deletions.
3 changes: 0 additions & 3 deletions .babelrc

This file was deleted.

10 changes: 5 additions & 5 deletions .codeclimate.yml
@@ -1,13 +1,13 @@
engines:
eslint:
enabled: true
channel: "eslint-3"
channel: 'eslint-6'

ratings:
paths:
- src/**
- packages/structure/src/**

exclude_paths:
- benchmark/**/*
- dist/**/*
- test/**/*
- benchmark/**/*
- packages/structure/dist/**/*
- packages/structure/test/**/*
18 changes: 13 additions & 5 deletions .eslintrc
Expand Up @@ -2,10 +2,13 @@
"env": {
"node": true,
"es6": true,
"mocha": true
"jest/globals": true
},
"extends": ["eslint:recommended", "plugin:jest/recommended", "prettier"],
"plugins": ["jest"],
"parserOptions": {
"ecmaVersion": 2018
},
"extends": ["eslint:recommended", "prettier"],
"plugins": ["mocha"],
"rules": {
"comma-spacing": ["error", { "before": false, "after": true }],
"complexity": ["error", 4],
Expand All @@ -16,8 +19,13 @@
"always",
{ "avoidQuotes": true, "avoidExplicitReturnArrows": true }
],
"mocha/no-exclusive-tests": "error",
"mocha/no-skipped-tests": "error",
"jest/no-disabled-tests": "warn",
"jest/no-focused-tests": "error",
"jest/no-identical-title": "error",
"jest/prefer-to-have-length": "warn",
"jest/valid-expect": "error",
"jest/no-test-callback": "off",
"jest/no-try-expect": "off",
"quotes": ["error", "single", { "avoidEscape": true }],
"semi": ["error", "always"]
}
Expand Down
2 changes: 1 addition & 1 deletion .gitbook.yaml
@@ -1,3 +1,3 @@
structure:
readme: README.md
readme: packages/structure/README.md
summary: docs/SUMMARY.md
1 change: 1 addition & 0 deletions .nvmrc
@@ -0,0 +1 @@
10.13.0
4 changes: 1 addition & 3 deletions .prettierignore
@@ -1,3 +1 @@
/dist
/README.md
/CHANGELOG.md
dist
File renamed without changes.
29 changes: 22 additions & 7 deletions .travis.yml
@@ -1,10 +1,25 @@
language: node_js
node_js:
- "node"
- "6.1"
- "6.0"
- "8.0"
- '10'
- '11'
- '12'
- 'node'

addons:
apt:
packages:
- xvfb

install:
- yarn
- export DISPLAY=':99.0'
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &

before_script:
- yarn test:browser:build

script:
- npm run lint
- npm test
- npm run coveralls
- yarn lint
- yarn test
- yarn test:browser:run
- yarn coveralls
111 changes: 100 additions & 11 deletions CHANGELOG.md
@@ -1,40 +1,129 @@
## 2.0.0 - 2020-03-31

Refactors:

- The whole part of schemas and attribute definitions was refactored
- Tests are now run by Jest (and Electron for browser tests)
- Prettier was added
- Move to mono-repo

Enhancements

- Implement jest-structure assertions
- It's possible to set custom getters e setters directly in the structure class
- Allows to disable coercion

Breaking changes:

- Joi is updated to v16
- Attribute path in validation _errors_ is an array instead of a string
- Attribute path in validation _messages_ contains the whole path joined by '.'
- The name used for the dynamic import should aways be the same as the name of its type or else a custom identifier must be used
- Non-nullable attributes with value null will use default value the same way undefined does
- Structure classes now have two methods to generically set and get the value of the attributes, `.get(attributeName)` and `.set(attributeName, attributeValue)`
- Minimum Node version is now 10

Docs:

- Rename the term `type descriptor` to `attribute definition` in the docs and in the code
- Reorganize and add more specific pages to docs

## 2.0.0-alpha.4 - 2020-03-21

- Publish only src folder for jest-structure

## 2.0.0-alpha.3 - 2020-03-20

- Reorganize md files

## 2.0.0-alpha.2 - 2020-03-19

- Invert symlinks

## 2.0.0-alpha.1 - 2020-03-19

- Add symlinks to md files to packages/structure

## 2.0.0-alpha.0 - 2020-03-19

Refactors:

- The whole part of schemas and attribute definitions was refactored
- Tests are now run by Jest (and Electron for browser tests)
- Prettier was added
- Move to mono-repo

Enhancements

- Implement jest-structure assertions
- It's possible to set custom getters e setters directly in the structure class

Breaking changes:

- Joi is updated to v16
- Attribute path in validation _errors_ is an array instead of a string
- Attribute path in validation _messages_ contains the whole path joined by '.'
- The name used for the dynamic import should aways be the same as the name of its type or else a custom identifier must be used
- Non-nullable attributes with value null will use default value the same way undefined does
- Structure classes now have two methods to generically set and get the value of the attributes, `.get(attributeName)` and `.set(attributeName, attributeValue)`
- Minimum Node version is now 10

## 1.8.0 - 2019-09-16

Enhancements:
* Add `unique` validation to arrays

- Add `unique` validation to arrays

## 1.7.0 - 2019-09-14

Enhancements:
* Add method to clone structures

- Add method to clone structures

## 1.6.0 - 2019-08-27

Enhancements:
* Allow custom error class to static mode

- Allow custom error class to static mode

## 1.5.0 - 2019-07-08

Enhancements:
* Add `buildStrict` static method

- Add `buildStrict` static method

## 1.4.0 - 2019-03-26

Enhancements:
* Add `nullable` option

- Add `nullable` option

## 1.3.2 - 2019-03-22

Fix:
* The actual instance is passed to the dynamic defaults

- The actual instance is passed to the dynamic defaults

## 1.3.0 - 2018-03-23

Enhancements:
* When using default function to initialize attributes you can now refer to another attribute values to compose value

- When using default function to initialize attributes you can now refer to another attribute values to compose value

## 1.2.0 - 2017-02-01

Features:
* Allow circular reference on type definitions ([@talyssonoc](https://github.com/talyssonoc/structure/pull/30))

- Allow circular reference on type definitions ([@talyssonoc](https://github.com/talyssonoc/structure/pull/30))

Enhancements:
* Make validation faster ([@talyssonoc](https://github.com/talyssonoc/structure/pull/28))

- Make validation faster ([@talyssonoc](https://github.com/talyssonoc/structure/pull/28))

Dependencies update:
* Update joi from 9.2.0 to 10.2.0 ([@talyssonoc](https://github.com/talyssonoc/structure/pull/26))

- Update joi from 9.2.0 to 10.2.0 ([@talyssonoc](https://github.com/talyssonoc/structure/pull/26))

## 1.1.0 - 2017-01-17
* Added static method `validate()` to structures ([@talyssonoc](https://github.com/talyssonoc/structure/pull/25))

- Added static method `validate()` to structures ([@talyssonoc](https://github.com/talyssonoc/structure/pull/25))
75 changes: 15 additions & 60 deletions README.md
Expand Up @@ -2,33 +2,16 @@

## A simple schema/attributes library built on top of modern JavaScript

[![npm](https://img.shields.io/npm/v/structure.svg?style=flat)](https://www.npmjs.com/package/structure) [![Build Status](https://travis-ci.org/talyssonoc/structure.svg?branch=master)](https://travis-ci.org/talyssonoc/structure) [![Coverage Status](https://coveralls.io/repos/github/talyssonoc/structure/badge.svg?branch=master)](https://coveralls.io/github/talyssonoc/structure?branch=master) [![Code Climate](https://codeclimate.com/github/talyssonoc/structure/badges/gpa.svg)](https://codeclimate.com/github/talyssonoc/structure) [![JS.ORG](https://img.shields.io/badge/js.org-structure-ffb400.svg?style=flat)](https://js.org/)
---
Structure provides a simple interface which allows you to add attributes to your ES6 classes based on a schema, with validations and type coercion.
Structure provides a simple interface which allows you to add attributes to your classes based on a schema, with validations and type coercion.

## Use cases
## Packages

You can use Structure for a lot of different cases, including:
- [Structure](packages/structure)
- [jest-structure](packages/jest-structure)

- Domain entities and value objects
- Model business rules
- Validation and coercion of request data
- Map pure objects and JSON to your application classes
- Add attributes to classes that you can't change the class hierarchy
## [Documentation](https://structure.js.org/)

Structure was inspired by Ruby's [Virtus](https://github.com/solnic/virtus).

What Structure is __not__:

- It's not a database abstraction
- It's not a MVC framework (but it can be used to domain entities)
- It's not an attempt to simulate classic inheritance in JavaScript

## Getting started

`npm install --save structure`

## Usage
## Example Structure usage

For each attribute on your schema, a getter and a setter will be created into the given class. It'll also auto-assign those attributes passed to the constructor.

Expand All @@ -39,53 +22,25 @@ const User = attributes({
name: String,
age: {
type: Number,
default: 18
default: 18,
},
birthday: Date
})(class User {
greet() {
return `Hello ${this.name}`;
birthday: Date,
})(
class User {
greet() {
return `Hello ${this.name}`;
}
}
});

/* The attributes "wraps" the Class, still providing access to its methods: */
);

const user = new User({
name: 'John Foo'
name: 'John Foo',
});

user.name; // 'John Foo'
user.greet(); // 'Hello John Foo'
```

## Support and compatibility

Structure is built on top of modern JavaScript, using new features like [Proxy](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy), [Reflect](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Reflect) and [Symbol](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol). That being so, there are some things regarding compatibility you should consider when using Structure.

### Node

Node only implemented all the used features on version 6, so for using Structure for a backend application you'll need Node 6 or later.

### Browser

Not all major browsers implemented the used features so you'll need to transpile the code for using it. For browser usage we have the [UMD version](https://github.com/talyssonoc/structure/blob/master/dist/structure.js) bundled with Webpack. We don't bundle Structure with its dependencies so you'll have to provide it with your module bundler. It's recommended to replace joi with [joi-browser](https://www.npmjs.com/package/joi-browser) when using it on the front-end, here's how we run our test suite on the browser regarding [bundling](https://github.com/talyssonoc/structure/blob/master/test/karma.conf.js#L3-L11) and [polyfill of features](https://github.com/talyssonoc/structure/blob/master/test/browserSetup.js#L1-L2).

Be aware that not the whole test suite will pass on browsers, there are some cases that can't be simulated through polyfilling, like extending Array or having a non-structure class extending a structure class. You can setup the project on your computer and run npm run test:browser to see how it'll work.

Right now 95.5% of the tests will pass on Chrome 55, and 95% will pass on Firefox 45. We intend to make it support older versions using polyfills in the next releases.

## BattleCry generators

There are configurable [BattleCry](https://github.com/pedsmoreira/battlecry) generators ready to be downloaded and help scaffolding schema:

```sh
npm install -g battlecry
cry download generator talyssonoc/structure
cry g schema user name age:int:required cars:string[] favoriteBook:book friends:user[]:default :updateAge
```

Run `cry --help` to check more info about the generators available;

## [Contributing](contributing.md)

## [LICENSE](license.md)
2 changes: 1 addition & 1 deletion benchmark/benchmark.js
Expand Up @@ -2,7 +2,7 @@ const Benchmark = require('benchmark');
const suites = require('./suites');

suites.forEach((suiteData) => {
var suite = new Benchmark.Suite(suiteData.name);
let suite = new Benchmark.Suite(suiteData.name);

suite = suiteData.cases.reduce((s, c) => {
return s.add(c.name, c.fn);
Expand Down
4 changes: 2 additions & 2 deletions benchmark/coercion.bm.js
@@ -1,4 +1,4 @@
const { attributes } = require('../src');
const { attributes } = require('../packages/structure/src');

const Book = attributes({
year: Number
Expand Down Expand Up @@ -26,7 +26,7 @@ const User = attributes({
}
})(class User { });

const CircularUser = require('../test/fixtures/CircularUser');
const CircularUser = require('../packages/structure/test/fixtures/CircularUser');

exports.name = 'Coercion';

Expand Down
6 changes: 3 additions & 3 deletions benchmark/instantiation.bm.js
@@ -1,4 +1,4 @@
const { attributes } = require('../src');
const { attributes } = require('../packages/structure/src');

const User = attributes({
name: String,
Expand All @@ -17,8 +17,8 @@ const Product = attributes({
}
})(class Product { });

const CircularUser = require('../test/fixtures/CircularUser');
const CircularBook = require('../test/fixtures/CircularBook');
const CircularUser = require('../packages/structure/test/fixtures/CircularUser');
const CircularBook = require('../packages/structure/test/fixtures/CircularBook');

exports.name = 'Instantiation';

Expand Down
2 changes: 1 addition & 1 deletion benchmark/updating.bm.js
@@ -1,4 +1,4 @@
const { attributes } = require('../src');
const { attributes } = require('../packages/structure/src');

const Book = attributes({
name: String
Expand Down
2 changes: 1 addition & 1 deletion benchmark/validation.bm.js
@@ -1,4 +1,4 @@
const { attributes } = require('../src');
const { attributes } = require('../packages/structure/src');

const Order = attributes({
createdAt: Date,
Expand Down

0 comments on commit 3f527c1

Please sign in to comment.